diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..3191e885 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at https://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.bat] +end_of_line = crlf + diff --git a/.gitattributes b/.gitattributes index 83517436..307be399 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,8 @@ +# Define the line ending behavior of the different file extensions # Set the default behavior, in case people don't have core.autocrlf set. -* eol=lf -* text=auto +* text text=auto eol=lf + +*.php diff=php # Denote all files that are truly binary and should not be modified. *.png binary @@ -17,15 +19,18 @@ *.mo binary *.pdf binary *.xsd binary -*.ts binary *.exe binary # Remove files for archives generated using `git archive` -codeception.yml export-ignore dependency.json export-ignore +phpstan.json export-ignore +phpstan.neon export-ignore +psalm-report.json export-ignore linguist-generated=true +tooling.yml export-ignore .coveralls.yml export-ignore .travis.yml export-ignore .editorconfig export-ignore .gitattributes export-ignore .gitignore export-ignore -tooling.yml export-ignore +architecture-baseline.json export-ignore +.github/ export-ignore diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..01031cea --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +## PR Description +Add a meaningful description here that will let us know what you want to fix with this PR or what functionality you want to add. + +## Steps before you submit a PR +- Please add tests for the code you add if it's possible. +- Please check out our contribution guide: https://docs.spryker.com/docs/dg/dev/code-contribution-guide.html +- Add a `contribution-license-agreement.txt` file with the following content: +`I hereby agree to Spryker\'s Contribution License Agreement in https://github.com/spryker/development/blob/HASH_OF_COMMIT_YOU_ARE_BASING_YOUR_BRANCH_FROM_MASTER_BRANCH/CONTRIBUTING.md.` + +This is a mandatory step to make sure you are aware of the license agreement and agree to it. `HASH_OF_COMMIT_YOU_ARE_BASING_YOUR_BRANCH_FROM_MASTER_BRANCH` is a hash of the commit you are basing your branch from the master branch. You can take it from commits list of master branch before you submit a PR. + +## Checklist +- [x] I agree with the Code Contribution License Agreement in CONTRIBUTING.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..5d6b48fd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +name: CI + +on: + push: + branches: + - 'master' + pull_request: + workflow_dispatch: + +jobs: + validation: + name: Validation + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: mbstring, intl, bcmath + coverage: none + + - name: Composer Install + run: composer install --prefer-dist --no-interaction --profile + + - name: Run validation + run: composer validate + + - name: Syntax check + run: find ./src -path src -prune -o -type f -name '*.php' -print0 | xargs -0 -n1 -P4 php -l -n | (! grep -v "No syntax errors detected" ) + + lowest: + name: Prefer Lowest + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: mbstring, intl, bcmath + coverage: none + + - name: Composer Install + run: composer install --prefer-dist --no-interaction --profile + + - name: Composer Update + run: composer update --prefer-lowest --prefer-dist --no-interaction --profile -vvv diff --git a/.gitignore b/.gitignore index 0d27ebd1..58b3e11f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,36 @@ -# IDEs -/.idea -/.project -/nbproject -/.buildpath -/.settings +# IDE +.idea/ +.project/ +nbproject/ +.buildpath/ +.settings/ *.sublime-* + +# OS +.DS_Store *.AppleDouble *.AppleDB *.AppleDesktop -# OS -.DS_Store +# grunt stuff +.grunt +.sass-cache +/node_modules/ + +# tooling +vendor/ +composer.lock +.phpunit.result.cache + +# built client resources +src/*/Zed/*/Static/Public +src/*/Zed/*/Static/Assets/sprite -/vendor -/composer.lock +# Propel classes +src/*/Zed/*/Persistence/Propel/Base/* +src/*/Zed/*/Persistence/Propel/Map/* -/tests/_output/* -!/tests/_output/.gitkeep +# tests +tests/**/_generated/ +tests/_output/* +!tests/_output/.gitkeep diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0d7fcc78..00000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: php -dist: trusty - -php: - - 7.1 - -cache: - directories: - - vendor - - $HOME/.composer/cache - -env: - global: - - APPLICATION_ENV=development - - APPLICATION_STORE=DE - -install: - - composer install --no-interaction --prefer-dist - -script: - - vendor/bin/phpcs src --standard=vendor/spryker/code-sniffer/Spryker/ruleset.xml - - vendor/bin/codecept run --env isolated --coverage-xml - -after_success: - - vendor/bin/coveralls -vvv - -notifications: - email: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5eff362d..6a2d4c07 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,46 +1,69 @@ -CODE CONTRIBUTION LICENSE AGREEMENT - -BY DISPLAYING, PUBLISHING, UPLOADING OR PROMOTING (COLLECTIVELY, “POSTING”) SOURCE CODE (“SOURCE CODE”) -TO SPRYKER SYSTEMS GMBH, REGISTERED WITH THE COMMERCIAL REGISTER OF THE LOWER COURT OF HAMBURG UNDER -HRB 134310 (“WE”, “US” OR ”SPRYKER”), YOU AGREE TO THIS CODE CONTRIBUTION LICENSE AGREEMENT (THE “AGREEMENT”). - -You grant us and our affiliates an irrevocable, perpetual, worldwide, royalty-free, non-exclusive, unrestricted -license and right to use, reproduce and store, disseminate and otherwise exploit, modify, delete from, add to, -create derivative works of, publicly perform, publicly display, reproduce, exchange parts of Source Code or combine them with -other Source Code, use in data networks and distribute with or without consideration and without limitations as to the -number of items via all distribution channels (and to sublicense the foregoing rights through multiple tiers of licensees) -of such Source Code and any other copyright protected material for any reason and in connection with advertising and -promoting our software and/or our products in any media formats and through any channels now existing or developed in -the future. The transfer and assignment of rights covers any usage and exploitation rights for any unknown types of use -as well as with regard to any known types of use the right to unrestrictedly make publicly available and publish, -irrespective of the medium including any editions and versions and grant simple or exclusive usage, exploitation or -adaptation rights to third parties. - -Spryker may reject, refuse to post or delete any Source Code for any or no reason, including, without limitation. - -From time to time, we may remove the Source Code permanently or temporarily, provided that even if we do remove such -Source Code, we shall have no obligation to cease our other uses of the Source Code as permitted above. - -You agree to be fully responsible for and to pay any and all royalties, fees, and any other monies owing any person or -entity by reason of any Source Code posted by you. - -Spryker respects the intellectual property of others, and requires that you do the same. Your postings and the Source Code -must not infringe any copyright, patent, trademark, trade secret or other proprietary rights or other rights of any person -or entity and you may not upload, embed, post, email, transmit or otherwise make available Source Code, software or any other -material that that infringes such rights. - -YOU GUARANTEE THAT: (I) YOU OWN THE SOURCE CODE POSTED BY YOU OR OTHERWISE HAVE THE RIGHT TO GRANT THE LICENSES AND RIGHTS -SET FORTH ABOVE, AND (II) THE POSTING OF YOUR SOURCE CODE DOES NOT VIOLATE THE PRIVACY RIGHTS, PUBLICITY RIGHTS, CONTRACT RIGHTS, -INTELLECTUAL PROPERTY OR ANY OTHER RIGHTS OF ANY PERSON OR ENTITY OR ANY APPLICABLE LAW. - -YOU AGREE TO INDEMNIFY AND HOLD SPRYKER, ITS SUBSIDIARIES, AND AFFILIATES, AND THEIR RESPECTIVE OFFICERS, AGENTS, PARTNERS -AND EMPLOYEES, HARMLESS FROM ANY LOSS, LIABILITY, COST, EXPENSE, CLAIM OR DEMAND, INCLUDING WITHOUT LIMITATION, REASONABLE -ATTORNEYS’ FEES, DUE OR RELATING TO OR ARISING OUT OF THE USE OF YOUR SOURCE CODE IN VIOLATION OF THIS AGREEMENT AND/OR -ARISING FROM A BREACH OF ANY TERMS OF THIS AGREEMENT AND/OR ANY BREACH OF YOUR REPRESENTATIONS AND WARRANTIES SET FORTH IN -THIS AGREEMENT AND/OR ARISING OUT OF OR RELATING TO ANY SOURCE CODE THAT YOU POST. - -This Agreement shall be governed by the laws of Germany to the exclusion of IPR (International Law) and the United Nations Convention -on Contracts for the International Sale of Goods (CISG). The parties consent to the jurisdiction of the courts in Berlin (Germany). - -This Agreement constitutes the entire agreement between you and us concerning Spryker’s use of the Source Code. This Agreement -supersedes any prior verbal understanding between the parties. This Agreement may be amended only in a writing signed by an authorized officer of Spryker. +SPRYKER - CONTRIBUTION AGREEMENT FOR PLATFORM CONTRIBUTIONS + +Spryker Systems GmbH, Heidestraße 9-10, 10557 Berlin, Germany (“Spryker”), and its affiliates invite you to contribute +to Spryker’s Software, including but not limited to with bug fixes, enhancements, additions or features +(each a “Platform Contribution”). For the purposes of this Agreement, the “Software” includes any software, +which is owned and made available by Spryker. Contributions can consist of source code, documentation and/or other +code-related elements. + +BY DISPLAYING, PUBLISHING, UPLOADING, PROMOTING OR OTHERWISE PROVIDING A PLATFORM CONTRIBUTION TO SPRYKER +(COLLECTIVELY, “SUBMITTING”), YOU AGREE TO THIS CONTRIBUTION AGREEMENT FOR PLATFORM CONTRIBUTIONS (THE “AGREEMENT”). + +Spryker grants you the right to use the Software for the purpose of developing and submitting Platform Contributions +to the Software and/or Spryker’s documentation subject to your compliance with this Agreement. +Under the license granted in this Agreement, you must not (i) use the Software to set up a production live system; +(ii) copy any part of the Software except to develop and provide a Platform Contribution or make one copy for back-up +purposes; (iii) distribute, disclose, market, rent, lease, or transfer the Software or act as a service bureau with +respect to the Software; (iv) export the Software or install it in multiple locations; (v) disclose any confidential +information provided by Spryker; (vi) modify or make derivative works of the Software beyond what you will submit to +Spryker as Platform Contribution; or (vii) allow others to make or obtain copies of the Software. + +You grant Spryker and its affiliates an irrevocable, perpetual, worldwide, royalty-free, non-exclusive, +unrestricted license and right to use, including to reproduce and store, disseminate and otherwise exploit, modify, +delete from, add to, create derivative works of, publicly perform, publicly display, reproduce, exchange parts +of a Platform Contribution or combine them with other code, use in data networks and distribute with or without +consideration and without limitations as to the number of items via all distribution channels (and to sublicense +the foregoing rights through multiple tiers of licensees) such Platform Contribution and any other copyright +protected material for any reason and in connection with advertising and promoting our software and/or Spryker’s +products in any media formats and through any channels now existing or developed in the future. +The granting of these rights covers any usage and exploitation rights for any unknown types of use as well as +with regard to any known types of use the right to unrestrictedly make publicly available and publish, +irrespective of the medium including any editions and versions and grant simple or exclusive usage, +exploitation or adaptation rights to third parties. + +Spryker may reject, refuse to post or delete any Platform Contribution for any or no reason, including, +without limitation. Spryker may or may not mention your name when publishing the Platform Contribution. +From time to time, Spryker may remove the Platform Contribution permanently or temporarily, provided that even +if Spryker does remove such Platform Contribution, Spryker shall have no obligation to cease its other uses of +the Platform Contribution as permitted above. +Spryker respects the intellectual property of others, and requires that you do the same. Your Platform Contributions +must not infringe any copyright, patent, trademark, trade secret or other proprietary rights or other rights of any +person or entity and you may not upload, embed, post, email, transmit or otherwise make available a Platform Contribution +or any other material that infringes such rights. +If you are submitting a Platform Contribution that includes licensed rights, you will inform Spryker of the name of +such third-party licensor, the third-party license as such and any restrictions you are aware of. +If you are submitting a Platform Contribution that was developed by you in the course of your work for your employer +or as a contractor, vendor or agent for another principal, you are responsible for obtaining permission from your +employer or such other principal. +You will not include a Platform Contribution containing code governed by a license with copyleft effect. You agree +to be fully responsible for and to pay any and all royalties, fees, and any other monies owed to any person or +entity for any rights in a Platform Contribution submitted by you. +YOU REPRESENT AND WARRANT THAT: (I) YOU OWN THE PLATFORM CONTRIBUTION POSTED BY YOU OR OTHERWISE ARE ENTITLED TO +GRANT THE LICENSES AND RIGHTS SET FORTH ABOVE, INCLUDING WHERE NECESSARY HAVE OBTAINED YOUR EMPLOYER’S OR OTHER +PRINCIPAL’S PERMISSION, AND (II) THE SUBMISSION OF YOUR PLATFORM CONTRIBUTION DOES NOT VIOLATE THE PRIVACY RIGHTS, +PUBLICITY RIGHTS, CONTRACT RIGHTS, INTELLECTUAL PROPERTY OR ANY OTHER RIGHTS OF ANY PERSON OR ENTITY OR ANY +APPLICABLE LAW. + +YOU AGREE TO INDEMNIFY AND HOLD SPRYKER AND ITS AFFILIATES, AND THEIR RESPECTIVE OFFICERS, AGENTS, PARTNERS AND EMPLOYEES, +HARMLESS FROM ANY LOSS, LIABILITY, COST, EXPENSE, CLAIM, OR DEMAND, INCLUDING WITHOUT LIMITATION, REASONABLE ATTORNEYS’ FEES, +DUE OR RELATING TO OR ARISING OUT OF THE USE OF THE YOUR PLATFORM CONTRIBUTION IN VIOLATION OF THIS AGREEMENT AND/OR +ARISING FROM A BREACH OF ANY TERMS OF THIS AGREEMENT AND/OR ANY BREACH OF YOUR REPRESENTATIONS AND WARRANTIES SET +FORTH IN THIS AGREEMENT AND/OR ARISING OUT OF OR RELATING TO ANY PLATFORM CONTRIBUTION THAT YOU SUBMIT. + +This Agreement is governed by the laws of Germany to the exclusion of its conflict of laws provisions and +the United Nations Convention on Contracts for the International Sale of Goods (CISG). The parties consent to the +jurisdiction of the courts in Berlin (Germany). + +This Agreement constitutes the entire agreement between the parties concerning the Platform Contributions submitted +by you. This Agreement supersedes any prior verbal understanding between the parties on the matter. This Agreement +may be amended only in a writing signed by an authorized officer of Spryker. diff --git a/LICENSE b/LICENSE index d376fd6f..38123b96 100644 --- a/LICENSE +++ b/LICENSE @@ -1,40 +1,27 @@ -SPRYKER SYSTEMS GMBH EVALUATION LICENSE AGREEMENT - -SPRYKER SYSTEMS GMBH, REGISTERED WITH THE COMMERCIAL REGISTER OF THE LOWER COURT OF HAMBURG UNDER HRB 134310 -(“WE” OR ”SPRYKER”)GRANTS YOU (THE “LICENSEE”) THE RIGHT TO USE THE SOFTWARE (AS DEFINED BELOW) -UNDER THE PROVISIONS OF THIS EVALUATION LICENSE AGREEMENT (THE “AGREEMENT”). - -The “Software” includes any software owned and distributed by Spryker under this Agreement. The Software -contains elements of open source components, to which different license terms apply respectively. -These open source components are needed to be installed separately. - -Spryker grants to Licensee, during the 45-calendar-day period (the “Evaluation Period”) following the download of the Software, -the nontransferable, nonexclusive limited, free of charge license to permit Licensee’s employees to internally use the Software -to test and evaluate the Software in connection with potentially purchasing non-evaluation licenses to the Software. - -Licensee shall not (i) use the Software to set up a productive live system, for development purposes or any other purposes apart -from evaluating the Software; (ii) copy any part of the Software except to make one copy for back-up purposes; (iii) distribute, -disclose, market, rent, lease, or transfer the Software or act as a service bureau with respect to the Software; (iv) export the -Software or install it in multiple locations; (v) disclose any confidential information provided by Spryker; (vi) modify or make -derivative works of the Software; or (vii) allow others to make or obtain copies of the Software. - -THE SOFTWARE IS PROVIDED “AS-IS” AND WITHOUT WARRANTY OF ANY KIND. SPRYKER DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING -BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, TITLE, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. SPRYKER WILL NOT -BE LIABLE FOR ANY DAMAGES ASSOCIATED WITH THE SOFTWARE, INCLUDING WITHOUT LIMITATION ORDINARY, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL -DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO DAMAGES RELATING TO LOST DATA OR LOST PROFITS, EVEN IF SPRYKER HAS BEEN ADVISED OF -THE POSSIBILITY OF SUCH DAMAGES. - -Licensee's license to use the Software shall terminate on the earlier of (i) the expiration of the Evaluation Period, or (ii) the date -both parties enter into a definitive agreement for the provision by Spryker to Licensee of a non-evaluation license to the Software. -Upon termination of the license as provided above, Licensee shall promptly destroy the Software and any back-up copy of the Software -made during the Evaluation Period if Spryker and the Licensee have not agreed a non-evaluation license to the Software. - -This Agreement shall be governed by the laws of Germany to the exclusion of IPR (International Law) and the United Nations Convention -on Contracts for the International Sale of Goods (CISG). The parties consent to the jurisdiction of the courts in Berlin (Germany). - -This Agreement is not assignable or transferable by Licensee and any attempt to do so is null and void. - -This Agreement constitutes the entire agreement between the parties concerning Licensee’s use of the Software. This Agreement supersedes -any prior verbal understanding between the parties and any Licensee purchase order or other ordering document, regardless of whether such -document is received by Spryker before or after execution of this Agreement. This Agreement may be amended only in a writing signed by -an authorized officer of Spryker. +SPRYKER - LICENSE AGREEMENT FOR EVALUATION OF AND EARLY ACCESS TO SOFTWARE + +SPRYKER SYSTEMS GMBH, HEIDESTRASSE 9-10, 10557 BERLIN, GERMANY (“WE” OR ”SPRYKER”) GRANTS YOU (“LICENSEE”) THE RIGHT TO USE THE SOFTWARE (AS DEFINED BELOW) UNDER THE PROVISIONS OF THIS LICENSE AGREEMENT FOR EVALUATION AND EARLY ACCESS (THE “AGREEMENT”). + +For the purposes of this Agreement, the “Software” includes any software, which is owned and made available by Spryker (i) for evaluation purposes or (ii) as part of Spryker’s early access program under this Agreement. In case Licensee has a dedicated paid license agreement with Spryker on a part of the Software only, this Agreement still applies to all other parts of the Software not paid for and/or covered by such license agreement. + +Spryker grants to Licensee, (i) during the 45-calendar-day period (the “Evaluation Period”) following the first download of the Software or (ii) during the period it makes available a feature, module or functionality as part of its early access program (the “Early Access Period”), the non-transferable, non-exclusive limited, free of charge license (for (i) the “Evaluation License” or for (ii) the “Early Access License”, as applicable, both a “License”) to permit Licensee and/or Licensee’s employees to internally use the Software to test and evaluate the Software. In case of the Evaluation License, Licensee will not be granted the license under this Agreement for one particular piece of the Software more than once. + +Under the License granted in this Agreement, Licensee shall not (i) use the Software to set up a production live system, for development purposes or any other purposes apart from evaluataing and testing the Software; (ii) copy any part of the Software except to make one copy for back-up purposes; (iii) distribute, disclose, market, rent, lease, or transfer the Software or act as a service bureau with respect to the Software; (iv) export the Software or install it in multiple locations; (v) disclose any confidential information provided by Spryker; (vi) modify or make derivative works of the Software; or (vii) allow others to make or obtain copies of the Software. + +The use of the Software in a production environment, to the extent permitted at all, requires prior conclusion of a separate agreement between Spryker and Licensee. Spryker will not support any versions of the Software being provided for evaluation purposes or as part of Spryker’s early access program. The provision of the Software as part of Spryker’s early access program does not necessarily mean it will be released as part of Spryker’s products in the future. + +The Software may contain elements of open source components, to which different license terms apply respectively. Licensee may need to install these open source components separately. + +THE SOFTWARE IS PROVIDED “AS-IS” AND WITHOUT WARRANTY OF ANY KIND. SPRYKER DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, TITLE, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. SPRYKER WILL NOT BE LIABLE FOR ANY DAMAGES ASSOCIATED WITH THE SOFTWARE, INCLUDING WITHOUT LIMITATION ORDINARY, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO DAMAGES RELATING TO LOST DATA OR LOST PROFITS, EVEN IF SPRYKER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +Licensee can provide input, suggestions, suggest or recommend changes or enhancements of the Software (“Feedback”). Any Feedback provided by Licensee is not considered confidential information and is received and treated by Spryker on a non-confidential and unrestricted basis. Licensee grants Spryker a sub-licenseable right to use, distribute, disclose and/or incorporate it into the Software or other products of Spryker, free of charge and without restriction as to time and place. + +Licensee's License to use the Software under this Agreement shall terminate on the earlier of (i) the expiration of the Evaluation Period or the Early Access Period (as applicable), or (ii) the date both parties enter into a definitive agreement for the provision by Spryker to Licensee of a full non-evaluation license to Spryker’s software. + +Upon termination of the License as provided under this Agreement, Licensee shall promptly destroy the Software and any back-up copy of the Software made during the Evaluation Period or Early Access Period if Spryker and Licensee have not agreed a non-evaluation license to Spryker’s software. + +This Agreement shall be governed by the laws of Germany to the exclusion of IPR (International Law) and the United Nations Convention on Contracts for the International Sale of Goods (CISG). The parties consent to the jurisdiction of the courts in Berlin (Germany). + +This Agreement and/or the License is not assignable or transferable by Licensee and any attempt to do so is null and void. + +This Agreement constitutes the entire agreement between the parties concerning Licensee’s use of the Software. This Agreement supersedes any prior verbal understanding between the parties. This Agreement may be amended only in a writing signed by an authorized officer of Spryker. diff --git a/README.md b/README.md index 89c6dd2f..efaa9b77 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # Development Module +[![Latest Stable Version](https://poser.pugx.org/spryker/development/v/stable.svg)](https://packagist.org/packages/spryker/development) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.2-8892BF.svg)](https://php.net/) Development is a tooling module for (local) development. @@ -11,4 +13,4 @@ composer require --dev spryker/development ## Documentation -[Module Documentation](https://academy.spryker.com/developing_with_spryker/module_guide/modules.html) +[Spryker Documentation](https://docs.spryker.com) diff --git a/architecture-baseline.json b/architecture-baseline.json new file mode 100644 index 00000000..829d709c --- /dev/null +++ b/architecture-baseline.json @@ -0,0 +1,198 @@ +[ + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Controversial/CamelCaseMethodName.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Controversial\\CamelCaseMethodName::apply()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjects.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Design\\CouplingBetweenObjects::apply()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildren.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Design\\NumberOfChildren::apply()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethods.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Design\\TooManyMethods::apply()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethods.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Design\\TooManyPublicMethods::apply()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Naming\\ShortVariable::checkMinimumLength()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Naming\\ShortVariable::getExceptionsList()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Naming\\ShortVariable::isNameAllowedInContext()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php", + "description": "Method `Spryker\\Zed\\Development\\Business\\PhpMd\\Rules\\Naming\\ShortVariable::isChildOf()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\CodeArchitectureSnifferConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/CodePhpMessDetectorConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\CodePhpMessDetectorConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/CodePhpstanConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\CodePhpstanConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/CodeStyleSnifferConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\CodeStyleSnifferConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/ComposerJsonUpdaterConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\ComposerJsonUpdaterConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/DependencyTreeBuilderConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\DependencyTreeBuilderConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFixConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/GenerateClientIdeAutoCompletionConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\GenerateClientIdeAutoCompletionConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/GenerateGlueIdeAutoCompletionConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\GenerateGlueIdeAutoCompletionConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/GenerateIdeAutoCompletionConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\GenerateIdeAutoCompletionConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/GenerateServiceIdeAutoCompletionConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\GenerateServiceIdeAutoCompletionConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/GenerateYvesIdeAutoCompletionConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\GenerateYvesIdeAutoCompletionConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/GenerateZedIdeAutoCompletionConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\GenerateZedIdeAutoCompletionConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/PluginUsageFinderConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\PluginUsageFinderConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Console/PropelAbstractValidateConsole.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Console\\PropelAbstractValidateConsole::execute()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Communication/Form/BundlesFormType.php", + "description": "Method `Spryker\\Zed\\Development\\Communication\\Form\\BundlesFormType::getBlockPrefix()` must have return type.", + "rule": "ExternalMethodExtensionReturnTypeRule", + "ruleset": "Spryker", + "priority": "1" + }, + { + "fileName": "src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeBridge.php", + "description": "Bridges: Method `getProjectModules()` must have `public function getCollection(CriteriaTransfer): CollectionTransfer` signature.", + "rule": "BridgeFacadeMethodsRule", + "ruleset": "Spryker", + "priority": "2" + }, + { + "fileName": "src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeBridge.php", + "description": "Bridges: Method `getModules()` must have `public function getCollection(CriteriaTransfer): CollectionTransfer` signature.", + "rule": "BridgeFacadeMethodsRule", + "ruleset": "Spryker", + "priority": "2" + }, + { + "fileName": "src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeBridge.php", + "description": "Bridges: Method `getPackages()` must have `public function getCollection(CriteriaTransfer): CollectionTransfer` signature.", + "rule": "BridgeFacadeMethodsRule", + "ruleset": "Spryker", + "priority": "2" + } +] diff --git a/bin/development b/bin/development new file mode 100755 index 00000000..a42c662c --- /dev/null +++ b/bin/development @@ -0,0 +1,51 @@ +#!/usr/bin/env php +addCommands( + [ + new CodeArchitectureSnifferConsole(), + new CodePhpMessDetectorConsole(), + new CodePhpstanConsole(), + new CodeStyleSnifferConsole(), + ], +); + +$application->run(); + +if ($configWasAdded) { + unlink(getcwd() . '/config/Shared/config_default.php'); +} diff --git a/bin/phpstorm-command-line-tools.sh b/bin/phpstorm-command-line-tools.sh new file mode 100755 index 00000000..0c6354e1 --- /dev/null +++ b/bin/phpstorm-command-line-tools.sh @@ -0,0 +1,308 @@ +#!/bin/bash + +# The directory/file selected in PhpStorm ($FileName$) needs to be transformed to the widly used "module" parameter structure (first match applies): +# 1. Items in vendor direcotry are resolved to Core +# a. items ending as "/spryker" OR "/spryker/Bundles": are resolved to "Spryker.all" +# b. items ending as "/spryker-shop" OR "/spryker-shop/Bundles": are resolved to "SprykerShop.all" +# c. items ending as "/spryker-eco" OR "/spryker-eco/Bundles": are resolved to "SprykerEco.all" +# d. items containing "/spryker/spryker/" AND 1 more item: are resolved as "Spryker.{selected camelcased name}" (nonsplit modules) +# d. items containing "/spryker-shop/" AND 1 more item: are resolved as "SprykerShop.{selected camelcased name}" +# d. items containing "/spryker-eco/" AND 1 more item: are resolved as "SprykerEco.{selected camelcased name}" +# d. items containing "/spryker/" AND 1 more item: are resolved as "Spryker.{selected camelcased name}" (standalone modules) +# 2. If item is the root "src" directory OR a 1st level directory in "src" OR a 2nd level directory in "src": are resolved to "all" (project) +# 3. Item: is resolved to "{selected camelcased name}" (project) +TARGET_MODULE_EXPRESSION=$(cat <<'EOF' + TARGET_MODULE=$(if [[ $FileDirRelativeToProjectRoot$ == vendor* ]]; then if [[ $FileDirRelativeToProjectRoot$ == */spryker || $FileDirRelativeToProjectRoot$ == *spryker/Bundles ]]; then echo 'Spryker.all'; elif [[ $FileDirRelativeToProjectRoot$ == */spryker-shop || $FileDirRelativeToProjectRoot$ == *spryker-shop/Bundles ]]; then echo 'SprykerShop.all'; elif [[ $FileDirRelativeToProjectRoot$ == */spryker-eco || $FileDirRelativeToProjectRoot$ == *spryker-eco/Bundles ]]; then echo 'SprykerEco.all'; elif [[ $FileDirRelativeToProjectRoot$ == */spryker/spryker/* ]]; then echo \"Spryker.$TARGET_DIR\"; elif [[ $FileDirRelativeToProjectRoot$ == */spryker-shop/* ]]; then echo \"SprykerShop.$TARGET_DIR\"; elif [[ $FileDirRelativeToProjectRoot$ == */spryker-eco/* ]]; then echo \"SprykerEco.$TARGET_DIR\"; elif [[ "$FileDirRelativeToProjectRoot$" == */spryker/* && ! "$FileDirRelativeToProjectRoot$" == */spryker/*/* ]]; then echo \"Spryker.$TARGET_DIR\"; fi; else if [[ "$FilePath$" == "$ProjectFileDir$/src" ]] || [[ "$FilePath$" == "$ProjectFileDir$/src/*" && ! "$FilePath$" == "$ProjectFileDir$/src/*/*/*" ]]; then echo \"all\"; else echo \"$TARGET_DIR\"; fi; fi); +EOF +) + +# The directory/file selected in PhpStorm ($FileName$) is transformed to camelcase into TARGET_DIR variable (eg: event-behavior => EventBehavior, AclExtension => AclExtension) +TARGET_DIR_EXPRESSION=$(cat <<'EOF' + TARGET_DIR=$(echo '$FileName$' | awk -F- '{ OFS=\"\"; for(i=1; i<=NF; i++) $i = toupper(substr($i,1,1)) substr($i,2); print }'); +EOF +) + +XML_CONTENT_START=$(cat <<'EOF' + +EOF +) + +XML_CONTENT_END=$(cat <<'EOF' + + +EOF +) + +XML_GENERIC_COMMANDS=$(cat <<'EOF' + + + + + + + + + + + + + +EOF +) + +XML_CORE_COMMANDS=$(cat <<'EOF' + + + + + + + + + + + + + + + + + +EOF +) + + + +XML_GENERIC_COMMANDS="${XML_GENERIC_COMMANDS//__TARGETDIR__/$TARGET_DIR_EXPRESSION}" +XML_GENERIC_COMMANDS="${XML_GENERIC_COMMANDS//__TARGETMODULE__/$TARGET_MODULE_EXPRESSION}" +XML_CORE_COMMANDS="${XML_CORE_COMMANDS//__TARGETDIR__/$TARGET_DIR_EXPRESSION}" +XML_CORE_COMMANDS="${XML_CORE_COMMANDS//__TARGETMODULE__/$TARGET_MODULE_EXPRESSION}" + +display_help() { + cat << EOF +Description: + Copy Spryker Tool configuration files to the local machine PhpStorm configuration folder. + +Usage: + vendor/bin/phpstorm-command-line-tools.sh [options] + +Options: + -y Automatically agree to copy/remove the configuration files to the local machine PhpStorm configuration folder. + --platform=PLATFORM Set the platform for the configuration (default: docker). Options: docker, local. + -p PLATFORM Shorthand for --platform, specify either "docker" or "local". + -u, --uninstall Uninstall the Spryker tools configuration from the local PhpStorm configuration folder. + -h Display this help message. + +Help: + This script will copy configuration files to the local PhpStorm configuration folder for the latest version of PhpStorm. + + Example of usage: + + ./phpstorm-command-line-tools.sh -y --platform=local + This will run the script and automatically copy the configuration files for local machine tools without asking for confirmation. + + ./phpstorm-command-line-tools.sh -u + This will uninstall the Spryker tools configuration from the local PhpStorm configuration folder. + + Use -h to display this help message: + + ./phpstorm-command-line-tools.sh -h + +EOF +} + + +AUTO_CONFIRM=false +PLATFORM="docker" # Default value +UNINSTALL=false + +while [[ $# -gt 0 ]]; do + case "$1" in + -y) + AUTO_CONFIRM=true + shift # Remove -y from processing + ;; + -p) + # Ensure the platform argument exists and is valid for -p + if [[ -z "$2" || ( "$2" != "docker" && "$2" != "local" ) ]]; then + echo "Invalid platform option: $2 (allowed: docker, local)" >&2 + exit 1 + fi + PLATFORM="$2" + shift 2 # Remove both -p and its argument + ;; + --platform=*) + PLATFORM="${1#*=}" + if [[ "$PLATFORM" != "docker" && "$PLATFORM" != "local" ]]; then + echo "Invalid platform option: $PLATFORM (allowed: docker, local)" >&2 + exit 1 + fi + shift # Remove this argument + ;; + -u|--uninstall) + UNINSTALL=true + shift # Remove -u or --uninstall from processing + ;; + -h|--help) + display_help + exit 0 + ;; + *) + echo "Invalid option: $1" >&2 + exit 1 + ;; + esac +done + +delete_from_jetbrains() { + # Take the base directory as an argument + local BASE_DIR="$1" + + # Find the latest product version directory + LATEST_DIR=$(find "$BASE_DIR" -maxdepth 1 -type d -name 'PhpStorm*' | sort -V | tail -n 1) + + # Check if the latest PhpStorm configuration directory was found + if [[ -n "$LATEST_DIR" ]]; then + DEST_DIR="$LATEST_DIR/tools" + FILE_PATH="$DEST_DIR/Spryker Tools.xml" + + # Check if the Spryker Tools.xml file exists + if [[ -f "$FILE_PATH" ]]; then + # If AUTO_CONFIRM is not true, ask for confirmation + if ! $AUTO_CONFIRM; then + echo -e "\033[0;33mThis script will delete the Spryker Tools configuration file from your local JetBrains PhpStorm configuration directory:\033[0m" + echo "File to be deleted: $FILE_PATH" + read -p "Do you agree to proceed with the deletion? (y/n): " confirm + + if [[ "$confirm" != "y" ]]; then + echo "Operation canceled." + return 1 + fi + fi + + # Proceed to delete the file + rm -f "$FILE_PATH" + echo "Deleted $FILE_PATH ." + echo -e "\033[0;33mPlease restart PhpStorm for the changes to take effect.\033[0m" + else + echo "No Spryker Tools.xml file found in $DEST_DIR." + fi + else + echo "No JetBrains product directory found in $BASE_DIR." + fi +} + +# Function to handle copying on both macOS and Linux +copy_to_jetbrains() { + # Take the base directory as an argument + local BASE_DIR="$1" + + # Find the latest product version directory + LATEST_DIR=$(find "$BASE_DIR" -maxdepth 1 -type d -name 'PhpStorm*' | sort -V | tail -n 1) + + if [[ -n "$LATEST_DIR" ]]; then + DEST_DIR="$LATEST_DIR/tools" + + # If the -y flag was not provided, ask for confirmation + if ! $AUTO_CONFIRM; then + echo -e "\033[0;33mThis script will create or modify a file in your local machine JetBrains PhpStorm configuration directory:\033[0m" + echo "File: $DEST_DIR/Spryker Tools.xml" + read -p "Do you agree to proceed? (y/n): " confirm + + if [[ "$confirm" != "y" ]]; then + echo "Operation canceled." + exit 1 + fi + fi + + mkdir -p "$DEST_DIR" + + if [[ "$PLATFORM" == "local" ]]; then + XML_GENERIC_COMMANDS="${XML_GENERIC_COMMANDS//__COMMAND__/vendor/bin/console}" + if [[ -f "./vendor/bin/spryker-dev-console" ]]; then + echo "$XML_CONTENT_START$XML_GENERIC_COMMANDS$XML_CORE_COMMANDS$XML_CONTENT_END" > "$DEST_DIR/Spryker Tools.xml" + else + echo "$XML_CONTENT_START$XML_CORE_COMMANDS$XML_CONTENT_END" > "$DEST_DIR/Spryker Tools.xml" + fi + + echo "" + echo "Successfully created Spryker Tools.xml in $DEST_DIR with" + echo "- vendor/bin/console code:sniff:style -f -m [module]" + echo "- vendor/bin/console code:phpstan -m [module] -vvv" + echo "- vendor/bin/console code:sniff:architecture -m [module] -vvv" + if [[ -f "./vendor/bin/spryker-dev-console" ]]; then + echo "- vendor/bin/codecept run -c [relative directory]" + echo "- vendor/bin/spryker-dev-console dev:validate-module-transfers -m [module] -vvv" + echo "- vendor/bin/spryker-dev-console dev:validate-module-schemas -m [module] -vvv" + echo "- vendor/bin/spryker-dev-console dev:validate-module-databuilders -m [module] -vvv" + fi + echo "" + echo -e "\033[1;33mImportant:\033[0m To execute commands from within PhpStorm, verify that all required tools are installed and runnable on your local machine." + echo -e "\033[0;33mPlease restart PhpStorm for the changes to take effect.\033[0m" + + elif [[ "$PLATFORM" == "docker" ]]; then + XML_GENERIC_COMMANDS="${XML_GENERIC_COMMANDS//__COMMAND__/docker/sdk console}" + echo "$XML_CONTENT_START$XML_GENERIC_COMMANDS$XML_CONTENT_END" > "$DEST_DIR/Spryker Tools.xml" + echo "" + echo "Successfully created Spryker Tools.xml in $DEST_DIR with" + echo "- docker/sdk console code:sniff:style -f -m [module]" + echo "- docker/sdk console code:phpstan -m [module] -vvv" + echo "- docker/sdk console code:sniff:architecture -m [module] -vv" + if [[ -f "./vendor/bin/spryker-dev-console" ]]; then + echo "Info: vendor/bin/spryker-dev-console and vendor/bin/codecept commands were not registered as they require local machine to run." + fi + echo "" + echo -e "\033[1;33mImportant:\033[0m To execute commands from within PhpStorm, ensure that Spryker Docker is running." + echo -e "\033[0;33mPlease restart PhpStorm for the changes to take effect.\033[0m" + + else + echo "Error: Unexpected argument combination. Please specify a valid PLATFORM value ('local' or 'docker')." >&2 + exit 1 + fi + else + echo "No JetBrains product directory found in $BASE_DIR." + + exit 0 + fi +} + +if [[ "$UNINSTALL" != true ]]; then + if ! command -v awk &> /dev/null; then + echo "Error: 'awk' is not installed. Please install it before running this script." + exit 1 + fi +fi + +if [[ "$OSTYPE" == "darwin"* ]]; then + BASE_DIR="$HOME/Library/Application Support/JetBrains" +else + echo "Unsupported operating system: $OSTYPE" + exit 1 +fi + +if [[ "$UNINSTALL" == true ]]; then + delete_from_jetbrains "$BASE_DIR" +else + copy_to_jetbrains "$BASE_DIR" +fi diff --git a/codeception.yml b/codeception.yml index a1e68b24..5521e740 100644 --- a/codeception.yml +++ b/codeception.yml @@ -2,26 +2,13 @@ namespace: SprykerTest include: - tests/SprykerTest/Zed/Development paths: - tests: tests + tests: tests/ support: . - log: tests/_output - data: tests/_data - envs: tests/_envs + output: tests/_output/ + data: tests/_data/ + envs: tests/_envs/ settings: - bootstrap: _bootstrap.php suite_class: \PHPUnit\Framework\TestSuite colors: true memory_limit: 1024M log: true -coverage: - enabled: true - whitelist: - include: - - 'src/*' -extensions: - enabled: - - Codeception\Extension\Phantoman - config: - Codeception\Extension\Phantoman: - suites: - - Presentation diff --git a/composer.json b/composer.json index 372c5c8a..f099991a 100644 --- a/composer.json +++ b/composer.json @@ -1,45 +1,60 @@ { - "name": "spryker/development", - "type": "library", - "description": "Development module", - "license": "proprietary", - "require": { - "nette/di": "^2.4.7 || ^3.0", - "php": ">=7.1", - "spryker/config": "^3.0.0", - "spryker/graph": "^3.0.0", - "spryker/kernel": "^3.22.0", - "spryker/symfony": "^3.0.0", - "spryker/twig": "^3.0.0", - "spryker/zend": "^2.0.0" - }, - "require-dev": { - "spryker/code-sniffer": "*", - "spryker/propel": "*", - "spryker/testify": "*" - }, - "autoload": { - "psr-4": { - "Spryker\\": "src/Spryker/", - "SprykerTest\\Zed\\Development\\Helper\\": "tests/SprykerTest/Zed/Development/_support/Helper/" + "name": "spryker/development", + "type": "library", + "description": "Development module", + "license": "proprietary", + "require": { + "nette/di": "^2.4.7 || ^3.2.0", + "php": ">=8.2", + "phpmd/phpmd": "^2.0.0", + "spryker/config": "^3.0.0", + "spryker/graph": "^3.0.0", + "spryker/kernel": "^3.52.0", + "spryker/laminas": "^1.0.0", + "spryker/module-finder": "^1.0.0", + "spryker/symfony": "^3.0.0", + "spryker/twig": "^3.16.0" }, - "files": [ - "tests/dd.php" + "require-dev": { + "spryker-sdk/phpstan-spryker": "*", + "spryker/architecture-sniffer": "*", + "spryker/code-sniffer": "*", + "spryker/propel": "*", + "spryker/testify": "*" + }, + "autoload": { + "psr-4": { + "Spryker\\": "src/Spryker/", + "SprykerTest\\Zed\\Development\\Helper\\": "tests/SprykerTest/Zed/Development/_support/Helper/" + }, + "files": [ + "tests/dd.php" + ] + }, + "autoload-dev": { + "psr-4": { + "SprykerTest\\": "tests/SprykerTest/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "scripts": { + "cs-check": "phpcs -p -s --standard=vendor/spryker/code-sniffer/Spryker/ruleset.xml src/ tests/", + "cs-fix": "phpcbf -p --standard=vendor/spryker/code-sniffer/Spryker/ruleset.xml src/ tests/" + }, + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "config": { + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "bin": [ + "bin/development", + "bin/phpstorm-command-line-tools.sh" ] - }, - "autoload-dev": { - "psr-4": { - "SprykerTest\\": "tests/SprykerTest/" - } - }, - "minimum-stability": "dev", - "prefer-stable": true, - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "config": { - "sort-packages": true - } } diff --git a/config/Shared/config_default.php b/config/Shared/config_default.php new file mode 100644 index 00000000..c78cb432 --- /dev/null +++ b/config/Shared/config_default.php @@ -0,0 +1,15 @@ +" between int<2, max> and 1 is always true.#' + - '#Instanceof between string and Nette\\DI\\Config\\Adapter will always evaluate to false.#' + - '#Parameter \#1 \$[a-zA-Z]* of class ReflectionClass constructor expects class-string\|T of object, string given.#' + - '#Parameter \#1 \$callback of function spl_autoload_unregister expects callable\(\): mixed, array given.#' + - '#Parameter \#2 \$callback of function array_filter expects .+, .+glob.+ given#' + - '#Parameter \#2 \$callback of function array_filter expects \(callable\(mixed\): bool\)\|null, .+ given.#' + - '#Parameter \#2 \$callback of function array_filter expects \(callable\(string\): bool\)\|null, .+ given.#' diff --git a/psalm-report.json b/psalm-report.json new file mode 100644 index 00000000..c7d0e71d --- /dev/null +++ b/psalm-report.json @@ -0,0 +1,3057 @@ +{ + "error": [ + { + "severity": "error", + "line_from": 698, + "line_to": 698, + "type": "UndefinedMethod", + "message": "Method ReflectionType::getName does not exist", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $type = $parameter->getType()->getName();", + "selected_text": "getName", + "error_level": 6, + "shortcode": 22 + }, + { + "severity": "error", + "line_from": 341, + "line_to": 341, + "type": "InvalidArgument", + "message": "Argument 2 of array_filter expects callable(mixed, mixed=):scalar, \"glob\" provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParser.php", + "snippet": " return array_filter($lookupPaths, 'glob');", + "selected_text": "'glob'", + "error_level": 6, + "shortcode": 4 + }, + { + "severity": "error", + "line_from": 67, + "line_to": 69, + "type": "InvalidArgument", + "message": "Argument 2 of array_filter expects callable(mixed, mixed=):scalar, impure-Closure(string):(false|list) provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinder.php", + "snippet": " function (string $twigFilePath) {\n return glob($twigFilePath, GLOB_NOSORT);\n },", + "selected_text": "function (string $twigFilePath) {\n return glob($twigFilePath, GLOB_NOSORT);\n }", + "error_level": 6, + "shortcode": 4 + }, + { + "severity": "error", + "line_from": 38, + "line_to": 38, + "type": "InvalidArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\DependencyTree\\DependencyFinder\\UseStatement::getLayerFromUseStatement expects string, array provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/UseStatement.php", + "snippet": " $layer = $this->getLayerFromUseStatement($match);", + "selected_text": "$match", + "error_level": 6, + "shortcode": 4 + }, + { + "severity": "error", + "line_from": 36, + "line_to": 38, + "type": "InvalidArgument", + "message": "Argument 2 of array_filter expects callable(mixed, mixed=):scalar, impure-Closure(string):(false|list) provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FileFinder.php", + "snippet": " $directories = array_filter($directories, function (string $directory) {\n return glob($directory, GLOB_NOSORT);\n });", + "selected_text": "function (string $directory) {\n return glob($directory, GLOB_NOSORT);\n }", + "error_level": 6, + "shortcode": 4 + }, + { + "severity": "error", + "line_from": 70, + "line_to": 72, + "type": "InvalidArgument", + "message": "Argument 2 of array_filter expects callable(mixed, mixed=):scalar, impure-Closure(string):(false|list) provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinder.php", + "snippet": " function (string $directory) {\n return glob($directory, GLOB_NOSORT | GLOB_ONLYDIR);\n },", + "selected_text": "function (string $directory) {\n return glob($directory, GLOB_NOSORT | GLOB_ONLYDIR);\n }", + "error_level": 6, + "shortcode": 4 + }, + { + "severity": "error", + "line_from": 105, + "line_to": 105, + "type": "InvalidReturnStatement", + "message": "The inferred type 'mixed|string' does not match the declared return type 'int' for Spryker\\Zed\\Development\\Business\\SnifferConfiguration\\Builder\\ArchitectureSnifferConfigurationBuilder::getPriority", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/SnifferConfiguration/Builder/ArchitectureSnifferConfigurationBuilder.php", + "snippet": " return $userPriorityOption;", + "selected_text": "$userPriorityOption", + "error_level": 6, + "shortcode": 128 + }, + { + "severity": "error", + "line_from": 91, + "line_to": 91, + "type": "InvalidReturnType", + "message": "The declared return type 'ArrayObject' for Spryker\\Zed\\Development\\Communication\\Console\\AbstractCoreModuleAwareConsole::getModuleDependencies is incorrect, got 'ArrayObject|array'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php", + "snippet": " * @return \\ArrayObject", + "selected_text": "\\ArrayObject", + "error_level": 6, + "shortcode": 11 + }, + { + "severity": "error", + "line_from": 101, + "line_to": 101, + "type": "InvalidReturnStatement", + "message": "The inferred type 'ArrayObject|array' does not match the declared return type 'ArrayObject' for Spryker\\Zed\\Development\\Communication\\Console\\AbstractCoreModuleAwareConsole::getModuleDependencies", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php", + "snippet": " return $dependencyValidationResponseTransfer->getModuleDependencies();", + "selected_text": "$dependencyValidationResponseTransfer->getModuleDependencies()", + "error_level": 6, + "shortcode": 128 + } + ], + "warning": [ + { + "severity": "info", + "line_from": 192, + "line_to": 192, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Laminas\\Config\\Reader\\ReaderInterface::fromString cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/ArchitectureSniffer/ArchitectureSniffer.php", + "snippet": " $results = $this->xmlReader->fromString($output);", + "selected_text": "$output", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 316, + "line_to": 316, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/ArchitectureSniffer/ArchitectureSniffer.php", + "snippet": " $process->getExitCodeText(),", + "selected_text": "$process->getExitCodeText()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 133, + "line_to": 133, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $fileName = $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface.php';", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 133, + "line_to": 133, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $fileName = $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface.php';", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 133, + "line_to": 133, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $fileName = $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface.php';", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 137, + "line_to": 137, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getVendor() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getVendor()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 137, + "line_to": 142, + "type": "ArgumentTypeCoercion", + "message": "Argument 1 of ReflectionClass::__construct expects class-string|object|trait-string, parent type non-empty-string provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getVendor() . '\\\\' .\n $bridgeBuilderDataTransfer->getApplication() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . '\\\\' .\n 'Dependency\\\\' .\n $bridgeBuilderDataTransfer->getToType() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface',", + "selected_text": "$bridgeBuilderDataTransfer->getVendor() . '\\\\' .\n $bridgeBuilderDataTransfer->getApplication() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . '\\\\' .\n 'Dependency\\\\' .\n $bridgeBuilderDataTransfer->getToType() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface'", + "error_level": 3, + "shortcode": 193 + }, + { + "severity": "info", + "line_from": 138, + "line_to": 138, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getApplication() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getApplication()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 139, + "line_to": 139, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 141, + "line_to": 141, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToType() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 142, + "line_to": 142, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface',", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 142, + "line_to": 142, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface',", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 142, + "line_to": 142, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface',", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 164, + "line_to": 164, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $fileName = $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge.php';", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 164, + "line_to": 164, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $fileName = $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge.php';", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 164, + "line_to": 164, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $fileName = $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge.php';", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 169, + "line_to": 169, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getVendor() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getVendor()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 169, + "line_to": 174, + "type": "ArgumentTypeCoercion", + "message": "Argument 1 of ReflectionClass::__construct expects class-string|object|trait-string, parent type non-empty-string provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getVendor() . '\\\\' .\n $bridgeBuilderDataTransfer->getApplication() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . '\\\\' .\n 'Dependency\\\\' .\n $bridgeBuilderDataTransfer->getToType() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge',", + "selected_text": "$bridgeBuilderDataTransfer->getVendor() . '\\\\' .\n $bridgeBuilderDataTransfer->getApplication() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . '\\\\' .\n 'Dependency\\\\' .\n $bridgeBuilderDataTransfer->getToType() . '\\\\' .\n $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge'", + "error_level": 3, + "shortcode": 193 + }, + { + "severity": "info", + "line_from": 170, + "line_to": 170, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getApplication() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getApplication()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 171, + "line_to": 171, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 173, + "line_to": 173, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToType() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 174, + "line_to": 174, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge',", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 174, + "line_to": 174, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge',", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 174, + "line_to": 174, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge',", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 256, + "line_to": 256, + "type": "PossiblyNullArgument", + "message": "Argument 1 of lcfirst cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " '{toModuleVariable}' => lcfirst($bridgeBuilderDataTransfer->getToModule()),", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 259, + "line_to": 259, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\CodeBuilder\\Bridge\\BridgeBuilder::getModuleLayer cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " if ($this->getModuleLayer($bridgeBuilderDataTransfer->getToType())) {", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 260, + "line_to": 260, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\CodeBuilder\\Bridge\\BridgeBuilder::getModuleLayer cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $replacements['{toModuleLayer}'] = '\\\\' . $this->getModuleLayer($bridgeBuilderDataTransfer->getToType());", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 408, + "line_to": 408, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\DevelopmentConfig::getPathToInternalNamespace cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $pathToInternalNamespace = $this->config->getPathToInternalNamespace($bridgeBuilderDataTransfer->getVendor());", + "selected_text": "$bridgeBuilderDataTransfer->getVendor()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 410, + "line_to": 410, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " return $pathToInternalNamespace . $bridgeBuilderDataTransfer->getModule();", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 413, + "line_to": 413, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\CodeBuilder\\Bridge\\BridgeBuilder::normalizeNameForSplit cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $vendorDirectory = $this->normalizeNameForSplit($bridgeBuilderDataTransfer->getVendor());", + "selected_text": "$bridgeBuilderDataTransfer->getVendor()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 414, + "line_to": 414, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\CodeBuilder\\Bridge\\BridgeBuilder::normalizeNameForSplit cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $moduleDirectory = $this->normalizeNameForSplit($bridgeBuilderDataTransfer->getModule());", + "selected_text": "$bridgeBuilderDataTransfer->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 430, + "line_to": 430, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\DevelopmentConfig::getPathToInternalNamespace cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $pathToInternalNamespace = $this->config->getPathToInternalNamespace($bridgeBuilderDataTransfer->getToVendor());", + "selected_text": "$bridgeBuilderDataTransfer->getToVendor()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 432, + "line_to": 432, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " return $pathToInternalNamespace . $bridgeBuilderDataTransfer->getToModule();", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 435, + "line_to": 435, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\CodeBuilder\\Bridge\\BridgeBuilder::normalizeNameForSplit cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $vendorDirectory = $this->normalizeNameForSplit($bridgeBuilderDataTransfer->getToVendor());", + "selected_text": "$bridgeBuilderDataTransfer->getToVendor()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 436, + "line_to": 436, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\CodeBuilder\\Bridge\\BridgeBuilder::normalizeNameForSplit cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $moduleDirectory = $this->normalizeNameForSplit($bridgeBuilderDataTransfer->getToModule());", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 484, + "line_to": 484, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType(),", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 484, + "line_to": 484, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType(),", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 499, + "line_to": 499, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToVendor() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getToVendor()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 500, + "line_to": 500, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToApplication() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getToApplication()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 501, + "line_to": 501, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToModule() . '\\\\';", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 504, + "line_to": 504, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $path .= $bridgeBuilderDataTransfer->getToModuleLayer() . '\\\\';", + "selected_text": "$bridgeBuilderDataTransfer->getToModuleLayer()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 507, + "line_to": 507, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $path .= $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType();", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 507, + "line_to": 507, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $path .= $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType();", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 509, + "line_to": 509, + "type": "ArgumentTypeCoercion", + "message": "Argument 1 of ReflectionClass::__construct expects class-string|object|trait-string, parent type non-empty-string provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $targetBridgeClass = new ReflectionClass($path);", + "selected_text": "$path", + "error_level": 3, + "shortcode": 193 + }, + { + "severity": "info", + "line_from": 528, + "line_to": 528, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToVendor() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getToVendor()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 529, + "line_to": 529, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToApplication() . '\\\\' .", + "selected_text": "$bridgeBuilderDataTransfer->getToApplication()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 530, + "line_to": 530, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $bridgeBuilderDataTransfer->getToModule() . '\\\\';", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 533, + "line_to": 533, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $path .= $bridgeBuilderDataTransfer->getToModuleLayer() . '\\\\';", + "selected_text": "$bridgeBuilderDataTransfer->getToModuleLayer()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 536, + "line_to": 536, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $path .= $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface';", + "selected_text": "$bridgeBuilderDataTransfer->getToModule()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 536, + "line_to": 536, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $path .= $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface';", + "selected_text": "$bridgeBuilderDataTransfer->getToType()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 538, + "line_to": 538, + "type": "ArgumentTypeCoercion", + "message": "Argument 1 of ReflectionClass::__construct expects class-string|object|trait-string, parent type non-empty-string provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php", + "snippet": " $targetBridgeInterface = new ReflectionClass($path);", + "selected_text": "$path", + "error_level": 3, + "shortcode": 193 + }, + { + "severity": "info", + "line_from": 110, + "line_to": 110, + "type": "PossiblyNullArgument", + "message": "Argument 1 of strpos cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " if (strpos($module, '.') !== false) {", + "selected_text": "$module", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 111, + "line_to": 111, + "type": "PossiblyNullArgument", + "message": "Argument 2 of explode cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " [$namespace, $module] = explode('.', $module, 2);", + "selected_text": "$module", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 149, + "line_to": 149, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\CodeStyleSniffer\\CodeStyleSniffer::resolveCorePath cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " return $this->resolveCorePath($module, $namespace, $path, $options);", + "selected_text": "$module", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 153, + "line_to": 153, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " return $this->addPath([], $this->config->getPathToRoot() . $path, $options);", + "selected_text": "$path", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 245, + "line_to": 245, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\CodeStyleSniffer\\CodeStyleSniffer::buildPath cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " return $this->buildPath($pathToInternalNamespace . $module . DIRECTORY_SEPARATOR, $pathSuffix);", + "selected_text": "$pathSuffix", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 252, + "line_to": 252, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\CodeStyleSniffer\\CodeStyleSniffer::buildPath cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " return $this->buildPath($path, $pathSuffix);", + "selected_text": "$pathSuffix", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 336, + "line_to": 336, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " $optionIgnore .= ($optionIgnore ? ',' : '') . '/src/Generated/';", + "selected_text": "$optionIgnore", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 376, + "line_to": 376, + "type": "PossiblyNullArgument", + "message": "Argument 1 of strpos cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " if (strpos($codeStyleSnifferConfiguration->getModule(), '.all') !== false) {", + "selected_text": "$codeStyleSnifferConfiguration->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 384, + "line_to": 384, + "type": "NullableReturnStatement", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\CodeStyleSniffer\\CodeStyleSniffer::runSnifferCommand is not nullable, but the function returns 'int|null'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " return $process->getExitCode();", + "selected_text": "$process->getExitCode()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 392, + "line_to": 392, + "type": "InvalidNullableReturnType", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\CodeStyleSniffer\\CodeStyleSniffer::runSnifferCommandForAll is not nullable, but 'int|null' contains null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " * @return int", + "selected_text": "int", + "error_level": 5, + "shortcode": 144 + }, + { + "severity": "info", + "line_from": 415, + "line_to": 415, + "type": "NullableReturnStatement", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\CodeStyleSniffer\\CodeStyleSniffer::runSnifferCommandForAll is not nullable, but the function returns 'int|null'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php", + "snippet": " return $process->getExitCode();", + "selected_text": "$process->getExitCode()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 220, + "line_to": 220, + "type": "InvalidNullableReturnType", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\CodeTest\\CodeTester::runTestCommand is not nullable, but 'int|null' contains null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php", + "snippet": " * @return int", + "selected_text": "int", + "error_level": 5, + "shortcode": 144 + }, + { + "severity": "info", + "line_from": 249, + "line_to": 249, + "type": "NullableReturnStatement", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\CodeTest\\CodeTester::runTestCommand is not nullable, but the function returns 'int|null'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php", + "snippet": " return $process->getExitCode();", + "selected_text": "$process->getExitCode()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 256, + "line_to": 256, + "type": "InvalidNullableReturnType", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\CodeTest\\CodeTester::runFixturesCommand is not nullable, but 'int|null' contains null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php", + "snippet": " * @return int", + "selected_text": "int", + "error_level": 5, + "shortcode": 144 + }, + { + "severity": "info", + "line_from": 281, + "line_to": 281, + "type": "NullableReturnStatement", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\CodeTest\\CodeTester::runFixturesCommand is not nullable, but the function returns 'int|null'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php", + "snippet": " return $process->getExitCode();", + "selected_text": "$process->getExitCode()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 39, + "line_to": 39, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Composer\\ComposerJson::hasComposerJson cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerJson.php", + "snippet": " if (!$this->hasComposerJson($moduleTransfer)) {", + "selected_text": "$moduleTransfer", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 79, + "line_to": 79, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerJson.php", + "snippet": " $composerJsonFilePath = sprintf('%s/composer.json', $moduleTransfer->getPath());", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 43, + "line_to": 43, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Symfony\\Component\\Finder\\Finder::in cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerJsonFinder.php", + "snippet": " ->in($module->getPath())", + "selected_text": "$module->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 60, + "line_to": 60, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdater.php", + "snippet": " $moduleKey = implode('.', [$moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()]);", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 78, + "line_to": 78, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed());", + "selected_text": "$moduleTransfer->getOrganization()->getNameDashed()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 78, + "line_to": 78, + "type": "PossiblyNullReference", + "message": "Cannot call method getNameDashed on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed());", + "selected_text": "getNameDashed", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 78, + "line_to": 78, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed());", + "selected_text": "$moduleTransfer->getNameDashed()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 93, + "line_to": 93, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed());", + "selected_text": "$moduleTransfer->getOrganization()->getNameDashed()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 93, + "line_to": 93, + "type": "PossiblyNullReference", + "message": "Cannot call method getNameDashed on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed());", + "selected_text": "getNameDashed", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 93, + "line_to": 93, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed());", + "selected_text": "$moduleTransfer->getNameDashed()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 160, + "line_to": 160, + "type": "PossiblyNullArrayOffset", + "message": "Cannot access value on variable $this->moduleTransferCollectionGroupedByModuleName[null|string] using possibly null offset null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " $this->moduleTransferCollectionGroupedByModuleName[$moduleTransfer->getName()][] = $moduleTransfer;", + "selected_text": "$this->moduleTransferCollectionGroupedByModuleName", + "error_level": 3, + "shortcode": 125 + }, + { + "severity": "info", + "line_from": 179, + "line_to": 179, + "type": "PossiblyNullArrayOffset", + "message": "Cannot access value on variable $this->packageTransferCollectionGroupedByPackageName[null|string] using possibly null offset null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php", + "snippet": " $this->packageTransferCollectionGroupedByPackageName[$packageTransfer->getPackageName()] = $packageTransfer;", + "selected_text": "$this->packageTransferCollectionGroupedByPackageName", + "error_level": 3, + "shortcode": 125 + }, + { + "severity": "info", + "line_from": 54, + "line_to": 54, + "type": "RedundantCondition", + "message": "Operand of type true is always true", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Composer/Updater/RequireDevUpdater.php", + "snippet": " } elseif (!$requiresCodeSniffer) {", + "selected_text": "!$requiresCodeSniffer", + "error_level": 4, + "shortcode": 122 + }, + { + "severity": "info", + "line_from": 50, + "line_to": 50, + "type": "ArgumentTypeCoercion", + "message": "Argument 1 of ReflectionClass::__construct expects class-string|object|trait-string, parent type string provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/ComposerParser/ExternalDependencyParser.php", + "snippet": " $reflectionClass = new ReflectionClass($className);", + "selected_text": "$className", + "error_level": 3, + "shortcode": 193 + }, + { + "severity": "info", + "line_from": 113, + "line_to": 113, + "type": "PossiblyNullArgument", + "message": "Argument 1 of strcmp cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainer.php", + "snippet": " return strcmp($dependencyBundleTransferA->getModule(), $dependencyBundleTransferB->getModule());", + "selected_text": "$dependencyBundleTransferA->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 113, + "line_to": 113, + "type": "PossiblyNullArgument", + "message": "Argument 2 of strcmp cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainer.php", + "snippet": " return strcmp($dependencyBundleTransferA->getModule(), $dependencyBundleTransferB->getModule());", + "selected_text": "$dependencyBundleTransferB->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 116, + "line_to": 116, + "type": "PossiblyInvalidMethodCall", + "message": "Cannot call method on possible array variable ", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainer.php", + "snippet": " $dependencyModules = $dependencyCollectionTransfer->getDependencyModules()->getArrayCopy();", + "selected_text": "getArrayCopy", + "error_level": 3, + "shortcode": 113 + }, + { + "severity": "info", + "line_from": 75, + "line_to": 75, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php", + "snippet": " $moduleExtensionKey = sprintf('%s.%sExtension', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 75, + "line_to": 75, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php", + "snippet": " $moduleExtensionKey = sprintf('%s.%sExtension', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 75, + "line_to": 75, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php", + "snippet": " $moduleExtensionKey = sprintf('%s.%sExtension', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 78, + "line_to": 78, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\ExtensionDependencyFinder::buildComposerName cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php", + "snippet": " $composerName = $this->buildComposerName($moduleTransfer->getOrganization()->getName(), sprintf('%sExtension', $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 78, + "line_to": 78, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php", + "snippet": " $composerName = $this->buildComposerName($moduleTransfer->getOrganization()->getName(), sprintf('%sExtension', $moduleTransfer->getName()));", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 78, + "line_to": 78, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php", + "snippet": " $composerName = $this->buildComposerName($moduleTransfer->getOrganization()->getName(), sprintf('%sExtension', $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 113, + "line_to": 113, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\InternalDependencyFinder::getNamesFromUseStatements cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/InternalDependencyFinder.php", + "snippet": " $composerNames = $this->getNamesFromUseStatements($useStatements, $context->getModule()->getName());", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 71, + "line_to": 71, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Dependency\\SchemaParser\\PropelSchemaParserInterface::getModuleNameByForeignReference cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/PersistenceDependencyFinder.php", + "snippet": " $dependentModule = $this->propelSchemaParser->getModuleNameByForeignReference($foreignIdColumnName, $context->getModule()->getName());", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 113, + "line_to": 113, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\SprykerSdkDependencyFinder::getModuleNamesFromUseStatements cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/SprykerSdkDependencyFinder.php", + "snippet": " $modules = $this->getModuleNamesFromUseStatements($useStatements, $context->getModule()->getName());", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 39, + "line_to": 39, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\TwigDependencyFinder\\AtomFunctionDependencyFinder::addFindings cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/AtomFunctionDependencyFinder.php", + "snippet": " return $this->addFindings($context->getModule()->getName(), $matches, $dependencyContainer);", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 39, + "line_to": 39, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\TwigDependencyFinder\\MoleculeFunctionDependencyFinder::addFindings cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/MoleculeFunctionDependencyFinder.php", + "snippet": " return $this->addFindings($context->getModule()->getName(), $matches, $dependencyContainer);", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 39, + "line_to": 39, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\TwigDependencyFinder\\OrganismFunctionDependencyFinder::addFindings cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/OrganismFunctionDependencyFinder.php", + "snippet": " return $this->addFindings($context->getModule()->getName(), $matches, $dependencyContainer);", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 39, + "line_to": 39, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\TwigDependencyFinder\\TemplateFunctionDependencyFinder::addFindings cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TemplateFunctionDependencyFinder.php", + "snippet": " return $this->addFindings($context->getModule()->getName(), $matches, $dependencyContainer);", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 39, + "line_to": 39, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\DependencyFinder\\TwigDependencyFinder\\ViewFunctionDependencyFinder::addFindings cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/ViewFunctionDependencyFinder.php", + "snippet": " return $this->addFindings($context->getModule()->getName(), $matches, $dependencyContainer);", + "selected_text": "$context->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 61, + "line_to": 61, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\ModuleDependencyParser::dasherize cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/ModuleDependencyParser.php", + "snippet": " $moduleTransfer->setNameDashed($this->dasherize($moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 49, + "line_to": 49, + "type": "LessSpecificImplementedReturnType", + "message": "The inherited return type 'array' for Spryker\\Zed\\Development\\Business\\Dependency\\SchemaParser\\PropelSchemaParserInterface::getForeignColumnNames is more specific than the implemented return type for Spryker\\Zed\\Development\\Business\\Dependency\\SchemaParser\\PropelSchemaParser::getforeigncolumnnames 'array'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParser.php", + "snippet": " * @return array", + "selected_text": "array", + "error_level": 5, + "shortcode": 166 + }, + { + "severity": "info", + "line_from": 95, + "line_to": 95, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Dependency\\ModuleDependencyParserInterface::parseOutgoingDependencies cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/Validator/DependencyValidator.php", + "snippet": " $dependencyValidationRequestTransfer->getModule(),", + "selected_text": "$dependencyValidationRequestTransfer->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 99, + "line_to": 99, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Composer\\ComposerNameFinderInterface::findComposerNameByModuleName cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/Validator/DependencyValidator.php", + "snippet": " $composerName = $dependencyModuleTransfer->getComposerName() ?? $this->composerNameFinder->findComposerNameByModuleName($dependencyModuleTransfer->getModule());", + "selected_text": "$dependencyModuleTransfer->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 73, + "line_to": 73, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\DependencyTree\\ComposerDependencyParser::parseComposerJson cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $composerDependencyCollectionTransfer = $this->parseComposerJson($dependencyCollectionTransfer->getModule());", + "selected_text": "$dependencyCollectionTransfer->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 83, + "line_to": 83, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $currentComposerName = sprintf('%s/%s', $dependencyCollectionTransfer->getModule()->getOrganization()->getNameDashed(), $dependencyCollectionTransfer->getModule()->getNameDashed());", + "selected_text": "$dependencyCollectionTransfer->getModule()->getOrganization()->getNameDashed()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 83, + "line_to": 83, + "type": "PossiblyNullReference", + "message": "Cannot call method getOrganization on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $currentComposerName = sprintf('%s/%s', $dependencyCollectionTransfer->getModule()->getOrganization()->getNameDashed(), $dependencyCollectionTransfer->getModule()->getNameDashed());", + "selected_text": "getOrganization", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 83, + "line_to": 83, + "type": "PossiblyNullReference", + "message": "Cannot call method getNameDashed on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $currentComposerName = sprintf('%s/%s', $dependencyCollectionTransfer->getModule()->getOrganization()->getNameDashed(), $dependencyCollectionTransfer->getModule()->getNameDashed());", + "selected_text": "getNameDashed", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 83, + "line_to": 83, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $currentComposerName = sprintf('%s/%s', $dependencyCollectionTransfer->getModule()->getOrganization()->getNameDashed(), $dependencyCollectionTransfer->getModule()->getNameDashed());", + "selected_text": "$dependencyCollectionTransfer->getModule()->getNameDashed()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 83, + "line_to": 83, + "type": "PossiblyNullReference", + "message": "Cannot call method getNameDashed on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $currentComposerName = sprintf('%s/%s', $dependencyCollectionTransfer->getModule()->getOrganization()->getNameDashed(), $dependencyCollectionTransfer->getModule()->getNameDashed());", + "selected_text": "getNameDashed", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 252, + "line_to": 252, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\DependencyTree\\ComposerDependencyParser::parseDeclaredDependenciesForBundle cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $declaredDependencies = $this->parseDeclaredDependenciesForBundle($dependencyCollectionTransfer->getModule());", + "selected_text": "$dependencyCollectionTransfer->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 293, + "line_to": 293, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\DependencyTree\\ComposerDependencyParser::parseComposerJson cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $composerDependencyCollectionTransfer = $this->parseComposerJson($dependencyCollectionTransfer->getModule());", + "selected_text": "$dependencyCollectionTransfer->getModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 300, + "line_to": 300, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\DependencyTree\\ComposerDependencyParser::addDeclaredDependency cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $dependencyCollectionTransfer = $this->addDeclaredDependency($dependencyCollectionTransfer, $composerDependency->getName());", + "selected_text": "$composerDependency->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 316, + "line_to": 316, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $dependencyJsonFilePath = sprintf('%s/dependency.json', $moduleTransfer->getPath());", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 353, + "line_to": 353, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $composerJsonFilePath = sprintf('%s/composer.json', $moduleTransfer->getPath());", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 451, + "line_to": 451, + "type": "PossiblyFalseOperand", + "message": "Left operand cannot be falsable, got false|int|positive-int", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " $name = substr($package, strpos($package, '/') + 1);", + "selected_text": "strpos($package, '/')", + "error_level": 3, + "shortcode": 162 + }, + { + "severity": "info", + "line_from": 468, + "line_to": 468, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " return $moduleName === $dependencyCollectionTransfer->getModule()->getName() . 'Extension';", + "selected_text": "$dependencyCollectionTransfer->getModule()->getName()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 468, + "line_to": 468, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php", + "snippet": " return $moduleName === $dependencyCollectionTransfer->getModule()->getName() . 'Extension';", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 64, + "line_to": 64, + "type": "PossiblyFalseOperand", + "message": "Left operand cannot be falsable, got false|int", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependency.php", + "snippet": " $classNameParts = array_slice($tokens, $pointer, $endOfNew - $foundPosition - 2);", + "selected_text": "$endOfNew", + "error_level": 3, + "shortcode": 162 + }, + { + "severity": "info", + "line_from": 70, + "line_to": 70, + "type": "PossiblyFalseOperand", + "message": "Left operand cannot be falsable, got false|int", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependency.php", + "snippet": " $startOf = $file->findPrevious([T_OPEN_PARENTHESIS, T_WHITESPACE, T_OPEN_SQUARE_BRACKET], $foundPosition - 1) + 1;", + "selected_text": "$file->findPrevious([T_OPEN_PARENTHESIS, T_WHITESPACE, T_OPEN_SQUARE_BRACKET], $foundPosition - 1)", + "error_level": 3, + "shortcode": 162 + }, + { + "severity": "info", + "line_from": 117, + "line_to": 117, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/OutgoingGraphBuilder.php", + "snippet": " 'url' => '/development/dependency/outgoing-graph?bundle=' . $incomingBundle->getName(),", + "selected_text": "$incomingBundle->getName()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 119, + "line_to": 119, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Graph\\Communication\\Plugin\\GraphPlugin::addNode cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/OutgoingGraphBuilder.php", + "snippet": " $this->graph->addNode($incomingBundle->getName(), $attributes);", + "selected_text": "$incomingBundle->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 120, + "line_to": 120, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Graph\\Communication\\Plugin\\GraphPlugin::addEdge cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/OutgoingGraphBuilder.php", + "snippet": " $this->graph->addEdge($incomingBundle->getName(), $this->bundleName);", + "selected_text": "$incomingBundle->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 32, + "line_to": 32, + "type": "LessSpecificImplementedReturnType", + "message": "The inherited return type 'array' for Spryker\\Zed\\Development\\Business\\DependencyTree\\Finder\\FinderInterface::find is more specific than the implemented return type for Spryker\\Zed\\Development\\Business\\DependencyTree\\Finder\\FinderComposite::find 'array'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderComposite.php", + "snippet": " * @return array", + "selected_text": "array", + "error_level": 5, + "shortcode": 166 + }, + { + "severity": "info", + "line_from": 50, + "line_to": 50, + "type": "PossiblyNullArgument", + "message": "Argument 1 of rtrim cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/AbstractPathBuilder.php", + "snippet": " $basePath = rtrim($this->config->getPathToInternalNamespace(static::ORGANIZATION), '/');", + "selected_text": "$this->config->getPathToInternalNamespace(static::ORGANIZATION)", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 35, + "line_to": 35, + "type": "PossiblyNullArgument", + "message": "Argument 1 of rtrim cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerEcoPathBuilder.php", + "snippet": " $basePath = rtrim($this->config->getPathToInternalNamespace(static::ORGANIZATION), '/');", + "selected_text": "$this->config->getPathToInternalNamespace(static::ORGANIZATION)", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 35, + "line_to": 35, + "type": "PossiblyNullArgument", + "message": "Argument 1 of rtrim cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerSdkPathBuilder.php", + "snippet": " $basePath = rtrim($this->config->getPathToInternalNamespace(static::ORGANIZATION), '/');", + "selected_text": "$this->config->getPathToInternalNamespace(static::ORGANIZATION)", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 59, + "line_to": 59, + "type": "PossiblyNullArrayOffset", + "message": "Cannot access value on variable $bundleTransferCollection[null|string] using possibly null offset null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php", + "snippet": " $bundleTransferCollection[$bundleTransfer->getName()] = $bundleTransfer;", + "selected_text": "$bundleTransferCollection", + "error_level": 3, + "shortcode": 125 + }, + { + "severity": "info", + "line_from": 102, + "line_to": 102, + "type": "PossiblyNullArgument", + "message": "Argument 1 of array_key_exists cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php", + "snippet": " if (!array_key_exists($bundleTransfer->getName(), $bundles)) {", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 106, + "line_to": 106, + "type": "PossiblyNullArrayOffset", + "message": "Cannot access value on variable $bundles using possibly null offset null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php", + "snippet": " $existingBundleTransfer = $bundles[$bundleTransfer->getName()];", + "selected_text": "$bundles", + "error_level": 3, + "shortcode": 125 + }, + { + "severity": "info", + "line_from": 109, + "line_to": 109, + "type": "PossiblyInvalidArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\IdeAutoCompletion\\Bundle\\BundleFinder::mergeMethods expects ArrayObject, possibly different type ArrayObject|array provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php", + "snippet": " $existingBundleTransfer->getMethods(),", + "selected_text": "$existingBundleTransfer->getMethods()", + "error_level": 3, + "shortcode": 92 + }, + { + "severity": "info", + "line_from": 110, + "line_to": 110, + "type": "PossiblyInvalidArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\IdeAutoCompletion\\Bundle\\BundleFinder::mergeMethods expects ArrayObject, possibly different type ArrayObject|array provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php", + "snippet": " $bundleTransfer->getMethods(),", + "selected_text": "$bundleTransfer->getMethods()", + "error_level": 3, + "shortcode": 92 + }, + { + "severity": "info", + "line_from": 130, + "line_to": 130, + "type": "PossiblyNullArrayOffset", + "message": "Cannot access value on variable $methodsByName[null|string] using possibly null offset null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php", + "snippet": " $methodsByName[$methodTransfer->getName()] = $methodTransfer;", + "selected_text": "$methodsByName", + "error_level": 3, + "shortcode": 125 + }, + { + "severity": "info", + "line_from": 134, + "line_to": 134, + "type": "PossiblyNullArrayOffset", + "message": "Cannot access value on variable $methodsByName[null|string] using possibly null offset null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php", + "snippet": " $methodsByName[$methodTransfer->getName()] = $methodTransfer;", + "selected_text": "$methodsByName", + "error_level": 3, + "shortcode": 125 + }, + { + "severity": "info", + "line_from": 104, + "line_to": 104, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\IdeAutoCompletion\\Bundle\\MethodBuilder\\AbstractBundleMethodBuilder::getInterfaceFileName cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/AbstractBundleMethodBuilder.php", + "snippet": " $interfaceFileName = $this->getInterfaceFileName($bundleTransfer->getName());", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 127, + "line_to": 127, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\IdeAutoCompletion\\Bundle\\MethodBuilder\\AbstractBundleMethodBuilder::getClassFileName cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/AbstractBundleMethodBuilder.php", + "snippet": " $classFileName = $this->getClassFileName($bundleTransfer->getName());", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 183, + "line_to": 183, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\IdeAutoCompletion\\Bundle\\NamespaceExtractorInterface::fromDirectory cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/AbstractBundleMethodBuilder.php", + "snippet": " return $this->namespaceExtractor->fromDirectory($directory, $bundleTransfer->getBaseDirectory());", + "selected_text": "$bundleTransfer->getBaseDirectory()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 31, + "line_to": 31, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilder.php", + "snippet": " $bundleTransfer->getDirectory(),", + "selected_text": "$bundleTransfer->getDirectory()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 32, + "line_to": 32, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilder.php", + "snippet": " $bundleTransfer->getName(),", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 31, + "line_to": 31, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilder.php", + "snippet": " $bundleTransfer->getDirectory(),", + "selected_text": "$bundleTransfer->getDirectory()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 32, + "line_to": 32, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilder.php", + "snippet": " $bundleTransfer->getName(),", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 31, + "line_to": 31, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilder.php", + "snippet": " $bundleTransfer->getDirectory(),", + "selected_text": "$bundleTransfer->getDirectory()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 32, + "line_to": 32, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilder.php", + "snippet": " $bundleTransfer->getName(),", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 31, + "line_to": 31, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ResourceMethodBuilder.php", + "snippet": " $bundleTransfer->getDirectory(),", + "selected_text": "$bundleTransfer->getDirectory()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 32, + "line_to": 32, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ResourceMethodBuilder.php", + "snippet": " $bundleTransfer->getName(),", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 31, + "line_to": 31, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilder.php", + "snippet": " $bundleTransfer->getDirectory(),", + "selected_text": "$bundleTransfer->getDirectory()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 32, + "line_to": 32, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilder.php", + "snippet": " $bundleTransfer->getName(),", + "selected_text": "$bundleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 29, + "line_to": 29, + "type": "PossiblyInvalidMethodCall", + "message": "Cannot call method on possible array variable ", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/BundleMethodGenerator.php", + "snippet": " if ($moduleTransfer->getMethods()->count() === 0) {", + "selected_text": "count", + "error_level": 3, + "shortcode": 113 + }, + { + "severity": "info", + "line_from": 38, + "line_to": 38, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/BundleMethodGenerator.php", + "snippet": " $fileName = sprintf('%s.php', $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 115, + "line_to": 115, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php", + "snippet": " $moduleTransfer->getPath(),", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 116, + "line_to": 116, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php", + "snippet": " $moduleTransfer->getOrganization()->getName(),", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 116, + "line_to": 116, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php", + "snippet": " $moduleTransfer->getOrganization()->getName(),", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 117, + "line_to": 117, + "type": "PossiblyNullArgument", + "message": "Argument 4 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php", + "snippet": " $applicationTransfer->getName(),", + "selected_text": "$applicationTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 118, + "line_to": 118, + "type": "PossiblyNullArgument", + "message": "Argument 5 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php", + "snippet": " $moduleTransfer->getName(),", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 164, + "line_to": 164, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php", + "snippet": " $dependencyProviderClassName = str_replace([$moduleTransfer->getPath() . 'src/', '.php', DIRECTORY_SEPARATOR], ['', '', '\\\\'], $splFileInfo->getPathname());", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 142, + "line_to": 142, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Module\\ModuleFinder\\ModuleFinder::getComposerJsonAsArray cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " $composerJsonAsArray = $this->getComposerJsonAsArray($moduleTransfer->getPath());", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 212, + "line_to": 212, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 212, + "line_to": 212, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 212, + "line_to": 212, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 284, + "line_to": 284, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " $lookupDirectory = sprintf('%s/src/%s/', $moduleTransfer->getPath(), $moduleTransfer->getOrganization()->getName());", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 284, + "line_to": 284, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " $lookupDirectory = sprintf('%s/src/%s/', $moduleTransfer->getPath(), $moduleTransfer->getOrganization()->getName());", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 284, + "line_to": 284, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " $lookupDirectory = sprintf('%s/src/%s/', $moduleTransfer->getPath(), $moduleTransfer->getOrganization()->getName());", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 378, + "line_to": 378, + "type": "PossiblyFalseOperand", + "message": "Left operand cannot be falsable, got false|int", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " $organizationName = $pathFragments[$vendorPosition + 1];", + "selected_text": "$vendorPosition", + "error_level": 3, + "shortcode": 162 + }, + { + "severity": "info", + "line_from": 395, + "line_to": 395, + "type": "PossiblyFalseOperand", + "message": "Left operand cannot be falsable, got false|int", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php", + "snippet": " $applicationName = $pathFragments[$vendorPosition + 2];", + "selected_text": "$vendorPosition", + "error_level": 3, + "shortcode": 162 + }, + { + "severity": "info", + "line_from": 29, + "line_to": 29, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Module\\ModuleMatcher\\ModuleMatcher::matchesOrganization cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " if (!$this->matchesOrganization($moduleFilterTransfer, $moduleTransfer->getOrganization())) {", + "selected_text": "$moduleTransfer->getOrganization()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 54, + "line_to": 54, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Module\\ModuleMatcher\\ModuleMatcher::match cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " return $this->match($moduleFilterTransfer->getOrganization()->getName(), $organizationTransfer->getName());", + "selected_text": "$moduleFilterTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 54, + "line_to": 54, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " return $this->match($moduleFilterTransfer->getOrganization()->getName(), $organizationTransfer->getName());", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 54, + "line_to": 54, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Module\\ModuleMatcher\\ModuleMatcher::match cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " return $this->match($moduleFilterTransfer->getOrganization()->getName(), $organizationTransfer->getName());", + "selected_text": "$organizationTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 74, + "line_to": 74, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Module\\ModuleMatcher\\ModuleMatcher::match cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " if ($this->match($moduleFilterTransfer->getApplication()->getName(), $applicationTransfer->getName())) {", + "selected_text": "$moduleFilterTransfer->getApplication()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 74, + "line_to": 74, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " if ($this->match($moduleFilterTransfer->getApplication()->getName(), $applicationTransfer->getName())) {", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 74, + "line_to": 74, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Module\\ModuleMatcher\\ModuleMatcher::match cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " if ($this->match($moduleFilterTransfer->getApplication()->getName(), $applicationTransfer->getName())) {", + "selected_text": "$applicationTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 94, + "line_to": 94, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Module\\ModuleMatcher\\ModuleMatcher::match cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " return $this->match($moduleFilterTransfer->getModule()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleFilterTransfer->getModule()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 94, + "line_to": 94, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " return $this->match($moduleFilterTransfer->getModule()->getName(), $moduleTransfer->getName());", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 94, + "line_to": 94, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Module\\ModuleMatcher\\ModuleMatcher::match cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php", + "snippet": " return $this->match($moduleFilterTransfer->getModule()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 43, + "line_to": 43, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php", + "snippet": " $this->config->getPathToInternalNamespace(static::ORGANIZATION),", + "selected_text": "$this->config->getPathToInternalNamespace(static::ORGANIZATION)", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 56, + "line_to": 56, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php", + "snippet": " return ($moduleTransfer->getOrganization()->getName() === static::ORGANIZATION);", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 62, + "line_to": 62, + "type": "InvalidNullableReturnType", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\AbstractPathBuilder::getModuleName is not nullable, but 'null|string' contains null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php", + "snippet": " * @return string", + "selected_text": "string", + "error_level": 5, + "shortcode": 144 + }, + { + "severity": "info", + "line_from": 66, + "line_to": 66, + "type": "NullableReturnStatement", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\AbstractPathBuilder::getModuleName is not nullable, but the function returns 'null|string'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php", + "snippet": " return $moduleTransfer->getName();", + "selected_text": "$moduleTransfer->getName()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 22, + "line_to": 22, + "type": "InvalidNullableReturnType", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\SprykerEcoModulePathBuilder::getModuleName is not nullable, but 'null|string' contains null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerEcoModulePathBuilder.php", + "snippet": " * @return string", + "selected_text": "string", + "error_level": 5, + "shortcode": 144 + }, + { + "severity": "info", + "line_from": 26, + "line_to": 26, + "type": "NullableReturnStatement", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\SprykerEcoModulePathBuilder::getModuleName is not nullable, but the function returns 'null|string'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerEcoModulePathBuilder.php", + "snippet": " return $moduleTransfer->getNameDashed();", + "selected_text": "$moduleTransfer->getNameDashed()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 22, + "line_to": 22, + "type": "InvalidNullableReturnType", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\SprykerSdkModulePathBuilder::getModuleName is not nullable, but 'null|string' contains null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerSdkModulePathBuilder.php", + "snippet": " * @return string", + "selected_text": "string", + "error_level": 5, + "shortcode": 144 + }, + { + "severity": "info", + "line_from": 26, + "line_to": 26, + "type": "NullableReturnStatement", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\SprykerSdkModulePathBuilder::getModuleName is not nullable, but the function returns 'null|string'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerSdkModulePathBuilder.php", + "snippet": " return $moduleTransfer->getNameDashed();", + "selected_text": "$moduleTransfer->getNameDashed()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 40, + "line_to": 40, + "type": "InvalidNullableReturnType", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\SprykerStandaloneModulePathBuilder::getModuleName is not nullable, but 'null|string' contains null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerStandaloneModulePathBuilder.php", + "snippet": " * @return string", + "selected_text": "string", + "error_level": 5, + "shortcode": 144 + }, + { + "severity": "info", + "line_from": 44, + "line_to": 44, + "type": "NullableReturnStatement", + "message": "The declared return type 'string' for Spryker\\Zed\\Development\\Business\\Module\\PathBuilder\\SprykerStandaloneModulePathBuilder::getModuleName is not nullable, but the function returns 'null|string'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerStandaloneModulePathBuilder.php", + "snippet": " return $moduleTransfer->getNameDashed();", + "selected_text": "$moduleTransfer->getNameDashed()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 200, + "line_to": 200, + "type": "PossiblyFalseOperand", + "message": "Left operand cannot be falsable, got false|int", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php", + "snippet": " $organizationName = $pathFragments[$srcPosition + 1];", + "selected_text": "$srcPosition", + "error_level": 3, + "shortcode": 162 + }, + { + "severity": "info", + "line_from": 217, + "line_to": 217, + "type": "PossiblyFalseOperand", + "message": "Left operand cannot be falsable, got false|int", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php", + "snippet": " $organizationName = $pathFragments[$srcPosition + 2];", + "selected_text": "$srcPosition", + "error_level": 3, + "shortcode": 162 + }, + { + "severity": "info", + "line_from": 239, + "line_to": 239, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 239, + "line_to": 239, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 239, + "line_to": 239, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 52, + "line_to": 52, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Package/PackageFinder/PackageFinder.php", + "snippet": " $packageCollectionKey = sprintf('%s.%s', $packageTransfer->getOrganizationName(), $packageTransfer->getPackageName());", + "selected_text": "$packageTransfer->getOrganizationName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 52, + "line_to": 52, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Package/PackageFinder/PackageFinder.php", + "snippet": " $packageCollectionKey = sprintf('%s.%s', $packageTransfer->getOrganizationName(), $packageTransfer->getPackageName());", + "selected_text": "$packageTransfer->getPackageName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 131, + "line_to": 131, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Package\\PackageFinder\\PackageFinder::getComposerJsonAsArray cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Package/PackageFinder/PackageFinder.php", + "snippet": " $composerJsonAsArray = $this->getComposerJsonAsArray($packageTransfer->getPath());", + "selected_text": "$packageTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 60, + "line_to": 60, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\PhpMd\\PhpMdRunner::resolvePath cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php", + "snippet": " $path = $this->resolvePath($bundle);", + "selected_text": "$bundle", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 182, + "line_to": 182, + "type": "NullableReturnStatement", + "message": "The declared return type 'int' for Spryker\\Zed\\Development\\Business\\PhpMd\\PhpMdRunner::runPhpMdCommand is not nullable, but the function returns 'int|null'", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php", + "snippet": " return $process->getExitCode();", + "selected_text": "$process->getExitCode()", + "error_level": 5, + "shortcode": 139 + }, + { + "severity": "info", + "line_from": 80, + "line_to": 80, + "type": "PossiblyNullArgument", + "message": "Argument 1 of strpos cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php", + "snippet": " if (strpos($fileName, 'Cest.php') !== false) {", + "selected_text": "$fileName", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 390, + "line_to": 390, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Phpstan\\PhpstanRunner::getVendorPathByNamespace cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php", + "snippet": " $vendorDirectoryPath = $this->getVendorPathByNamespace($namespace);", + "selected_text": "$namespace", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 393, + "line_to": 393, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\Phpstan\\Config\\PhpstanConfigFileFinderInterface::searchIn cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php", + "snippet": " ->searchIn($vendorDirectoryPath);", + "selected_text": "$vendorDirectoryPath", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 398, + "line_to": 398, + "type": "PossiblyNullArgument", + "message": "Argument 2 of Spryker\\Zed\\Development\\Business\\Phpstan\\Config\\PhpstanConfigFileManagerInterface::merge cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php", + "snippet": " $this->getConfigFilenameForMerge($moduleConfigFile),", + "selected_text": "$this->getConfigFilenameForMerge($moduleConfigFile)", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 447, + "line_to": 447, + "type": "PossiblyNullArgument", + "message": "Argument 1 of dirname cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php", + "snippet": " return dirname($pathToModules) . DIRECTORY_SEPARATOR;", + "selected_text": "$pathToModules", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 67, + "line_to": 67, + "type": "PossiblyNullArrayAssignment", + "message": "Cannot access array value on possibly null variable $this->bundles[$currentBundleName]['out'] of type mixed|null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Stability/StabilityCalculator.php", + "snippet": " $this->bundles[$currentBundleName]['out'][$outgoingBundleName] = $outgoingBundleName;", + "selected_text": "$this->bundles[$currentBundleName]['out']", + "error_level": 3, + "shortcode": 120 + }, + { + "severity": "info", + "line_from": 68, + "line_to": 68, + "type": "PossiblyNullArrayAssignment", + "message": "Cannot access array value on possibly null variable $this->bundles[$outgoingBundleName]['in'] of type mixed|null", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Stability/StabilityCalculator.php", + "snippet": " $this->bundles[$outgoingBundleName]['in'][$currentBundleName] = $currentBundleName;", + "selected_text": "$this->bundles[$outgoingBundleName]['in']", + "error_level": 3, + "shortcode": 120 + }, + { + "severity": "info", + "line_from": 324, + "line_to": 324, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 324, + "line_to": 324, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 324, + "line_to": 324, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php", + "snippet": " return sprintf('%s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName());", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 134, + "line_to": 134, + "type": "PossiblyNullArgument", + "message": "Argument 3 of Spryker\\Zed\\Development\\Communication\\Console\\CodeArchitectureSnifferConsole::runForCore cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php", + "snippet": " $success = $this->runForCore($output, $module, $path);", + "selected_text": "$path", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 141, + "line_to": 141, + "type": "PossiblyNullArgument", + "message": "Argument 3 of Spryker\\Zed\\Development\\Communication\\Console\\CodeArchitectureSnifferConsole::runForProject cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php", + "snippet": " $success = $this->runForProject($output, $module, $path);", + "selected_text": "$path", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 253, + "line_to": 253, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\CodeArchitectureSnifferConsole::buildPath cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php", + "snippet": " return $this->buildPath($moduleTransfer->getPath(), $pathSuffix);", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 264, + "line_to": 264, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php", + "snippet": " return rtrim($path . $suffix, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;", + "selected_text": "$suffix", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 458, + "line_to": 458, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php", + "snippet": " $customPath = $pathToRoot . $path;", + "selected_text": "$path", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 111, + "line_to": 111, + "type": "PossiblyNullArgument", + "message": "Argument 1 of strpos cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/CodeStyleSnifferConsole.php", + "snippet": " $isCore = strpos($module, '.') !== false;", + "selected_text": "$module", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 70, + "line_to": 70, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/ComposerJsonUpdaterConsole.php", + "snippet": " $module,", + "selected_text": "$module", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 120, + "line_to": 120, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Symfony\\Component\\Console\\Output\\OutputInterface::writeln cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/ComposerJsonValidatorConsole.php", + "snippet": " $this->output->writeln($validationMessageTransfer->getMessage());", + "selected_text": "$validationMessageTransfer->getMessage()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 211, + "line_to": 211, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'Composer name' => sprintf('%s', $color, $composerName),", + "selected_text": "$composerName", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 212, + "line_to": 212, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getColoredYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'is valid' => $this->getColoredYesOrNo($moduleDependencyTransfer->getIsValid()),", + "selected_text": "$moduleDependencyTransfer->getIsValid()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 213, + "line_to": 213, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'src dependency' => $this->getYesOrNo($moduleDependencyTransfer->getIsSrcDependency()),", + "selected_text": "$moduleDependencyTransfer->getIsSrcDependency()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 214, + "line_to": 214, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'test dependency' => $this->getYesOrNo($moduleDependencyTransfer->getIsTestDependency()),", + "selected_text": "$moduleDependencyTransfer->getIsTestDependency()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 215, + "line_to": 215, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'in composer require' => $this->getYesOrNo($moduleDependencyTransfer->getIsInComposerRequire()),", + "selected_text": "$moduleDependencyTransfer->getIsInComposerRequire()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 216, + "line_to": 216, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'in composer require-dev' => $this->getYesOrNo($moduleDependencyTransfer->getIsInComposerRequireDev()),", + "selected_text": "$moduleDependencyTransfer->getIsInComposerRequireDev()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 217, + "line_to": 217, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'in composer suggest' => $this->getYesOrNo($moduleDependencyTransfer->getIsSuggested()),", + "selected_text": "$moduleDependencyTransfer->getIsSuggested()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 218, + "line_to": 218, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'is optional dependency' => $this->getYesOrNo($moduleDependencyTransfer->getIsOptionalDependency()),", + "selected_text": "$moduleDependencyTransfer->getIsOptionalDependency()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 219, + "line_to": 219, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Communication\\Console\\DependencyViolationFinderConsole::getYesOrNo cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php", + "snippet": " 'is own extension module' => $this->getYesOrNo($moduleDependencyTransfer->getIsOwnExtensionModule()),", + "selected_text": "$moduleDependencyTransfer->getIsOwnExtensionModule()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 90, + "line_to": 90, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('No dependency issues found in %s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 90, + "line_to": 90, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('No dependency issues found in %s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 90, + "line_to": 90, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('No dependency issues found in %s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 111, + "line_to": 111, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('Could not get a composer name for \"%s\"', $moduleDependencyTransfer->getModuleName()));", + "selected_text": "$moduleDependencyTransfer->getModuleName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 112, + "line_to": 112, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('Please check the module %s.%s manually.', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 112, + "line_to": 112, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('Please check the module %s.%s manually.', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 112, + "line_to": 112, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('Please check the module %s.%s manually.', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 120, + "line_to": 120, + "type": "PossiblyNullArgument", + "message": "Argument 2 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('Fixed dependencies in %s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getOrganization()->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 120, + "line_to": 120, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('Fixed dependencies in %s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 120, + "line_to": 120, + "type": "PossiblyNullArgument", + "message": "Argument 3 of sprintf cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $this->output->writeln(sprintf('Fixed dependencies in %s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()));", + "selected_text": "$moduleTransfer->getName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 137, + "line_to": 137, + "type": "PossiblyNullArgument", + "message": "Argument 1 of Spryker\\Zed\\Development\\Business\\DevelopmentFacadeInterface::findComposerNameByModuleName cannot be null, possibly null value provided", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " return $this->getFacade()->findComposerNameByModuleName($moduleDependencyTransfer->getModuleName());", + "selected_text": "$moduleDependencyTransfer->getModuleName()", + "error_level": 3, + "shortcode": 78 + }, + { + "severity": "info", + "line_from": 150, + "line_to": 150, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $composerJsonFile = $moduleTransfer->getPath() . '/composer.json';", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 168, + "line_to": 168, + "type": "PossiblyNullOperand", + "message": "Cannot concatenate with a possibly null null|string", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php", + "snippet": " $composerJsonFile = $moduleTransfer->getPath() . '/composer.json';", + "selected_text": "$moduleTransfer->getPath()", + "error_level": 1, + "shortcode": 80 + }, + { + "severity": "info", + "line_from": 46, + "line_to": 46, + "type": "RedundantFunctionCall", + "message": "The call to ksort is unnecessary, non-empty-list is already a list", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Controller/ArchitectureController.php", + "snippet": " ksort($collection);", + "selected_text": "ksort", + "error_level": 4, + "shortcode": 280 + }, + { + "severity": "info", + "line_from": 83, + "line_to": 83, + "type": "PossiblyNullReference", + "message": "Cannot call method getOrganization on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Controller/DependencyProviderPluginUsageController.php", + "snippet": " 'organization' => $dependencyProviderTransfer->getModule()->getOrganization()->getName(),", + "selected_text": "getOrganization", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 83, + "line_to": 83, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Controller/DependencyProviderPluginUsageController.php", + "snippet": " 'organization' => $dependencyProviderTransfer->getModule()->getOrganization()->getName(),", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + }, + { + "severity": "info", + "line_from": 84, + "line_to": 84, + "type": "PossiblyNullReference", + "message": "Cannot call method getName on possibly null value", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Controller/DependencyProviderPluginUsageController.php", + "snippet": " 'module' => $dependencyProviderTransfer->getModule()->getName(),", + "selected_text": "getName", + "error_level": 3, + "shortcode": 83 + } + ], + "deprecation": [ + { + "severity": "info", + "line_from": 55, + "line_to": 55, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\Business\\Dependency\\DependencyContainer\\DependencyContainer::makeOptionalIfSilex has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainer.php", + "snippet": " $isOptional = $this->makeOptionalIfSilex($moduleName, $isOptional);", + "selected_text": "makeOptionalIfSilex", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 102, + "line_to": 102, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\DevelopmentConfig::getPathToCore has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php", + "snippet": " return $this->config->getPathToCore();", + "selected_text": "getPathToCore", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 124, + "line_to": 124, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\DevelopmentConfig::getPathToCore has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php", + "snippet": " return $this->config->getPathToCore() . $bundle . DIRECTORY_SEPARATOR;", + "selected_text": "getPathToCore", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 55, + "line_to": 55, + "type": "DeprecatedConstant", + "message": "Constant Spryker\\Zed\\Development\\Communication\\Console\\CodePhpstanConsole::OPTION_FORMAT is deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/Communication/Console/CodePhpstanConsole.php", + "snippet": " $this->addOption(static::OPTION_FORMAT, 'f', InputOption::VALUE_OPTIONAL, 'Output format [text, xml, json, md]');", + "selected_text": "static::OPTION_FORMAT", + "error_level": 2, + "shortcode": 170 + }, + { + "severity": "info", + "line_from": 141, + "line_to": 141, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\DevelopmentConfig::getPathToCore has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/DevelopmentConfig.php", + "snippet": " $this->getPathToCore() . '%1$s/src/Spryker/Zed/%1$s/Presentation/',", + "selected_text": "getPathToCore", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 142, + "line_to": 142, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\DevelopmentConfig::getPathToCore has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/DevelopmentConfig.php", + "snippet": " $this->getPathToCore() . '%1$s/src/Spryker/Yves/%1$s/Theme/',", + "selected_text": "getPathToCore", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 143, + "line_to": 143, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\DevelopmentConfig::getPathToShop has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/DevelopmentConfig.php", + "snippet": " $this->getPathToShop() . '%1$s/src/SprykerShop/Yves/%1$s/Theme/',", + "selected_text": "getPathToShop", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 253, + "line_to": 253, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\DevelopmentConfig::getPathToCore has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/DevelopmentConfig.php", + "snippet": " 'Spryker' => $this->getPathToCore(),", + "selected_text": "getPathToCore", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 254, + "line_to": 254, + "type": "DeprecatedMethod", + "message": "The method Spryker\\Zed\\Development\\DevelopmentConfig::getPathToEco has been marked as deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/DevelopmentConfig.php", + "snippet": " 'SprykerEco' => $this->getPathToEco(),", + "selected_text": "getPathToEco", + "error_level": 2, + "shortcode": 1 + }, + { + "severity": "info", + "line_from": 778, + "line_to": 778, + "type": "DeprecatedConstant", + "message": "Constant Spryker\\Shared\\Kernel\\KernelConstants::SPRYKER_ROOT is deprecated", + "file_name": "vendor/spryker/spryker/Bundles/Development/src/Spryker/Zed/Development/DevelopmentConfig.php", + "snippet": " $path = $this->getConfig()->get(KernelConstants::SPRYKER_ROOT);", + "selected_text": "KernelConstants::SPRYKER_ROOT", + "error_level": 2, + "shortcode": 170 + } + ], + "count": 254 +} diff --git a/src/Spryker/Zed/Development/Business/PhpMd/ruleset.xml b/resources/phpmd/ruleset.xml similarity index 54% rename from src/Spryker/Zed/Development/Business/PhpMd/ruleset.xml rename to resources/phpmd/ruleset.xml index 71f488b4..1db4e664 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/ruleset.xml +++ b/resources/phpmd/ruleset.xml @@ -1,13 +1,13 @@ - + - Spryker Php Mess Detector rule set + Spryker PHP Mess Detector rule set tests/_data @@ -19,20 +19,22 @@ */Generated/* - - + + - - + + - + 2 - + - + 2 - + - - - + + + - + - + - + - - + + - + - + Detects when a field, local, or parameter has a very short name. @@ -152,11 +162,13 @@ class Something { - + 1 - - + + + + + Spryker Coding Standard for Spryker Core. + + Extends main Spryker Coding Standard. + All sniffs in ./Sniffs will be auto loaded + + + + + */tests/_support/_generated/* + */tests/_helpers/* + */tests/_output/* + */node_modules/* + + + + + + + + + + + + + diff --git a/rulesetStrict.xml b/rulesetStrict.xml new file mode 100644 index 00000000..fc14211c --- /dev/null +++ b/rulesetStrict.xml @@ -0,0 +1,28 @@ + + + + Spryker Coding Standard for SprykerShop. + + Extends main Spryker Coding Standard. + All sniffs in ./Sniffs will be auto loaded + + + + + */tests/_support/_generated/* + */tests/_helpers/* + */tests/_output/* + */node_modules/* + + + + + + + + + + + + + diff --git a/src/Spryker/Shared/Development/DevelopmentConstants.php b/src/Spryker/Shared/Development/DevelopmentConstants.php index cab1da5d..217dddbd 100644 --- a/src/Spryker/Shared/Development/DevelopmentConstants.php +++ b/src/Spryker/Shared/Development/DevelopmentConstants.php @@ -12,17 +12,32 @@ */ interface DevelopmentConstants { + /** + * @var string + */ public const COMPOSER_REQUIRE_VERSION = 'COMPOSER_REQUIRE_VERSION'; + + /** + * @var string + */ public const COMPOSER_REQUIRE_VERSION_EXTERNAL = 'COMPOSER_REQUIRE_VERSION_EXTERNAL'; + + /** + * @var string + */ public const COMPOSER_BRANCH_ALIAS = 'COMPOSER_BRANCH_ALIAS'; /** * @see \Spryker\Shared\Kernel\KernelConstants::PROJECT_NAMESPACES + * + * @var string */ public const PROJECT_NAMESPACES = 'PROJECT_NAMESPACES'; /** * @see \Spryker\Shared\Kernel\KernelConstants::CORE_NAMESPACES + * + * @var string */ public const CORE_NAMESPACES = 'CORE_NAMESPACES'; @@ -31,6 +46,8 @@ interface DevelopmentConstants * - Sets the permission mode for generated directories. * * @api + * + * @var string */ public const DIRECTORY_PERMISSION = 'DEVELOPMENT:DIRECTORY_PERMISSION'; } diff --git a/src/Spryker/Shared/Development/Transfer/development.transfer.xml b/src/Spryker/Shared/Development/Transfer/development.transfer.xml index 18d433bc..d8f23514 100644 --- a/src/Spryker/Shared/Development/Transfer/development.transfer.xml +++ b/src/Spryker/Shared/Development/Transfer/development.transfer.xml @@ -1,9 +1,5 @@ - + @@ -27,11 +23,13 @@ + + @@ -53,7 +51,8 @@ - + + @@ -69,7 +68,7 @@ - + @@ -82,7 +81,9 @@ - + + + @@ -91,7 +92,7 @@ - + @@ -151,7 +152,7 @@ - + @@ -166,4 +167,11 @@ + + + + + + + diff --git a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinder.php b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinder.php index 54087e51..f4334f00 100644 --- a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinder.php +++ b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinder.php @@ -8,9 +8,12 @@ namespace Spryker\Zed\Development\Business\ArchitectureSniffer; use InvalidArgumentException; +use Laminas\Filter\FilterInterface; use Symfony\Component\Finder\Finder; -use Zend\Filter\FilterInterface; +/** + * @deprecated Use {@link AllModuleFinder} instead. + */ class AllBundleFinder implements AllBundleFinderInterface { /** @@ -19,25 +22,25 @@ class AllBundleFinder implements AllBundleFinderInterface protected $finder; /** - * @var \Zend\Filter\FilterInterface + * @var \Laminas\Filter\FilterInterface */ protected $filter; /** - * @var array + * @var array */ protected $projectNamespaces; /** - * @var array + * @var array */ protected $coreNamespaces; /** * @param \Symfony\Component\Finder\Finder $finder - * @param \Zend\Filter\FilterInterface $filter - * @param array $projectNamespaces - * @param array $coreNamespaces + * @param \Laminas\Filter\FilterInterface $filter + * @param array $projectNamespaces + * @param array $coreNamespaces */ public function __construct(Finder $finder, FilterInterface $filter, $projectNamespaces = [], $coreNamespaces = []) { @@ -65,21 +68,22 @@ public function find() /** * @param string $path * @param string $namespace - * @param array $allBundles + * @param array> $allBundles * - * @return array + * @return array> */ protected function findBundles($path, $namespace, array $allBundles) { - $directories = []; - try { + /** @var array<\SplFileInfo> $directories */ $directories = (new Finder()) ->directories() ->in($path) - ->depth('== 0'); + ->depth('== 0') + ->sortByName(); } catch (InvalidArgumentException $e) { // ~ Directory does not exist. It's not an error. + return $allBundles; } foreach ($directories as $dir) { @@ -94,9 +98,9 @@ protected function findBundles($path, $namespace, array $allBundles) } /** - * @param array $allBundles + * @param array> $allBundles * - * @return array + * @return array> */ protected function loadProjectBundles(array $allBundles) { @@ -104,26 +108,28 @@ protected function loadProjectBundles(array $allBundles) $path = APPLICATION_SOURCE_DIR . '/' . $projectNamespace . '/*'; $allBundles = $this->findBundles($path, $projectNamespace, $allBundles); } + return $allBundles; } /** - * @param array $allBundles + * @param array> $allBundles * - * @return array + * @return array> */ protected function loadCoreDevelopmentBundles(array $allBundles) { $path = APPLICATION_VENDOR_DIR . '/spryker/spryker/Bundles/*/src/Spryker/*'; $namespace = 'Spryker'; $allBundles = $this->findBundles($path, $namespace, $allBundles); + return $allBundles; } /** - * @param array $allBundles + * @param array> $allBundles * - * @return array + * @return array> */ protected function loadOtherCoreBundles(array $allBundles) { @@ -134,13 +140,14 @@ protected function loadOtherCoreBundles(array $allBundles) $path = APPLICATION_VENDOR_DIR . '/' . $namespaceDir . '/*/src/*/*'; $allBundles = $this->findBundles($path, $coreNamespace, $allBundles); } + return $allBundles; } /** - * @param array $allBundles + * @param array> $allBundles * - * @return mixed + * @return array> */ protected function addApplication(array $allBundles) { @@ -148,6 +155,7 @@ protected function addApplication(array $allBundles) $expl = explode('/', $bundleData['directory']); $allBundles[$i]['application'] = $expl[count($expl) - 2]; } + return $allBundles; } } diff --git a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinderInterface.php b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinderInterface.php index 18ffb6fb..9b963019 100644 --- a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllBundleFinderInterface.php @@ -7,6 +7,9 @@ namespace Spryker\Zed\Development\Business\ArchitectureSniffer; +/** + * @deprecated Use {@link AllModuleFinderInterface} instead. + */ interface AllBundleFinderInterface { /** diff --git a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllModuleFinder.php b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllModuleFinder.php new file mode 100644 index 00000000..e7178f23 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllModuleFinder.php @@ -0,0 +1,176 @@ +finder = $finder; + $this->developmentConfig = $developmentConfig; + $this->filter = $filter; + } + + /** + * @return array + */ + public function find(): array + { + $modules = []; + $modules[] = $this->loadProjectModules(); + $modules[] = $this->loadCoreDevelopmentModules(); + $modules[] = $this->loadFeaturesDevelopmentModules(); + $modules[] = $this->loadOtherCoreModules(); + + return $this->addApplication(array_merge(...$modules)); + } + + /** + * @return array + */ + protected function loadProjectModules(): array + { + $modules = []; + foreach ($this->developmentConfig->getProjectNamespaces() as $projectNamespace) { + $path = APPLICATION_SOURCE_DIR . '/' . $projectNamespace . '/*'; + $modules = $this->findModules($path, $projectNamespace); + } + + return $modules; + } + + /** + * @return array + */ + protected function loadCoreDevelopmentModules(): array + { + $modules = []; + foreach ($this->developmentConfig->getInternalNamespacesList() as $internalNamespace) { + foreach (range('A', 'Z') as $letter) { + $namespaceDir = $this->filter->filter($internalNamespace); + $namespaceDir = strtolower($namespaceDir); + + $path = sprintf('%s/spryker/%s/Bundles/%s*/src/*/*', APPLICATION_VENDOR_DIR, $namespaceDir, $letter); + $modules[] = $this->findModules($path, $internalNamespace); + } + } + + return array_merge(...$modules); + } + + /** + * @return array + */ + protected function loadFeaturesDevelopmentModules(): array + { + $modules = []; + + foreach (range('A', 'Z') as $letter) { + $path = sprintf('%s/spryker/%s/Features/%s*/src/*/*', APPLICATION_VENDOR_DIR, 'spryker', $letter); + $modules[] = $this->findModules($path, $this->developmentConfig->getSprykerFeatureNamespace()); + } + + return array_merge(...$modules); + } + + /** + * @return array + */ + protected function loadOtherCoreModules(): array + { + $modules = []; + foreach ($this->developmentConfig->getCoreNamespaces() as $coreNamespace) { + foreach (range('a', 'z') as $letter) { + $namespaceDir = $this->filter->filter($coreNamespace); + $namespaceDir = strtolower($namespaceDir); + + $path = sprintf('%s/%s/%s*/src/*/*', APPLICATION_VENDOR_DIR, $namespaceDir, $letter); + $modules[] = $this->findModules($path, $coreNamespace); + } + } + + return array_merge(...$modules); + } + + /** + * @param string $path + * @param string $namespace + * + * @return array + */ + protected function findModules($path, $namespace): array + { + $finder = clone $this->finder; + + try { + /** @var array<\SplFileInfo> $directories */ + $directories = $finder + ->directories() + ->in($path) + ->depth('== 0'); + } catch (InvalidArgumentException $e) { + // ~ Directory does not exist. It's not an error. + return []; + } + + if (!$directories) { + return []; + } + + $modules = []; + foreach ($directories as $dir) { + $modules[] = [ + 'bundle' => $dir->getFileName(), + 'namespace' => $namespace, + 'directory' => $dir->getPathName(), + ]; + } + + return $modules; + } + + /** + * @param array> $modules + * + * @return array> + */ + protected function addApplication(array $modules): array + { + foreach ($modules as $i => $moduleData) { + $moduleDataExploded = explode('/', $moduleData['directory']); + $modules[$i]['application'] = $moduleDataExploded[count($moduleDataExploded) - 2]; + } + + return $modules; + } +} diff --git a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllModuleFinderInterface.php b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllModuleFinderInterface.php new file mode 100644 index 00000000..c5dc82fc --- /dev/null +++ b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/AllModuleFinderInterface.php @@ -0,0 +1,16 @@ + $options * - * @return array + * @return array> */ - public function run($directory, array $options = []) + public function run($directory, array $options = []): array { $options = $this->configurationBuilder->getConfiguration($directory, $options); if ($options === []) { - return $this->formatResult($options); + return []; } if ($this->isCoreModule($options)) { @@ -124,22 +213,95 @@ public function run($directory, array $options = []) $results = $this->getResultsWithoutIgnoredErrors($results, $options); $fileViolations = $this->formatResult($results); - return $fileViolations; + return $this->runAnalyzer($fileViolations, $directory, $options); } /** - * @param string $command + * @param array>> $fileViolations + * @param string $directory + * @param array $options + * + * @return array> + */ + protected function runAnalyzer(array $fileViolations, $directory, array $options): array + { + $reportPath = APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . static::ARCHITECTURE_BASELINE_JSON; + if ($this->isCoreModule($options)) { + $reportPath = dirname($directory) . DIRECTORY_SEPARATOR . static::ARCHITECTURE_BASELINE_JSON; + } + + $reportFileExists = file_exists($reportPath); + $result = $this->formatViolations($fileViolations); + $reportResult = $reportFileExists ? $this->getReportResult($reportPath) : []; + + if ($options[static::OPTION_UPDATE] || !$reportFileExists) { + $this->saveBaseline($result, $reportPath); + } + + if (!$result) { + $result = $reportResult; + } + + return $this->sortViolations($result, $reportResult); + } + + /** + * @param array $result + * @param string $reportPath + * + * @throws \RuntimeException + * + * @return void + */ + protected function saveBaseline(array $result, $reportPath): void + { + $content = json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + if ($content === false) { + throw new RuntimeException('Error encoding:' . json_last_error()); + } + + $content .= PHP_EOL; + + file_put_contents($reportPath, $content); + } + + /** + * @param array $result + * @param array $reportResult + * + * @return array + */ + protected function sortViolations(array $result, array $reportResult): array + { + $sortedViolations = [ + static::NAME_VISIBLE_VIOLATIONS => [], + static::NAME_IGNORED_VIOLATIONS => [], + ]; + + foreach ($result as $key => $violations) { + if (array_search($violations[static::VIOLATION_FIELD_NAME_DESCRIPTION], array_column($reportResult, static::VIOLATION_FIELD_NAME_DESCRIPTION)) !== false) { + $sortedViolations[static::NAME_IGNORED_VIOLATIONS][] = $result[$key]; + } else { + $sortedViolations[static::NAME_VISIBLE_VIOLATIONS][] = $result[$key]; + } + } + + return $sortedViolations; + } + + /** + * @param array $command * * @return \Symfony\Component\Process\Process */ - protected function getProcess($command) + protected function getProcess(array $command) { - return new Process($command, null, null, null, 0); + return new Process($command, APPLICATION_ROOT_DIR, null, null, 0); } /** * @param string $directory - * @param array $options + * @param array $options * * @throws \Exception * @@ -147,38 +309,158 @@ protected function getProcess($command) */ protected function runCommand($directory, array $options = []) { - $command = str_replace(DevelopmentConfig::BUNDLE_PLACEHOLDER, $directory, $this->command); - - $command .= ' --minimumpriority ' . $options[static::OPTION_PRIORITY]; + $command = $this->resolveRulesetPath($directory); + $command = explode(' ', str_replace(DevelopmentConfig::BUNDLE_PLACEHOLDER, $directory, $command)); + $command[] = '--minimumpriority'; + $command[] = $options[static::OPTION_PRIORITY]; if (!empty($options[static::OPTION_STRICT])) { - $command .= ' --strict'; + $command[] = '--strict'; } if (!empty($options[static::OPTION_DRY_RUN])) { $this->displayAndExit($command); } - $p = $this->getProcess($command); - - $p->setWorkingDirectory(APPLICATION_ROOT_DIR); - $p->run(); - if (substr($p->getOutput(), 0, 5) !== 'getExitCodeText()); + $process = $this->getProcess($command); + $process->run(); + + if (substr($process->getOutput(), 0, 5) !== 'getExitCodeText(), + $process->getOutput(), + $process->getErrorOutput(), + ), + ); } - $output = $p->getOutput(); + $output = $process->getOutput(); + return $output; } /** - * @param string $command + * @param string $directory + * + * @return string + */ + protected function resolveRulesetPath(string $directory): string + { + $architecturalRulesetFilepath = dirname($directory) . DIRECTORY_SEPARATOR . static::CUSTOM_RULESET; + + if (file_exists($architecturalRulesetFilepath) === true) { + return $this->createCommand($architecturalRulesetFilepath); + } + $parentDirectory = dirname(dirname($directory)); + $parentArchitecturalRulesetFilepath = $parentDirectory . DIRECTORY_SEPARATOR . static::CUSTOM_RULESET; + + if (file_exists($parentArchitecturalRulesetFilepath) === true) { + return $this->createCommand($parentArchitecturalRulesetFilepath); + } + + return $this->command; + } + + /** + * @param string $architecturalRulesetFilepath + * + * @return string + */ + protected function createCommand(string $architecturalRulesetFilepath): string + { + $command = $this->command; + + return preg_replace( + static::DEFAULT_RULESET_PATTERN, + sprintf(static::REPLACEMENT_PLACEHOLDER, $architecturalRulesetFilepath), + $command, + ); + } + + /** + * @param array>> $array + * + * @return array> + */ + protected function formatViolations(array $array): array + { + $result = []; + + foreach ($array as $file => $violations) { + foreach ($violations as $violation) { + $result[] = [ + static::VIOLATION_FIELD_NAME_FILENAME => $this->normalizeProjectPath($file), + static::VIOLATION_FIELD_NAME_DESCRIPTION => $this->cleanDescription($violation['_']), + static::VIOLATION_FIELD_NAME_RULE => $violation['rule'], + static::VIOLATION_FIELD_NAME_RULESET => $violation['ruleset'], + static::VIOLATION_FIELD_NAME_PRIORITY => $violation['priority'], + ]; + } + } + + return $result; + } + + /** + * @param string $path + * + * @return string + */ + protected function normalizeProjectPath(string $path): string + { + $basePath = rtrim(APPLICATION_ROOT_DIR, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + + $path = str_replace($basePath, '', $path); + $pos = strpos($path, DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR); + if ($pos) { + $path = substr($path, $pos + 1); + } + + return $path; + } + + /** + * @param string $description + * + * @return string + */ + protected function cleanDescription(string $description): string + { + return trim($description); + } + + /** + * @param string $path + * + * @throws \RuntimeException + * + * @return array + */ + protected function getReportResult(string $path): array + { + $content = file_get_contents($path); + if ($content === false) { + throw new RuntimeException('Invalid content: ' . $path); + } + + $result = json_decode($content, true); + if ($result === null) { + throw new RuntimeException('Invalid JSON file: ' . $path); + } + + return $result; + } + + /** + * @param array $command * * @return void */ - protected function displayAndExit($command) + protected function displayAndExit(array $command) { - exit($command . PHP_EOL); + exit(implode(' ', $command) . PHP_EOL); } /** @@ -228,6 +510,7 @@ protected function formatMultiFileResults(array $results, array $fileViolations) } } } + return $fileViolations; } @@ -242,12 +525,15 @@ protected function formatSingleFileResults(array $results, array $fileViolations if (array_key_exists('violation', $results['file'])) { if (array_key_exists('_', $results['file']['violation'])) { $fileViolations[$results['file']['name']][] = $results['file']['violation']; + return $fileViolations; } else { $fileViolations[$results['file']['name']] = $results['file']['violation']; + return $fileViolations; } } + return $fileViolations; } @@ -262,7 +548,7 @@ protected function addSourcePathForCoreModulePath(string $directory): string } /** - * @param array $options + * @param array $options * * @return bool */ @@ -279,7 +565,7 @@ protected function isCoreModule(array $options): bool /** * @param array $results - * @param array $options + * @param array $options * * @return array */ @@ -318,7 +604,7 @@ protected function getResultsWithoutIgnoredErrors(array $results, array $options /** * @param array $fileResult - * @param string[] $ignoreErrorPatterns + * @param array $ignoreErrorPatterns * * @return array */ @@ -353,7 +639,7 @@ protected function filterOutIgnoredErrors(array $fileResult, array $ignoreErrorP /** * @param array $violation - * @param string[] $ignoreErrorPatterns + * @param array $ignoreErrorPatterns * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/ArchitectureSnifferInterface.php b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/ArchitectureSnifferInterface.php index 7411ef93..4af27d7e 100644 --- a/src/Spryker/Zed/Development/Business/ArchitectureSniffer/ArchitectureSnifferInterface.php +++ b/src/Spryker/Zed/Development/Business/ArchitectureSniffer/ArchitectureSnifferInterface.php @@ -11,7 +11,7 @@ interface ArchitectureSnifferInterface { /** * @param string $directory - * @param array $options + * @param array $options * * @return array */ diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php b/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php index ba966ced..0a966c00 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Bridge/BridgeBuilder.php @@ -8,41 +8,86 @@ namespace Spryker\Zed\Development\Business\CodeBuilder\Bridge; use Generated\Shared\Transfer\BridgeBuilderDataTransfer; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\CamelCaseToDash; +use Laminas\Filter\Word\UnderscoreToCamelCase; use ReflectionClass; use ReflectionMethod; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Filesystem\Filesystem; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\CamelCaseToDash; -use Zend\Filter\Word\UnderscoreToCamelCase; class BridgeBuilder { + /** + * @var string + */ protected const TEMPLATE_INTERFACE = 'interface'; + + /** + * @var string + */ protected const TEMPLATE_BRIDGE = 'bridge'; + + /** + * @var string + */ protected const TEMPLATE_INTERFACE_METHOD = 'interface_method'; + + /** + * @var string + */ protected const TEMPLATE_BRIDGE_METHOD = 'bridge_method'; + /** + * @var string + */ protected const DEFAULT_VENDOR = 'Spryker'; + + /** + * @var string + */ protected const DEFAULT_TO_TYPE = 'Facade'; + /** + * @var array + */ protected const APPLICATION_LAYER_MAP = [ 'Facade' => 'Zed', 'QueryContainer' => 'Zed', ]; + /** + * @var array + */ protected const MODULE_LAYER_MAP = [ 'Facade' => 'Business', 'QueryContainer' => 'Persistence', ]; + /** + * @var string + */ protected const FUNCTION_RETURN = 'return '; + /** + * @var string + */ protected const NULLABLE_RETURN_TYPE_HINT = ': ?'; + + /** + * @var string + */ protected const NON_NULLABLE_RETURN_TYPE_HINT = ': '; + /** + * @var string + */ protected const TYPE_HINT = 'type_hint'; + + /** + * @var string + */ protected const FQCN = 'fqcn'; /** @@ -61,7 +106,7 @@ public function __construct(DevelopmentConfig $config) /** * @param string $bundle * @param string $toBundle - * @param array $methods + * @param array $methods * * @throws \Symfony\Component\Console\Exception\InvalidArgumentException * @@ -94,7 +139,7 @@ protected function createInterface(BridgeBuilderDataTransfer $bridgeBuilderDataT $bridgeBuilderDataTransfer->getModule() . '\\' . 'Dependency\\' . $bridgeBuilderDataTransfer->getToType() . '\\' . - $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface' + $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Interface', ); foreach ($existingInterface->getMethods() as $method) { @@ -126,7 +171,7 @@ protected function createBridge(BridgeBuilderDataTransfer $bridgeBuilderDataTran $bridgeBuilderDataTransfer->getModule() . '\\' . 'Dependency\\' . $bridgeBuilderDataTransfer->getToType() . '\\' . - $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge' + $bridgeBuilderDataTransfer->getModule() . 'To' . $bridgeBuilderDataTransfer->getToModule() . $bridgeBuilderDataTransfer->getToType() . 'Bridge', ); foreach ($existingBridge->getMethods() as $method) { @@ -182,8 +227,9 @@ protected function getBridgeTemplateContent(): string */ protected function getTemplateContent(string $templateName): string { + /** @phpstan-var string */ return file_get_contents( - __DIR__ . DIRECTORY_SEPARATOR . 'Templates' . DIRECTORY_SEPARATOR . $templateName . '.tpl' + __DIR__ . DIRECTORY_SEPARATOR . 'Templates' . DIRECTORY_SEPARATOR . $templateName . '.tpl', ); } @@ -196,15 +242,15 @@ protected function getTemplateContent(string $templateName): string protected function replacePlaceHolder(BridgeBuilderDataTransfer $bridgeBuilderDataTransfer, string $templateContent): string { $replacements = [ - '{vendor}' => $bridgeBuilderDataTransfer->getVendor(), - '{application}' => $bridgeBuilderDataTransfer->getApplication(), - '{module}' => $bridgeBuilderDataTransfer->getModule(), - '{type}' => $bridgeBuilderDataTransfer->getType(), + '{vendor}' => (string)$bridgeBuilderDataTransfer->getVendor(), + '{application}' => (string)$bridgeBuilderDataTransfer->getApplication(), + '{module}' => (string)$bridgeBuilderDataTransfer->getModule(), + '{type}' => (string)$bridgeBuilderDataTransfer->getType(), - '{toVendor}' => $bridgeBuilderDataTransfer->getToVendor(), - '{toApplication}' => $bridgeBuilderDataTransfer->getToApplication(), - '{toModule}' => $bridgeBuilderDataTransfer->getToModule(), - '{toType}' => $bridgeBuilderDataTransfer->getToType(), + '{toVendor}' => (string)$bridgeBuilderDataTransfer->getToVendor(), + '{toApplication}' => (string)$bridgeBuilderDataTransfer->getToApplication(), + '{toModule}' => (string)$bridgeBuilderDataTransfer->getToModule(), + '{toType}' => (string)$bridgeBuilderDataTransfer->getToType(), '{toModuleLayer}' => '', '{toModuleVariable}' => lcfirst($bridgeBuilderDataTransfer->getToModule()), @@ -259,7 +305,7 @@ protected function getPathToDependencyFiles(BridgeBuilderDataTransfer $bridgeBui /** * @param string $source * @param string $target - * @param array $methods + * @param array $methods * * @return \Generated\Shared\Transfer\BridgeBuilderDataTransfer */ @@ -320,7 +366,7 @@ protected function interpretInputParameter($subject): array throw new InvalidArgumentException(sprintf( 'Invalid input parameter "%s", accepted format is "[VendorName.]ModuleName[.BridgeType]".', - $subject + $subject, )); } @@ -466,7 +512,7 @@ protected function addMethodsToBridge(BridgeBuilderDataTransfer $bridgeBuilderDa $targetBridgeClass, $bridgeBuilderDataTransfer->getMethods(), $this->getBridgeMethodTemplateContent(), - $templateContent + $templateContent, ); } @@ -495,13 +541,13 @@ protected function addMethodsToInterface(BridgeBuilderDataTransfer $bridgeBuilde $targetBridgeInterface, $bridgeBuilderDataTransfer->getMethods(), $this->getInterfaceMethodTemplateContent(), - $templateContent + $templateContent, ); } /** - * @param \ReflectionClass $reflectionClass - * @param array $methodNames + * @param \ReflectionClass $reflectionClass + * @param array $methodNames * @param string $methodTemplate * @param string $templateContent * @@ -513,12 +559,14 @@ protected function addMethodsToTemplate(ReflectionClass $reflectionClass, array $useStatements = []; foreach (array_unique($methodNames) as $methodName) { - if (empty($methodName)) { + if (!$methodName) { continue; } $method = $reflectionClass->getMethod($methodName); - $docComment = $this->cleanMethodDocBlock($method->getDocComment()); + /** @var string $docComment */ + $docComment = $method->getDocComment(); + $docComment = $this->cleanMethodDocBlock($docComment); $methodReturnType = $this->getMethodReturnTypeFromDocComment($docComment); $returnStatementReplacement = static::FUNCTION_RETURN; @@ -547,13 +595,11 @@ protected function addMethodsToTemplate(ReflectionClass $reflectionClass, array '{parametersWithoutTypes}' => $this->getParameterNames($method), ]; - $methods .= - str_replace( - array_keys($replacements), - array_values($replacements), - $methodTemplate - ) - . PHP_EOL . PHP_EOL . str_repeat(' ', 4); + $methods .= str_replace( + array_keys($replacements), + array_values($replacements), + $methodTemplate, + ) . PHP_EOL . PHP_EOL . str_repeat(' ', 4); } $useStatements = array_keys($useStatements); @@ -571,7 +617,7 @@ protected function addMethodsToTemplate(ReflectionClass $reflectionClass, array rtrim($methods, PHP_EOL . PHP_EOL . str_repeat(' ', 4)), $useStatements, ], - $templateContent + $templateContent, ); } @@ -586,7 +632,9 @@ protected function getParameters(ReflectionMethod $method): string foreach ($method->getParameters() as $parameter) { if ($parameter->hasType()) { - $finalOutput .= $this->getClassNameFromFqcn($parameter->getType()->getName()) . ' '; + /** @var \ReflectionNamedType $type */ + $type = $parameter->getType(); + $finalOutput .= $this->getClassNameFromFqcn($type->getName()) . ' '; } $finalOutput .= '$' . $parameter->getName(); @@ -621,6 +669,7 @@ protected function getParameters(ReflectionMethod $method): string protected function getClassNameFromFqcn($fqcn): string { $arr = explode('\\', $fqcn); + return end($arr); } @@ -702,6 +751,7 @@ protected function getMethodTypeHintForFunction(string $methodReturnType) if ($numberOfReturnParts === 1) { if (strpos($methodReturnType, '\\') !== false) { $methodTypeHintArray = explode('\\', $methodReturnType); + return [ static::TYPE_HINT => static::NON_NULLABLE_RETURN_TYPE_HINT . end($methodTypeHintArray), static::FQCN => ltrim($methodReturnType, '\\'), @@ -729,6 +779,7 @@ protected function getMethodTypeHintForFunction(string $methodReturnType) if (strpos($methodTypeHint, '\\') !== false) { $methodTypeHintArray = explode('\\', $methodTypeHint); + return [ static::TYPE_HINT => static::NULLABLE_RETURN_TYPE_HINT . end($methodTypeHintArray), static::FQCN => ltrim($methodTypeHint, '\\'), diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/ModuleBuilder.php b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/ModuleBuilder.php index 9cad16a0..409c99b1 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/ModuleBuilder.php +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/ModuleBuilder.php @@ -7,18 +7,27 @@ namespace Spryker\Zed\Development\Business\CodeBuilder\Module; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\CamelCaseToDash; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Filesystem\Filesystem; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\CamelCaseToDash; class ModuleBuilder { + /** + * @var string + */ protected const OPTION_FILE = 'file'; + + /** + * @var string + */ protected const OPTION_FORCE = 'force'; + /** + * @var string + */ protected const NAMESPACE_SPRYKER = 'Spryker'; - protected const NAMESPACE_SPRYKER_SHOP = 'SprykerShop'; /** * @var \Spryker\Zed\Development\DevelopmentConfig @@ -33,15 +42,13 @@ class ModuleBuilder * @var array */ protected $files = [ - '.coveralls.yml', '.gitattributes', '.gitignore', - '.travis.yml', 'CHANGELOG.md', 'codecept.yml' => 'codeception.yml', 'composer.json', 'LICENSE', - 'phpstan.json', + 'phpstan.neon', 'README.md', 'tooling.yml', ]; @@ -56,7 +63,7 @@ public function __construct(DevelopmentConfig $config) /** * @param string $module - * @param array $options + * @param array $options * * @return void */ @@ -80,7 +87,7 @@ public function build($module, array $options) } /** - * @return \Zend\Filter\FilterChain + * @return \Laminas\Filter\FilterChain */ protected function getUnderscoreToCamelCaseFilter() { @@ -94,13 +101,14 @@ protected function getUnderscoreToCamelCaseFilter() /** * @param string $namespace * - * @return string[] + * @return array */ protected function getModuleNames($namespace) { $moduleDirectory = $this->getDirectoryName($namespace); - $moduleDirectories = glob($moduleDirectory . '*'); + /** @var iterable $moduleDirectories */ + $moduleDirectories = glob($moduleDirectory . '*', GLOB_NOSORT); $modules = []; foreach ($moduleDirectories as $moduleDirectory) { @@ -113,7 +121,7 @@ protected function getModuleNames($namespace) /** * @param string $namespace * @param string $module - * @param array $options + * @param array $options * * @return void */ @@ -144,8 +152,9 @@ protected function createOrUpdateModule($namespace, $module, array $options) */ protected function getTemplateContent($templateName) { + /** @phpstan-var string */ return file_get_contents( - __DIR__ . DIRECTORY_SEPARATOR . 'Templates' . DIRECTORY_SEPARATOR . $templateName . '.tpl' + __DIR__ . DIRECTORY_SEPARATOR . 'Templates' . DIRECTORY_SEPARATOR . $templateName . '.tpl', ); } @@ -177,7 +186,7 @@ protected function replacePlaceHolder($namespace, $module, $templateContent) $templateContent = str_replace( $from, $to, - $templateContent + $templateContent, ); return $templateContent; @@ -192,7 +201,9 @@ protected function camelCaseToDash($module) { $filter = new CamelCaseToDash(); - $module = strtolower($filter->filter($module)); + /** @var string $camelCasedModule */ + $camelCasedModule = $filter->filter($module); + $module = strtolower($camelCasedModule); return $module; } diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.coveralls.yml.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.coveralls.yml.tpl deleted file mode 100644 index be4561ef..00000000 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.coveralls.yml.tpl +++ /dev/null @@ -1,3 +0,0 @@ -coverage_clover: tests/_output/coverage.xml -json_path: tests/_output/coveralls-upload.json -service_name: travis-ci diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitattributes.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitattributes.tpl index 88c9701a..51f3ea4b 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitattributes.tpl +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitattributes.tpl @@ -1,6 +1,8 @@ +# Define the line ending behavior of the different file extensions # Set the default behavior, in case people don't have core.autocrlf set. -* eol=lf -* text=auto +* text text=auto eol=lf + +*.php diff=php # Denote all files that are truly binary and should not be modified. *.png binary @@ -17,17 +19,18 @@ *.mo binary *.pdf binary *.xsd binary -*.ts binary *.exe binary # Remove files for archives generated using `git archive` -codeception.yml export-ignore dependency.json export-ignore +phpstan.json export-ignore +phpstan.neon export-ignore +psalm-report.json export-ignore linguist-generated=true +tooling.yml export-ignore .coveralls.yml export-ignore .travis.yml export-ignore .editorconfig export-ignore .gitattributes export-ignore .gitignore export-ignore -phpstan.neon export-ignore -phpstan.json export-ignore -tooling.yml export-ignore +.github/ export-ignore +architecture-baseline.json export-ignore diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitignore.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitignore.tpl index 0d27ebd1..1fd247d6 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitignore.tpl +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.gitignore.tpl @@ -13,7 +13,8 @@ .DS_Store /vendor -/composer.lock +composer.lock +.phpunit.result.cache /tests/_output/* !/tests/_output/.gitkeep diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.travis.yml.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.travis.yml.tpl deleted file mode 100644 index 9a96a68a..00000000 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/.travis.yml.tpl +++ /dev/null @@ -1,28 +0,0 @@ -language: php - -php: - - 7.1 - - 7.3 - -cache: - directories: - - vendor - - $HOME/.composer/cache - -env: - global: - - APPLICATION_ENV=development - - APPLICATION_STORE=DE - -install: - - composer install --no-interaction --prefer-dist - -script: - - vendor/bin/phpcs src --standard=vendor/spryker/code-sniffer/Spryker/ruleset.xml - - vendor/bin/codecept run --env isolated --coverage-xml - -after_success: - - vendor/bin/coveralls -vvv - -notifications: - email: false diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/LICENSE.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/LICENSE.tpl index d376fd6f..36237b30 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/LICENSE.tpl +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/LICENSE.tpl @@ -1,15 +1,15 @@ SPRYKER SYSTEMS GMBH EVALUATION LICENSE AGREEMENT SPRYKER SYSTEMS GMBH, REGISTERED WITH THE COMMERCIAL REGISTER OF THE LOWER COURT OF HAMBURG UNDER HRB 134310 -(“WE” OR ”SPRYKER”)GRANTS YOU (THE “LICENSEE”) THE RIGHT TO USE THE SOFTWARE (AS DEFINED BELOW) -UNDER THE PROVISIONS OF THIS EVALUATION LICENSE AGREEMENT (THE “AGREEMENT”). +("WE" OR "SPRYKER")GRANTS YOU (THE "LICENSEE") THE RIGHT TO USE THE SOFTWARE (AS DEFINED BELOW) +UNDER THE PROVISIONS OF THIS EVALUATION LICENSE AGREEMENT (THE "AGREEMENT"). -The “Software” includes any software owned and distributed by Spryker under this Agreement. The Software +The "Software" includes any software owned and distributed by Spryker under this Agreement. The Software contains elements of open source components, to which different license terms apply respectively. These open source components are needed to be installed separately. -Spryker grants to Licensee, during the 45-calendar-day period (the “Evaluation Period”) following the download of the Software, -the nontransferable, nonexclusive limited, free of charge license to permit Licensee’s employees to internally use the Software +Spryker grants to Licensee, during the 45-calendar-day period (the "Evaluation Period") following the download of the Software, +the nontransferable, nonexclusive limited, free of charge license to permit Licensee's employees to internally use the Software to test and evaluate the Software in connection with potentially purchasing non-evaluation licenses to the Software. Licensee shall not (i) use the Software to set up a productive live system, for development purposes or any other purposes apart @@ -18,7 +18,7 @@ disclose, market, rent, lease, or transfer the Software or act as a service bure Software or install it in multiple locations; (v) disclose any confidential information provided by Spryker; (vi) modify or make derivative works of the Software; or (vii) allow others to make or obtain copies of the Software. -THE SOFTWARE IS PROVIDED “AS-IS” AND WITHOUT WARRANTY OF ANY KIND. SPRYKER DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING +THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND. SPRYKER DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, TITLE, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. SPRYKER WILL NOT BE LIABLE FOR ANY DAMAGES ASSOCIATED WITH THE SOFTWARE, INCLUDING WITHOUT LIMITATION ORDINARY, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO DAMAGES RELATING TO LOST DATA OR LOST PROFITS, EVEN IF SPRYKER HAS BEEN ADVISED OF @@ -34,7 +34,7 @@ on Contracts for the International Sale of Goods (CISG). The parties consent to This Agreement is not assignable or transferable by Licensee and any attempt to do so is null and void. -This Agreement constitutes the entire agreement between the parties concerning Licensee’s use of the Software. This Agreement supersedes +This Agreement constitutes the entire agreement between the parties concerning Licensee's use of the Software. This Agreement supersedes any prior verbal understanding between the parties and any Licensee purchase order or other ordering document, regardless of whether such document is received by Spryker before or after execution of this Agreement. This Agreement may be amended only in a writing signed by an authorized officer of Spryker. diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/README.md.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/README.md.tpl index 092e4065..63f95cad 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/README.md.tpl +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/README.md.tpl @@ -1,5 +1,6 @@ # {module} Module -[![Build Status](https://travis-ci.org/{namespaceDashed}/{moduleDashed}.svg)](https://travis-ci.org/{namespaceDashed}/{moduleDashed}) +[![Latest Stable Version](https://poser.pugx.org/{namespaceDashed}/{moduleDashed}/v/stable.svg)](https://packagist.org/packages/{namespaceDashed}/{moduleDashed}) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.2-8892BF.svg)](https://php.net/) {{ADD DESCRIPTION HERE}} @@ -11,4 +12,4 @@ composer require {namespaceDashed}/{moduleDashed} ## Documentation -[Spryker Documentation](https://documentation.spryker.com/module_guide/overview.htm) +[Spryker Documentation](https://docs.spryker.com) diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/codecept.yml.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/codecept.yml.tpl index 57c16c21..76ce1669 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/codecept.yml.tpl +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/codecept.yml.tpl @@ -2,12 +2,11 @@ namespace: {module} actor: Tester paths: tests: tests - log: tests/_output + output: tests/_output data: tests/_data support: tests/_support envs: tests/_envs settings: - bootstrap: _bootstrap.php suite_class: \PHPUnit\Framework\TestSuite colors: true memory_limit: 1024M diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/composer.json.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/composer.json.tpl index a658a83d..6a3e30c3 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/composer.json.tpl +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/composer.json.tpl @@ -1,32 +1,34 @@ { - "name": "{namespaceDashed}/{moduleDashed}", - "type": "library", - "description": "{module} module", - "license": "proprietary", - "require": { - }, - "require-dev": { - "spryker/code-sniffer": "*", - "spryker/testify": "*" - }, - "autoload": { - "psr-4": { - "{namespace}\\": "src/{namespace}/" + "name": "{namespaceDashed}/{moduleDashed}", + "type": "library", + "description": "{module} module", + "license": "proprietary", + "require": { + }, + "require-dev": { + "spryker/code-sniffer": "*", + "spryker/testify": "*" + }, + "autoload": { + "psr-4": { + "{namespace}\\": "src/{namespace}/" + } + }, + "autoload-dev": { + "psr-4": { + "{namespace}Test\\": "tests/{namespace}Test/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "scripts": { + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "config": { + "sort-packages": true } - }, - "autoload-dev": { - "psr-4": { - "{namespace}Test\\": "tests/{namespace}Test/" - } - }, - "minimum-stability": "dev", - "prefer-stable": true, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "config": { - "sort-packages": true - } } diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/phpstan.json.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/phpstan.json.tpl deleted file mode 100644 index 5853d235..00000000 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/phpstan.json.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{ - "defaultLevel": 5 -} diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/phpstan.neon.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/phpstan.neon.tpl new file mode 100644 index 00000000..b5f07451 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/phpstan.neon.tpl @@ -0,0 +1,2 @@ +parameters: + level: 8 diff --git a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/tooling.yml.tpl b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/tooling.yml.tpl index 85edd114..669cf465 100644 --- a/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/tooling.yml.tpl +++ b/src/Spryker/Zed/Development/Business/CodeBuilder/Module/Templates/tooling.yml.tpl @@ -1,5 +1,5 @@ architecture-sniffer: - priority: 2 + priority: 2 code-sniffer: - level: 2 + level: 2 diff --git a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php index 6cc786af..12744c02 100644 --- a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php +++ b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/CodeStyleSniffer.php @@ -7,27 +7,28 @@ namespace Spryker\Zed\Development\Business\CodeStyleSniffer; -use RuntimeException; +use Laminas\Config\Reader\Xml; use Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationInterface; -use Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationLoaderInterface; -use Spryker\Zed\Development\Business\Exception\CodeStyleSniffer\PathDoesNotExistException; +use Spryker\Zed\Development\Business\Resolver\PathResolverInterface; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Process\Process; -use Zend\Filter\FilterChain; -use Zend\Filter\StringToLower; -use Zend\Filter\Word\CamelCaseToDash; class CodeStyleSniffer { + /** + * @var int + */ protected const CODE_SUCCESS = 0; + /** + * @var string + */ protected const OPTION_IGNORE = 'ignore'; - protected const APPLICATION_NAMESPACES = ['Orm']; - protected const APPLICATION_LAYERS = ['Zed', 'Client', 'Yves', 'Service', 'Shared']; - - protected const NAMESPACE_SPRYKER_SHOP = 'SprykerShop'; - protected const NAMESPACE_SPRYKER = 'Spryker'; + /** + * @var array + */ + protected const EXTENSIONS = ['php']; /** * @var \Spryker\Zed\Development\DevelopmentConfig @@ -35,180 +36,89 @@ class CodeStyleSniffer protected $config; /** - * @var \Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationLoaderInterface + * @var array */ - protected $codeStyleSnifferConfigurationLoader; + protected $options = []; /** - * @param \Spryker\Zed\Development\DevelopmentConfig $config - * @param \Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationLoaderInterface $codeStyleSnifferConfigurationLoader + * @var \Spryker\Zed\Development\Business\Resolver\PathResolverInterface */ - public function __construct(DevelopmentConfig $config, CodeStyleSnifferConfigurationLoaderInterface $codeStyleSnifferConfigurationLoader) - { - $this->config = $config; - $this->codeStyleSnifferConfigurationLoader = $codeStyleSnifferConfigurationLoader; - } + protected PathResolverInterface $pathResolver; /** - * @param string|null $module - * @param array $options - * - * @return int + * @var int */ - public function checkCodeStyle($module, array $options = []) - { - $namespace = null; - if (strpos($module, '.') !== false) { - [$namespace, $module] = explode('.', $module, 2); - } - - $pathOption = isset($options['path']) ? $options['path'] : null; - $defaults = [ - static::OPTION_IGNORE => $namespace || $pathOption ? null : 'vendor/', - ]; - $options += $defaults; - - $path = $this->resolvePath($module, $namespace, $pathOption); - $codeStyleSnifferConfiguration = $this->codeStyleSnifferConfigurationLoader->load($options, $path); - - return $this->runSnifferCommand($path, $codeStyleSnifferConfiguration); - } + protected $countResolvedPaths = 0; /** - * @param string $module - * @param string|null $namespace - * @param string|null $path - * - * @return string + * @var int */ - protected function resolvePath($module, $namespace = null, $path = null) - { - $path = $path !== null ? trim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : null; - - if ($namespace) { - if ($module === 'all') { - return $this->getPathToCore($namespace, $path); - } - - return $this->getPathToModule($module, $namespace, $path); - } - - $pathToRoot = $this->config->getPathToRoot(); - - if (!$module) { - return $pathToRoot . $path; - } - - return $this->resolveProjectPath($module, $path); - } + protected $countTotalPaths = 0; /** - * @param string $namespace - * @param string $path - * - * @throws \RuntimeException - * - * @return string + * @var array */ - protected function getPathToCore($namespace, $path) - { - if ($path) { - throw new RuntimeException('Path suffix option is not possible for "all".'); - } - - $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); - - if (!$pathToInternalNamespace) { - throw new RuntimeException('Namespace invalid: ' . $namespace); - } - - return $pathToInternalNamespace; - } + protected $commandsToFix = []; /** - * @param string $module - * @param string $namespace - * @param string|null $pathSuffix - * - * @throws \Spryker\Zed\Development\Business\Exception\CodeStyleSniffer\PathDoesNotExistException - * - * @return string + * @param \Spryker\Zed\Development\DevelopmentConfig $config + * @param \Spryker\Zed\Development\Business\Resolver\PathResolverInterface $pathResolver */ - protected function getPathToModule($module, $namespace, $pathSuffix = null) - { - $path = $this->getCorePath($module, $namespace, $pathSuffix); - if ($this->isPathValid($path)) { - return $path; - } - - $message = sprintf( - 'Could not find a valid path to your module "%s". Expected path "%s". Maybe there is a typo in the module name?', - $module, - $path - ); - - throw new PathDoesNotExistException($message); + public function __construct( + DevelopmentConfig $config, + PathResolverInterface $pathResolver + ) { + $this->config = $config; + $this->pathResolver = $pathResolver; } /** - * @param string $module - * @param string $namespace - * @param string|null $pathSuffix + * @param string|null $module + * @param array $options * - * @return string + * @return int */ - protected function getCorePath($module, $namespace, $pathSuffix = null) + public function checkCodeStyle(?string $module, array $options = []): int { - $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); - if ($pathToInternalNamespace && is_dir($pathToInternalNamespace . $module)) { - return $this->buildPath($pathToInternalNamespace . $module . DIRECTORY_SEPARATOR, $pathSuffix); + $resultCode = static::CODE_SUCCESS; + + $namespace = null; + if ($module !== null && strpos($module, '.') !== false) { + [$namespace, $module] = explode('.', $module, 2); } - $vendor = $this->normalizeName($namespace); - $module = $this->normalizeName($module); - $path = $this->config->getPathToRoot() . 'vendor' . DIRECTORY_SEPARATOR . $vendor . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR; + $pathOption = $options['path'] ?? null; + $options += $this->getDefaultIgnoredPath($module, $pathOption); - return $this->buildPath($path, $pathSuffix); - } + $paths = $this->pathResolver->resolvePaths($module, $namespace, $pathOption, $options); + $this->countTotalPaths = count($paths); - /** - * @param string $path - * @param string $suffix - * - * @return string - */ - protected function buildPath($path, $suffix) - { - if (!$suffix) { - return $path; + foreach ($paths as $path => $codeStyleSnifferConfiguration) { + $this->countResolvedPaths++; + $resultCode |= $this->runSnifferCommand($path, $codeStyleSnifferConfiguration); } - return $path . $suffix; - } - - /** - * @param string $name - * - * @return string - */ - protected function normalizeName($name) - { - $filterChain = new FilterChain(); - $filterChain - ->attach(new CamelCaseToDash()) - ->attach(new StringToLower()); + if ($this->commandsToFix) { + echo 'To fix run the following command: ' . PHP_EOL; + echo implode('', $this->commandsToFix); + } - return $filterChain->filter($name); + return $resultCode; } /** - * @param string $path + * @param string|null $path + * @param string|null $pathOption * - * @return bool + * @return array */ - protected function isPathValid($path) + protected function getDefaultIgnoredPath(?string $path = null, ?string $pathOption = null): array { - return (is_file($path) || is_dir($path)); + $dontIgnoreVendor = $path || $pathOption || $this->config->isStandaloneMode(); + + return [ + static::OPTION_IGNORE => $dontIgnoreVendor ? null : 'vendor/', + ]; } /** @@ -219,7 +129,8 @@ protected function isPathValid($path) */ protected function runSnifferCommand($path, CodeStyleSnifferConfigurationInterface $codeStyleSnifferConfiguration) { - $processConfig = ' --standard=' . $codeStyleSnifferConfiguration->getCodingStandard(); + $standard = $codeStyleSnifferConfiguration->getCodingStandard($path); + $processConfig = '--standard=' . $standard; if ($codeStyleSnifferConfiguration->isVerbose()) { $processConfig .= ' -v'; @@ -234,17 +145,32 @@ protected function runSnifferCommand($path, CodeStyleSnifferConfigurationInterfa } $optionSniffs = $codeStyleSnifferConfiguration->getSpecificSniffs(); - if ($optionSniffs) { $processConfig .= ' --sniffs=' . $optionSniffs; } + $processConfig .= ' --extensions=' . implode(',', static::EXTENSIONS); + $optionIgnore = $codeStyleSnifferConfiguration->getIgnoredPaths(); + $customPaths = []; + $hasConfigFile = file_exists($path . DIRECTORY_SEPARATOR . 'phpcs.xml'); + if (!$hasConfigFile) { + if (is_dir($path . 'src')) { + $customPaths[] = $path . 'src/'; + } + if (is_dir($path . 'tests')) { + $customPaths[] = $path . 'tests/'; + } + $optionIgnore .= ($optionIgnore ? ',' : '') . '/src/Generated/'; + } + if ($optionIgnore) { $processConfig .= ' --ignore=' . $optionIgnore; } + $processConfig .= ' ' . implode(' ', $customPaths); + $optionVerbose = $codeStyleSnifferConfiguration->isVerbose(); $optionFix = $codeStyleSnifferConfiguration->isFixing(); @@ -252,11 +178,17 @@ protected function runSnifferCommand($path, CodeStyleSnifferConfigurationInterfa $processConfig .= ' -s'; } + if (!$hasConfigFile || $this->hasLegacyConfiguration($path . DIRECTORY_SEPARATOR . 'phpcs.xml')) { + $path = ' ' . $path; + } else { + $path = ''; + } + $command = sprintf( 'vendor/bin/%s %s%s', $optionFix ? 'phpcbf' : 'phpcs', - $path, - $processConfig + $processConfig, + $customPaths ? '' : $path, ); $optionDryRun = $codeStyleSnifferConfiguration->isDryRun(); @@ -267,7 +199,14 @@ protected function runSnifferCommand($path, CodeStyleSnifferConfigurationInterfa return static::CODE_SUCCESS; } - $process = new Process($command, $this->config->getPathToRoot(), null, null, 4800); + $process = new Process(explode(' ', $command), $this->config->getPathToRoot()); + $process->setTimeout($this->config->getProcessTimeout()); + + $module = $codeStyleSnifferConfiguration->getModule(); + if ($module !== null && strpos($module, '.all') !== false) { + return $this->runSnifferCommandForAll($process, $path, $codeStyleSnifferConfiguration); + } + $process->run(function ($type, $buffer) { echo $buffer; }); @@ -276,35 +215,55 @@ protected function runSnifferCommand($path, CodeStyleSnifferConfigurationInterfa } /** - * @param string $module - * @param string|null $pathSuffix + * @param \Symfony\Component\Process\Process $process + * @param string $path + * @param \Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationInterface $codeStyleSnifferConfiguration * - * @return string + * @return int */ - protected function resolveProjectPath($module, $pathSuffix = null) - { - $projectNamespaces = $this->config->getProjectNamespaces(); - $namespaces = array_merge(static::APPLICATION_NAMESPACES, $projectNamespaces); - $pathToRoot = $this->config->getPathToRoot(); + protected function runSnifferCommandForAll( + Process $process, + string $path, + CodeStyleSnifferConfigurationInterface $codeStyleSnifferConfiguration + ): int { + $process->run(); + + echo sprintf( + 'Finished %s/%s %s (level %s) /%s %s' . PHP_EOL, + $this->countResolvedPaths, + $this->countTotalPaths, + basename($path), + $codeStyleSnifferConfiguration->getLevel(), + $this->getSnifferResultMessage($process), + ($process->getExitCode() !== static::CODE_SUCCESS ? $process->getOutput() : ''), + ); - $paths = []; - foreach ($namespaces as $namespace) { - $path = $pathToRoot . 'src' . DIRECTORY_SEPARATOR . $namespace . DIRECTORY_SEPARATOR; + if ($process->getExitCode() !== static::CODE_SUCCESS && !$codeStyleSnifferConfiguration->isFixing()) { + $this->commandsToFix[] = sprintf('vendor/bin/console c:s:s -m %s.%s -f' . PHP_EOL, $codeStyleSnifferConfiguration->getNamespace(), basename($path)); + } - foreach (static::APPLICATION_LAYERS as $layer) { - $layerPath = $path . $layer . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR; - if ($pathSuffix) { - $layerPath .= $pathSuffix; - } + return $process->getExitCode(); + } - if (!is_dir($layerPath)) { - continue; - } + /** + * @param \Symfony\Component\Process\Process $process + * + * @return string + */ + protected function getSnifferResultMessage(Process $process): string + { + return sprintf('%s', $process->getExitCode() === static::CODE_SUCCESS ? "\033[32m OK \033[0m" : "\033[31m FAIL \033[0m"); + } - $paths[] = $layerPath; - } - } + /** + * @param string $path + * + * @return bool + */ + protected function hasLegacyConfiguration(string $path): bool + { + $xml = (new Xml())->fromFile($path); - return implode(' ', $paths); + return empty($xml['file']); } } diff --git a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfiguration.php b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfiguration.php index 75c198a7..349d9ea4 100644 --- a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfiguration.php +++ b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfiguration.php @@ -14,46 +14,80 @@ class CodeStyleSnifferConfiguration implements CodeStyleSnifferConfigurationInte { /** * @see \Spryker\Zed\Development\Communication\Console\CodeStyleSnifferConsole::OPTION_FIX + * + * @var string */ protected const OPTION_FIX = 'fix'; /** * @see \Spryker\Zed\Development\Communication\Console\CodeStyleSnifferConsole::OPTION_DRY_RUN + * + * @var string */ protected const OPTION_DRY_RUN = 'dry-run'; /** * @see \Spryker\Zed\Development\Communication\Console\CodeStyleSnifferConsole::OPTION_QUIET + * + * @var string */ protected const OPTION_QUIET = 'quiet'; /** * @see \Spryker\Zed\Development\Communication\Console\CodeStyleSnifferConsole::OPTION_EXPLAIN + * + * @var string */ protected const OPTION_EXPLAIN = 'explain'; /** * @see \Spryker\Zed\Development\Communication\Console\CodeStyleSnifferConsole::OPTION_SNIFFS + * + * @var string */ protected const OPTION_SNIFFS = 'sniffs'; /** * @see \Spryker\Zed\Development\Communication\Console\CodeStyleSnifferConsole::OPTION_VERBOSE + * + * @var string */ protected const OPTION_VERBOSE = 'verbose'; /** * @see \Spryker\Zed\Development\Business\CodeStyleSniffer\CodeStyleSniffer::OPTION_IGNORE + * + * @var string */ protected const OPTION_IGNORE = 'ignore'; + /** + * @see \Spryker\Zed\Development\Business\CodeStyleSniffer\CodeStyleSniffer::OPTION_MODULE + * + * @var string + */ + protected const OPTION_MODULE = 'module'; + /** * @see \Spryker\Zed\Development\Communication\Console\CodeStyleSnifferConsole::OPTION_LEVEL + * + * @var string */ protected const OPTION_LEVEL = 'level'; + /** + * @var string + */ protected const MODULE_CONFIG_LEVEL = 'level'; + + /** + * @var int + */ protected const LEVEL_SPRYKER_BASIC = 1; + + /** + * @var int + */ protected const LEVEL_SPRYKER_STRICT = 2; /** @@ -62,12 +96,17 @@ class CodeStyleSnifferConfiguration implements CodeStyleSnifferConfigurationInte protected $developmentConfig; /** - * @var array + * @var array */ protected $moduleConfig; /** - * @var array + * @var string + */ + protected $namespace; + + /** + * @var array */ protected $configurationOptions; @@ -80,7 +119,7 @@ public function __construct(DevelopmentConfig $developmentConfig) } /** - * @param array $moduleConfig + * @param array $moduleConfig * * @return $this */ @@ -92,7 +131,27 @@ public function setModuleConfig(array $moduleConfig) } /** - * @param array $configurationOptions + * @param string $namespace + * + * @return $this + */ + public function setNamespace(string $namespace) + { + $this->namespace = $namespace; + + return $this; + } + + /** + * @return string + */ + public function getNamespace(): string + { + return $this->namespace; + } + + /** + * @param array $configurationOptions * * @return $this */ @@ -104,21 +163,50 @@ public function setConfigurationOptions(array $configurationOptions) } /** - * {@inheritdoc} + * {@inheritDoc} + * + * @param string $path * * @return string */ - public function getCodingStandard(): string + public function getCodingStandard(string $path): string { + $phpcsRootFilePath = $path . 'phpcs.xml'; + + if (file_exists($phpcsRootFilePath)) { + return $phpcsRootFilePath; + } + + $vendorDir = APPLICATION_VENDOR_DIR . DIRECTORY_SEPARATOR; + + $localConfigPath = ''; + if (strpos($path, $vendorDir) === false && !$this->developmentConfig->isStandaloneMode()) { + return $this->developmentConfig->getCodingStandard(); + } + if ($this->getLevel() === static::LEVEL_SPRYKER_STRICT) { - return APPLICATION_VENDOR_DIR . DIRECTORY_SEPARATOR . 'spryker/code-sniffer/SprykerStrict/ruleset.xml'; + $localConfigPath = $this->developmentConfig->getCodeSnifferStrictRuleset(); + } + + if ($this->getLevel() === static::LEVEL_SPRYKER_STRICT && $this->getNamespace() === $this->developmentConfig->getSprykerFeatureNamespace()) { + $localConfigPath = $this->developmentConfig->getCodeSnifferFeatureRuleset(); + } + + if (file_exists($localConfigPath)) { + return $localConfigPath; + } + + $localConfigPath = $this->developmentConfig->getCodeSnifferRuleset(); + + if (file_exists($localConfigPath)) { + return $localConfigPath; } return $this->developmentConfig->getCodingStandard(); } /** - * {@inheritdoc} + * {@inheritDoc} * * @return string|null */ @@ -128,7 +216,17 @@ public function getIgnoredPaths(): ?string } /** - * {@inheritdoc} + * {@inheritDoc} + * + * @return string|null + */ + public function getModule(): ?string + { + return $this->configurationOptions[static::OPTION_MODULE]; + } + + /** + * {@inheritDoc} * * @return bool */ @@ -138,7 +236,7 @@ public function isFixing(): bool } /** - * {@inheritdoc} + * {@inheritDoc} * * @return bool */ @@ -148,7 +246,7 @@ public function isQuiet(): bool } /** - * {@inheritdoc} + * {@inheritDoc} * * @return bool */ @@ -158,7 +256,7 @@ public function isDryRun(): bool } /** - * {@inheritdoc} + * {@inheritDoc} * * @return bool */ @@ -168,7 +266,7 @@ public function isExplaining(): bool } /** - * {@inheritdoc} + * {@inheritDoc} * * @return string|null */ @@ -178,7 +276,7 @@ public function getSpecificSniffs(): ?string } /** - * {@inheritdoc} + * {@inheritDoc} * * @return bool */ @@ -188,7 +286,7 @@ public function isVerbose(): bool } /** - * {@inheritdoc} + * {@inheritDoc} * * @throws \InvalidArgumentException * @@ -199,9 +297,9 @@ public function getLevel(): int $optionLevel = $this->resolveOptionLevel(); $levelAllowed = $this->getAllowedLevels(); - if (!in_array($optionLevel, $levelAllowed)) { + if (!in_array($optionLevel, $levelAllowed, true)) { throw new InvalidArgumentException( - sprintf('Level should be in [%s] range', implode(', ', $levelAllowed)) + sprintf('Level should be in [%s] range', implode(', ', $levelAllowed)), ); } @@ -227,7 +325,7 @@ protected function resolveOptionLevel(): int } /** - * @return int[] + * @return array */ protected function getAllowedLevels(): array { diff --git a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationInterface.php b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationInterface.php index 4ffe613c..2dab5ed4 100644 --- a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationInterface.php +++ b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationInterface.php @@ -10,14 +10,26 @@ interface CodeStyleSnifferConfigurationInterface { /** - * @param array $moduleConfig + * @param array $moduleConfig * * @return $this */ public function setModuleConfig(array $moduleConfig); /** - * @param array $configurationOptions + * @param string $namespace + * + * @return $this + */ + public function setNamespace(string $namespace); + + /** + * @return string + */ + public function getNamespace(): string; + + /** + * @param array $configurationOptions * * @return $this */ @@ -25,11 +37,13 @@ public function setConfigurationOptions(array $configurationOptions); /** * Returns the list of paths to the coding standards which should be used in current CodeStyleSniffer run. - * Multiple paths should be separated by coma. + * Multiple paths should be separated by comma. + * + * @param string $path * * @return string */ - public function getCodingStandard(): string; + public function getCodingStandard(string $path): string; /** * Returns the list of patterns to the files or folders which should be skipped in current CodeStyleSniffer run. @@ -39,6 +53,13 @@ public function getCodingStandard(): string; */ public function getIgnoredPaths(): ?string; + /** + * Returns module. + * + * @return string|null + */ + public function getModule(): ?string; + /** * Returns true if current CodeStyleSniffer run should fix all the fixable errors. * diff --git a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoader.php b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoader.php index 56b0d090..268180a9 100644 --- a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoader.php +++ b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoader.php @@ -11,6 +11,9 @@ class CodeStyleSnifferConfigurationLoader implements CodeStyleSnifferConfigurationLoaderInterface { + /** + * @var string + */ protected const MODULE_CONFIG_TOOL_KEY = 'code-sniffer'; /** @@ -36,17 +39,20 @@ public function __construct( } /** - * @param array $configurationOptions + * @param array $configurationOptions * @param string $modulePath + * @param string|null $namespace * * @return \Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationInterface */ - public function load(array $configurationOptions, string $modulePath): CodeStyleSnifferConfigurationInterface + public function load(array $configurationOptions, string $modulePath, ?string $namespace): CodeStyleSnifferConfigurationInterface { $this->codeStyleSnifferConfiguration->setConfigurationOptions($configurationOptions); $generalModuleConfiguration = $this->configurationReader->getModuleConfigurationByAbsolutePath($modulePath); + $this->codeStyleSnifferConfiguration->setModuleConfig($generalModuleConfiguration[static::MODULE_CONFIG_TOOL_KEY] ?? []); + $this->codeStyleSnifferConfiguration->setNamespace($namespace ?? ''); return $this->codeStyleSnifferConfiguration; } diff --git a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoaderInterface.php b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoaderInterface.php index ebf29266..961a0ddb 100644 --- a/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoaderInterface.php +++ b/src/Spryker/Zed/Development/Business/CodeStyleSniffer/Config/CodeStyleSnifferConfigurationLoaderInterface.php @@ -10,10 +10,11 @@ interface CodeStyleSnifferConfigurationLoaderInterface { /** - * @param array $configurationOptions + * @param array $configurationOptions * @param string $modulePath + * @param string|null $namespace * * @return \Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationInterface */ - public function load(array $configurationOptions, string $modulePath): CodeStyleSnifferConfigurationInterface; + public function load(array $configurationOptions, string $modulePath, ?string $namespace): CodeStyleSnifferConfigurationInterface; } diff --git a/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php b/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php index e006ea9f..3c526d1a 100644 --- a/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php +++ b/src/Spryker/Zed/Development/Business/CodeTest/CodeTester.php @@ -7,145 +7,359 @@ namespace Spryker\Zed\Development\Business\CodeTest; -use ErrorException; +use Generated\Shared\Transfer\ModuleFilterTransfer; +use Generated\Shared\Transfer\ModuleTransfer; +use Generated\Shared\Transfer\OrganizationTransfer; +use RuntimeException; +use Spryker\Zed\Development\Business\Codeception\Argument\Builder\CodeceptionArgumentsBuilderInterface; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface; +use Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface; +use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Process\Process; -use Zend\Filter\Word\UnderscoreToCamelCase; class CodeTester { + /** + * @var string + */ public const OPTION_VERBOSE = 'verbose'; + /** + * @var string + */ public const OPTION_INITIALIZE = 'initialize'; + /** + * @var string + */ public const OPTION_GROUP = 'group'; + /** + * @var string + */ public const OPTION_TYPE_EXCLUDE = 'exclude'; /** * @var string */ - protected $applicationRoot; + public const OPTION_DRY_RUN = 'dry-run'; /** - * @var string + * @var int */ - protected $pathToBundles; + protected const CODE_SUCCESS = 0; /** - * @param string $applicationRoot - * @param string $pathToBundles + * @var int */ - public function __construct($applicationRoot, $pathToBundles) - { - $this->applicationRoot = $applicationRoot; - $this->pathToBundles = $pathToBundles; + protected const CODE_ERROR = 1; + + /** + * @var \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface + */ + protected $developmentToModuleFinderFacade; + + /** + * @var \Spryker\Zed\Development\Business\Codeception\Argument\Builder\CodeceptionArgumentsBuilderInterface + */ + protected $argumentBuilder; + + /** + * @var \Spryker\Zed\Development\DevelopmentConfig + */ + protected $config; + + /** + * @var \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface + */ + protected NameNormalizerInterface $nameNormalizer; + + /** + * @param \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface $developmentToModuleFinderFacade + * @param \Spryker\Zed\Development\Business\Codeception\Argument\Builder\CodeceptionArgumentsBuilderInterface $argumentBuilder + * @param \Spryker\Zed\Development\DevelopmentConfig $config + * @param \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface $nameNormalizer + */ + public function __construct( + DevelopmentToModuleFinderFacadeInterface $developmentToModuleFinderFacade, + CodeceptionArgumentsBuilderInterface $argumentBuilder, + DevelopmentConfig $config, + NameNormalizerInterface $nameNormalizer + ) { + $this->developmentToModuleFinderFacade = $developmentToModuleFinderFacade; + $this->argumentBuilder = $argumentBuilder; + $this->config = $config; + $this->nameNormalizer = $nameNormalizer; } /** - * @param string|null $bundle - * @param array $options + * Runs `vendor/bin/codecept run`. + * If module is given, it will run over this (core) module. Otherwise runs over project level. * - * @throws \ErrorException + * @param string|null $moduleName + * @param array $options * - * @return void + * @throws \RuntimeException + * + * @return int */ - public function runTest($bundle, array $options = []) + public function runTest(?string $moduleName, array $options = []): int { - $path = $this->resolvePath($bundle); + if ($moduleName === null || $moduleName === '') { + if ($options[static::OPTION_INITIALIZE] && !$options[static::OPTION_DRY_RUN]) { + $this->runCodeceptionBuild($options); + } + + return $this->runTestCommand(null, $options); + } + + $moduleFilterTransfer = $this->buildModuleFilterTransfer($moduleName); + $modules = $this->developmentToModuleFinderFacade->getModules($moduleFilterTransfer); + if (!$modules) { + if ($this->config->isStandaloneMode()) { + $path = $this->getCommonModulePath($moduleName); - if (!is_dir($path)) { - $message = 'This path does not exist'; - if (!empty($bundle)) { - $message = 'This bundle does not exist'; + return $this->runTestCommand($path, $options) ? static::CODE_SUCCESS : static::CODE_ERROR; } - throw new ErrorException($message); + throw new RuntimeException('No matching core modules found.'); } - $this->runTestCommand($path, $options); + $result = static::CODE_SUCCESS; + foreach ($modules as $module) { + $path = $module->getPath(); + + if (!$this->runTestCommand($path, $options)) { + $result = static::CODE_ERROR; + } + } + + return $result; } /** - * @param string $bundle + * Runs `vendor/bin/codecept fixtures`. + * If module is given, it will run over this (core) module. Otherwise runs over project level. * - * @return string + * @param string|null $moduleName + * @param array $options + * + * @throws \RuntimeException + * + * @return int */ - protected function resolvePath($bundle) + public function runFixtures(?string $moduleName, array $options = []): int { - if ($bundle) { - $bundle = $this->normalizeBundleName($bundle); + if ($moduleName === null || $moduleName === '') { + if ($options[static::OPTION_INITIALIZE] && !$options[static::OPTION_DRY_RUN]) { + $this->runCodeceptionBuild($options); + } - return $this->getPathToBundle($bundle); + return $this->runFixturesCommand(null, $options); } - return $this->applicationRoot; + $moduleFilterTransfer = $this->buildModuleFilterTransfer($moduleName); + $modules = $this->developmentToModuleFinderFacade->getModules($moduleFilterTransfer); + if (!$modules) { + if ($this->config->isStandaloneMode()) { + $path = $this->getCommonModulePath($moduleName); + + return $this->runFixturesCommand($path, $options) ? static::CODE_SUCCESS : static::CODE_ERROR; + } + + throw new RuntimeException('No matching core modules found.'); + } + + $result = static::CODE_SUCCESS; + foreach ($modules as $module) { + $path = $module->getPath(); + + if (!$this->runFixturesCommand($path, $options)) { + $result = static::CODE_ERROR; + } + } + + return $result; } /** - * @param string $bundle + * @param string|null $moduleName * - * @return string + * @return \Generated\Shared\Transfer\ModuleFilterTransfer */ - protected function normalizeBundleName($bundle) + protected function buildModuleFilterTransfer(?string $moduleName): ModuleFilterTransfer { - $filter = new UnderscoreToCamelCase(); + $moduleFilterTransfer = new ModuleFilterTransfer(); + if ($moduleName === null) { + return $moduleFilterTransfer; + } + + if (strpos($moduleName, '.') === false) { + $moduleTransfer = new ModuleTransfer(); + $moduleTransfer->setName($moduleName); + $moduleFilterTransfer->setModule($moduleTransfer); - return ucfirst($filter->filter($bundle)); + return $moduleFilterTransfer; + } + + return $this->addFilterDetails($moduleName, $moduleFilterTransfer); } /** - * @param string $bundle + * @param string $moduleName + * @param \Generated\Shared\Transfer\ModuleFilterTransfer $moduleFilterTransfer * - * @return string + * @return \Generated\Shared\Transfer\ModuleFilterTransfer */ - protected function getPathToBundle($bundle) + protected function addFilterDetails(string $moduleName, ModuleFilterTransfer $moduleFilterTransfer): ModuleFilterTransfer { - return $this->pathToBundles . $bundle . DIRECTORY_SEPARATOR; + $moduleFragments = explode('.', $moduleName); + + $organization = array_shift($moduleFragments); + $moduleName = array_shift($moduleFragments); + + if ($moduleName === null) { + $moduleName = $organization; + $organization = null; + } + + $moduleTransfer = new ModuleTransfer(); + $moduleTransfer->setName($moduleName); + $moduleFilterTransfer->setModule($moduleTransfer); + + $organizationTransfer = new OrganizationTransfer(); + $organizationTransfer->setName($organization); + $moduleFilterTransfer->setOrganization($organizationTransfer); + + return $moduleFilterTransfer; } /** - * @param string $path - * @param array $options + * @param string|null $path + * @param array $options * - * @return void + * @return int */ - protected function runTestCommand($path, array $options) + protected function runTestCommand(?string $path, array $options): int { - $pathToFiles = rtrim($path, DIRECTORY_SEPARATOR); - $config = ''; + $commandLine = []; - if ($pathToFiles) { - $config .= ' -c ' . $pathToFiles; - } + $commandLine[] = 'vendor/bin/codecept'; + $commandLine[] = 'run'; - if ($options[static::OPTION_GROUP]) { - $config .= ' -g ' . $options[static::OPTION_GROUP]; + if ($path) { + $options['config'] = $path; } - if ($options[static::OPTION_TYPE_EXCLUDE]) { - $config .= ' -x ' . $options[static::OPTION_TYPE_EXCLUDE]; - } + $commandLine = array_merge( + $commandLine, + $this->argumentBuilder + ->build($options) + ->getArguments(), + ); - if ($options[static::OPTION_VERBOSE]) { - $config .= ' -v'; + if ($options[static::OPTION_DRY_RUN]) { + return $this->dryRun($commandLine); } - if ($options[static::OPTION_INITIALIZE]) { - $command = 'vendor/bin/codecept build'; - $process = new Process($command, $this->applicationRoot, null, null, 4800); - $process->run(function ($type, $buffer) use ($options) { - if ($options[static::OPTION_VERBOSE]) { - echo $buffer; - } - }); - echo 'Test classes generated.'; + $process = new Process($commandLine, $this->config->getPathToRoot(), null, null, $this->config->getProcessTimeout()); + $process->run(function ($type, $buffer) { + echo $buffer; + }); + + return $process->getExitCode(); + } + + /** + * @param string|null $path + * @param array $options + * + * @return int + */ + protected function runFixturesCommand(?string $path, array $options): int + { + if ($options[static::OPTION_INITIALIZE] && !$options[static::OPTION_DRY_RUN]) { + $this->runCodeceptionBuild($options, $path); } - $command = 'vendor/bin/codecept run' . $config; + $commandLine = []; + + $commandLine[] = 'vendor/bin/codecept'; + $commandLine[] = 'fixtures'; + + $commandLine = array_merge( + $commandLine, + $this->argumentBuilder + ->build($options) + ->getArguments(), + ); - $process = new Process($command, $this->applicationRoot, null, null, 4800); + $process = new Process($commandLine, $this->config->getPathToRoot(), null, null, $this->config->getProcessTimeout()); $process->run(function ($type, $buffer) { echo $buffer; }); + + return $process->getExitCode(); + } + + /** + * @param array $options + * @param string|null $path + * + * @return void + */ + protected function runCodeceptionBuild(array $options, ?string $path = null): void + { + $commandLine = []; + + $commandPath = $path ?? ''; + $commandLine[] = $commandPath . 'vendor/bin/codecept'; + $commandLine[] = 'build'; + + $process = new Process($commandLine, $this->config->getPathToRoot(), null, null, $this->config->getProcessTimeout()); + $process->run(function ($type, $buffer) use ($options) { + if ($options[static::OPTION_VERBOSE]) { + echo $buffer; + } + }); + } + + /** + * @param array $command + * + * @return int + */ + protected function dryRun(array $command): int + { + $output = []; + foreach ($command as $line) { + if (strpos($line, ' ') !== false) { + $line = '"' . $line . '"'; + } + $output[] = $line; + } + echo implode(' ', $output) . PHP_EOL; + + return static::CODE_SUCCESS; + } + + /** + * @param string $module + * + * @return string + */ + protected function getCommonModulePath(string $module): string + { + [$namespace, $module] = explode('.', $module); + + $moduleVendor = $this->nameNormalizer->dasherize($namespace); + $module = $this->nameNormalizer->dasherize($module); + + return sprintf( + '%s/vendor/%s/%s/', + $this->config->getPathToRoot(), + $moduleVendor, + $module, + ); } } diff --git a/src/Spryker/Zed/Development/Business/Codeception/Argument/Builder/CodeceptionArgumentsBuilder.php b/src/Spryker/Zed/Development/Business/Codeception/Argument/Builder/CodeceptionArgumentsBuilder.php new file mode 100644 index 00000000..9262f520 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Codeception/Argument/Builder/CodeceptionArgumentsBuilder.php @@ -0,0 +1,195 @@ + + */ + protected $defaultInclusiveTestGroups; + + /** + * @param array $defaultInclusiveTestGroups + */ + public function __construct(array $defaultInclusiveTestGroups) + { + $this->defaultInclusiveTestGroups = $defaultInclusiveTestGroups; + } + + /** + * @param array $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + public function build(array $options): CodeceptionArguments + { + $codeceptionArguments = new CodeceptionArguments(); + + $codeceptionArguments = $this->addConfigPath($codeceptionArguments, $options); + $codeceptionArguments = $this->addInclusiveGroups($codeceptionArguments, $options); + $codeceptionArguments = $this->addIncludeGroups($codeceptionArguments, $options); + $codeceptionArguments = $this->addExcludeGroups($codeceptionArguments, $options); + $codeceptionArguments = $this->addVerboseMode($codeceptionArguments, $options); + + return $codeceptionArguments; + } + + /** + * @param \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments $codeceptionArguments + * @param array $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + protected function addConfigPath(CodeceptionArguments $codeceptionArguments, array $options): CodeceptionArguments + { + if (!empty($options[static::OPTION_CONFIG_PATH])) { + return $codeceptionArguments->addArgument('-c', [$options[static::OPTION_CONFIG_PATH]]); + } + + return $codeceptionArguments; + } + + /** + * @param \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments $codeceptionArguments + * @param array $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + protected function addIncludeGroups(CodeceptionArguments $codeceptionArguments, array $options): CodeceptionArguments + { + if (!empty($options[static::OPTION_GROUP_INCLUDE])) { + $codeceptionArguments->addArgument( + '-g', + explode(',', $options[static::OPTION_GROUP_INCLUDE]), + ); + } + + return $codeceptionArguments; + } + + /** + * @param \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments $codeceptionArguments + * @param array $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + protected function addExcludeGroups(CodeceptionArguments $codeceptionArguments, array $options): CodeceptionArguments + { + if (!empty($options[static::OPTION_GROUP_EXCLUDE])) { + $codeceptionArguments->addArgument( + '-x', + explode(',', $options[static::OPTION_GROUP_EXCLUDE]), + ); + } + + return $codeceptionArguments; + } + + /** + * @param \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments $codeceptionArguments + * @param array $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + protected function addVerboseMode(CodeceptionArguments $codeceptionArguments, array $options): CodeceptionArguments + { + if (!empty($options[static::OPTION_VERBOSE])) { + return $codeceptionArguments->addArgument('-v'); + } + + return $codeceptionArguments; + } + + /** + * @param \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments $codeceptionArguments + * @param array $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + protected function addInclusiveGroups(CodeceptionArguments $codeceptionArguments, array $options): CodeceptionArguments + { + if (!empty($options[static::OPTION_MODULE]) && strpos($options[static::OPTION_MODULE], '.') === false) { + $codeceptionArguments = $this->enableSuiteFilterExtension($codeceptionArguments); + $codeceptionArguments = $this->buildInlineExtensionConfig($codeceptionArguments, $options); + } + + return $codeceptionArguments; + } + + /** + * @param \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments $codeceptionArguments + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + protected function enableSuiteFilterExtension(CodeceptionArguments $codeceptionArguments): CodeceptionArguments + { + return $codeceptionArguments->addArgument( + '--ext', + ['\\' . SuiteFilterHelper::class], + ); + } + + /** + * @param \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments $codeceptionArguments + * @param array $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + protected function buildInlineExtensionConfig(CodeceptionArguments $codeceptionArguments, array $options): CodeceptionArguments + { + $extensionInlineConfigTemplate = 'extensions: config: %s: inclusive: [%s]'; + + $inclusiveGroups = $this->defaultInclusiveTestGroups; + $inclusiveGroups[] = $options[static::OPTION_MODULE]; + + $suiteFilterHelperClassName = '\\' . SuiteFilterHelper::class; + $inclusiveGroupsAsString = implode(',', $inclusiveGroups); + + $extensionInlineConfig = sprintf( + $extensionInlineConfigTemplate, + $suiteFilterHelperClassName, + $inclusiveGroupsAsString, + ); + + return $codeceptionArguments->addArgument( + '-o', + [$extensionInlineConfig], + ); + } +} diff --git a/src/Spryker/Zed/Development/Business/Codeception/Argument/Builder/CodeceptionArgumentsBuilderInterface.php b/src/Spryker/Zed/Development/Business/Codeception/Argument/Builder/CodeceptionArgumentsBuilderInterface.php new file mode 100644 index 00000000..f4078325 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Codeception/Argument/Builder/CodeceptionArgumentsBuilderInterface.php @@ -0,0 +1,20 @@ + $options + * + * @return \Spryker\Zed\Development\Business\Codeception\Argument\CodeceptionArguments + */ + public function build(array $options): CodeceptionArguments; +} diff --git a/src/Spryker/Zed/Development/Business/Codeception/Argument/CodeceptionArguments.php b/src/Spryker/Zed/Development/Business/Codeception/Argument/CodeceptionArguments.php new file mode 100644 index 00000000..45ad713d --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Codeception/Argument/CodeceptionArguments.php @@ -0,0 +1,46 @@ + + */ + protected $arguments = []; + + /** + * @param string $argumentName + * @param array $argumentValues + * + * @return $this + */ + public function addArgument(string $argumentName, array $argumentValues = []) + { + if (!$argumentValues) { + $this->arguments[] = $argumentName; + + return $this; + } + + foreach ($argumentValues as $value) { + $this->arguments[] = $argumentName; + $this->arguments[] = $value; + } + + return $this; + } + + /** + * @return array + */ + public function getArguments(): array + { + return $this->arguments; + } +} diff --git a/src/Spryker/Zed/Development/Business/Composer/ComposerJson.php b/src/Spryker/Zed/Development/Business/Composer/ComposerJson.php index 648c4217..afdbc808 100644 --- a/src/Spryker/Zed/Development/Business/Composer/ComposerJson.php +++ b/src/Spryker/Zed/Development/Business/Composer/ComposerJson.php @@ -63,8 +63,10 @@ protected function hasComposerJson(ModuleTransfer $moduleTransfer): bool protected function getComposerJsonAsArray(ModuleTransfer $moduleTransfer): array { $composerJsonFilePath = $this->getComposerJsonFilePath($moduleTransfer); + /** @var string $fileContent */ + $fileContent = file_get_contents($composerJsonFilePath); - return json_decode(file_get_contents($composerJsonFilePath), true); + return json_decode($fileContent, true); } /** diff --git a/src/Spryker/Zed/Development/Business/Composer/ComposerJsonFinder.php b/src/Spryker/Zed/Development/Business/Composer/ComposerJsonFinder.php index e3426dd0..f1cdb207 100644 --- a/src/Spryker/Zed/Development/Business/Composer/ComposerJsonFinder.php +++ b/src/Spryker/Zed/Development/Business/Composer/ComposerJsonFinder.php @@ -13,6 +13,9 @@ class ComposerJsonFinder implements ComposerJsonFinderInterface { + /** + * @var string + */ protected const COMPOSER_JSON_FILE_NAME = 'composer.json'; /** @@ -45,7 +48,10 @@ public function findByModule(ModuleTransfer $module): ?SplFileInfo return null; } - return iterator_to_array($currentFinderInstance, false)[0]; + $finderAsArray = iterator_to_array($currentFinderInstance, false); + + /** @phpstan-var \Symfony\Component\Finder\SplFileInfo|null */ + return reset($finderAsArray); } /** diff --git a/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdater.php b/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdater.php index 03ef828b..90a4c87c 100644 --- a/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdater.php @@ -7,16 +7,23 @@ namespace Spryker\Zed\Development\Business\Composer; +use Laminas\Filter\Word\CamelCaseToDash; use RuntimeException; use Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface; +use Spryker\Zed\Development\Business\Composer\Util\ComposerJson; use Spryker\Zed\Development\Business\Exception\DependencyTree\InvalidComposerJsonException; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\Word\CamelCaseToDash; class ComposerJsonUpdater implements ComposerJsonUpdaterInterface { - public const REPLACE_4_WITH_2_SPACES = '/^( +?)\\1(?=[^ ])/m'; + /** + * @var string + */ public const KEY_REQUIRE = 'require'; + + /** + * @var string + */ public const KEY_REQUIRE_DEV = 'require-dev'; /** @@ -40,7 +47,7 @@ public function __construct(ComposerJsonFinderInterface $finder, UpdaterInterfac } /** - * @param \Generated\Shared\Transfer\ModuleTransfer[] $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $moduleTransferCollection * @param bool $dryRun * * @return array @@ -72,7 +79,11 @@ public function update(array $moduleTransferCollection, $dryRun = false) protected function updateComposerJsonFile(SplFileInfo $composerJsonFile, $dryRun = false) { $composerJson = $composerJsonFile->getContents(); - $composerJsonArray = json_decode($composerJson, true); + $composerJsonArray = ComposerJson::fromString($composerJson); + + if (!empty($composerJsonArray['abandoned'])) { + return false; + } $this->assertCorrectName($composerJsonArray['name'], $composerJsonFile); @@ -80,8 +91,7 @@ protected function updateComposerJsonFile(SplFileInfo $composerJsonFile, $dryRun $composerJsonArray = $this->clean($composerJsonArray); $composerJsonArray = $this->order($composerJsonArray); - $modifiedComposerJson = json_encode($composerJsonArray, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); - $modifiedComposerJson = preg_replace(static::REPLACE_4_WITH_2_SPACES, '$1', $modifiedComposerJson) . PHP_EOL; + $modifiedComposerJson = ComposerJson::toString($composerJsonArray); if ($modifiedComposerJson === $composerJson) { return false; @@ -144,6 +154,7 @@ protected function order(array $composerJson) 'config', ]; + /** @phpstan-var callable((int|string), (int|string)): int */ $callable = function ($a, $b) use ($map) { $keyA = in_array($a, $map) ? array_search($a, $map) : 999; $keyB = in_array($b, $map) ? array_search($b, $map) : 999; @@ -151,6 +162,7 @@ protected function order(array $composerJson) if ($keyA === $keyB) { return 0; } + return $keyA > $keyB; }; @@ -170,7 +182,9 @@ protected function order(array $composerJson) protected function assertCorrectName(string $composerName, SplFileInfo $composerJsonFile) { $filter = new CamelCaseToDash(); - $moduleName = mb_strtolower($filter->filter(basename($composerJsonFile->getPath()))); + /** @var string $camelCasedModule */ + $camelCasedModule = $filter->filter(basename($composerJsonFile->getPath())); + $moduleName = mb_strtolower($camelCasedModule); $organization = $this->getOrganizationFromComposerJsonFile($composerJsonFile); $expected = $organization . '/' . $moduleName; @@ -188,17 +202,24 @@ protected function assertCorrectName(string $composerName, SplFileInfo $composer */ protected function getOrganizationFromComposerJsonFile(SplFileInfo $composerJsonFile) { - if (preg_match('/vendor\/spryker\/([a-z_-]+)\/Bundles\/\w+\/composer.json$/', $composerJsonFile->getRealPath(), $matches)) { + /** @var string $realPath */ + $realPath = $composerJsonFile->getRealPath(); + + if (preg_match('/vendor\/spryker\/([a-z_-]+)\/Bundles\/\w+\/composer.json$/', $realPath, $matches)) { return $matches[1]; } - if (preg_match('/vendor\/([a-z_-]+)\/[a-z_-]+\/composer.json$/', $composerJsonFile->getRealPath(), $matches)) { + if (preg_match('/vendor\/spryker\/spryker\/Features\/\w+\/composer.json$/', $realPath, $matches)) { + return 'spryker-feature'; + } + + if (preg_match('/vendor\/([a-z_-]+)\/[a-z_-]+\/composer.json$/', $realPath, $matches)) { return $matches[1]; } throw new InvalidComposerJsonException(sprintf( 'Unable to locate organization name from %s.', - $composerJsonFile->getRealPath() + $realPath, )); } } diff --git a/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdaterInterface.php b/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdaterInterface.php index e15fe414..640f2690 100644 --- a/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdaterInterface.php +++ b/src/Spryker/Zed/Development/Business/Composer/ComposerJsonUpdaterInterface.php @@ -10,7 +10,7 @@ interface ComposerJsonUpdaterInterface { /** - * @param \Generated\Shared\Transfer\ModuleTransfer[] $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $moduleTransferCollection * @param bool $dryRun * * @return array diff --git a/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php b/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php new file mode 100644 index 00000000..9d9164d6 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinder.php @@ -0,0 +1,184 @@ + + */ + protected $moduleTransferCollection = []; + + /** + * @var array>|null + */ + protected $moduleTransferCollectionGroupedByModuleName; + + /** + * @var array<\Generated\Shared\Transfer\PackageTransfer>|null + */ + protected $packageTransferCollectionGroupedByPackageName; + + /** + * @param \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade + */ + public function __construct(DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade) + { + $this->moduleFinderFacade = $moduleFinderFacade; + } + + /** + * @param string $moduleName + * + * @return string|null + */ + public function findComposerNameByModuleName(string $moduleName): ?string + { + $composerName = $this->getComposerNameFromModuleCollection($moduleName); + if ($composerName !== null) { + return $composerName; + } + + $composerName = $this->getComposerNameFromPackageCollection($moduleName); + if ($composerName !== null) { + return $composerName; + } + + return null; + } + + /** + * @param string $moduleName + * + * @return string|null + */ + protected function getComposerNameFromModuleCollection(string $moduleName): ?string + { + /** @deprecated This is to make spryker/silex optional. */ + if ($moduleName === 'Silex') { + return 'spryker/silex'; + } + + if ($this->isNamespacedModuleName($moduleName)) { + $moduleTransfer = $this->getModuleTransferCollection()[$moduleName]; + + return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed()); + } + + $moduleTransferCollection = $this->getModuleTransferCollectionGroupedByModuleName(); + + if (!isset($moduleTransferCollection[$moduleName])) { + return null; + } + + if (count($moduleTransferCollection[$moduleName]) > 1) { + return null; + } + + $moduleTransfer = $this->getCurrentModuleTransfer($moduleTransferCollection[$moduleName]); + + return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed()); + } + + /** + * @return array<\Generated\Shared\Transfer\ModuleTransfer> + */ + protected function getModuleTransferCollection(): array + { + if (!$this->moduleTransferCollection) { + $this->moduleTransferCollection = $this->moduleFinderFacade->getModules(); + } + + return $this->moduleTransferCollection; + } + + /** + * @param string $module + * + * @return bool + */ + protected function isNamespacedModuleName(string $module): bool + { + return (strpos($module, '.') !== false); + } + + /** + * @param string $moduleName + * + * @return string|null + */ + protected function getComposerNameFromPackageCollection(string $moduleName): ?string + { + $packageTransferCollection = $this->getPackageTransferCollectionGroupedByPackageName(); + + if (isset($packageTransferCollection[$moduleName])) { + $packageTransfer = $packageTransferCollection[$moduleName]; + + return $packageTransfer->getComposerName(); + } + + return null; + } + + /** + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $moduleTransferCollection + * + * @return \Generated\Shared\Transfer\ModuleTransfer + */ + protected function getCurrentModuleTransfer(array $moduleTransferCollection): ModuleTransfer + { + /** @var \Generated\Shared\Transfer\ModuleTransfer */ + return current($moduleTransferCollection); + } + + /** + * @return array> + */ + protected function getModuleTransferCollectionGroupedByModuleName(): array + { + if ($this->moduleTransferCollectionGroupedByModuleName !== null) { + return $this->moduleTransferCollectionGroupedByModuleName; + } + + $moduleTransferCollection = $this->getModuleTransferCollection(); + $this->moduleTransferCollectionGroupedByModuleName = []; + + foreach ($moduleTransferCollection as $moduleTransfer) { + $this->moduleTransferCollectionGroupedByModuleName[$moduleTransfer->getName()][] = $moduleTransfer; + } + + return $this->moduleTransferCollectionGroupedByModuleName; + } + + /** + * @return array<\Generated\Shared\Transfer\PackageTransfer> + */ + protected function getPackageTransferCollectionGroupedByPackageName(): array + { + if ($this->packageTransferCollectionGroupedByPackageName !== null) { + return $this->packageTransferCollectionGroupedByPackageName; + } + + $packageTransferCollection = $this->moduleFinderFacade->getPackages(); + $this->packageTransferCollectionGroupedByPackageName = []; + + foreach ($packageTransferCollection as $packageTransfer) { + $this->packageTransferCollectionGroupedByPackageName[$packageTransfer->getPackageName()] = $packageTransfer; + } + + return $this->packageTransferCollectionGroupedByPackageName; + } +} diff --git a/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinderInterface.php b/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinderInterface.php new file mode 100644 index 00000000..587e02b1 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Composer/ComposerNameFinderInterface.php @@ -0,0 +1,18 @@ +assertAllowPluginsConfig($path, $composerJson); + + if (isset($composerJson[static::KEY_CONFIG]) && empty($composerJson[static::KEY_CONFIG])) { + $composerJson[static::KEY_CONFIG] = new stdClass(); + } + + return $composerJson; + } + + /** + * @param string $path + * @param array $jsonArray + * + * @return array + */ + protected function assertAllowPluginsConfig(string $path, array $jsonArray): array + { + $requiresCodeSniffer = is_dir($path . 'src'); + if (!$requiresCodeSniffer) { + unset($jsonArray['config']['allow-plugins']); + + return $jsonArray; + } + + $jsonArray['config']['allow-plugins'] = [ + 'dealerdirect/phpcodesniffer-composer-installer' => true, + ]; + + return $jsonArray; + } +} diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/AutoloadUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/AutoloadUpdater.php index 1c33c4a7..be95808b 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/AutoloadUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/AutoloadUpdater.php @@ -7,36 +7,141 @@ namespace Spryker\Zed\Development\Business\Composer\Updater; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\DashToCamelCase; use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\DashToCamelCase; class AutoloadUpdater implements UpdaterInterface { + /** + * @var string + */ public const AUTOLOAD_KEY = 'autoload'; + + /** + * @var string + */ public const AUTOLOAD_DEV_KEY = 'autoload-dev'; + /** + * @var string + */ public const BASE_TESTS_DIRECTORY = 'tests'; + + /** + * @var string + */ public const BASE_SRC_DIRECTORY = 'src'; + + /** + * @var string + */ public const BASE_SUPPORT_DIRECTORY = '_support'; + + /** + * @var string + */ public const BASE_HELPER_DIRECTORY = 'Helper'; + /** + * @var string + */ + protected const BASE_PAGE_OBJECT_DIRECTORY = 'PageObject'; + + /** + * @var string + */ + public const BASE_TESTER_DIRECTORY = 'Tester'; + + /** + * @var string + */ + public const BASE_FIXTURES_DIRECTORY = 'Fixtures'; + + /** + * @var string + */ + public const BASE_STEP_OVERRIDE_DIRECTORY = 'StepOverride'; + + /** + * @var string + */ + public const BASE_FILTER_DIRECTORY = 'Filter'; + + /** + * @var string + */ + public const POLYFILL_NAMESPACE = 'Polyfill'; + + /** + * @var string + */ public const SPRYKER_TEST_NAMESPACE = 'SprykerTest'; + + /** + * @var string + */ public const SPRYKER_SDK_TEST_NAMESPACE = 'SprykerSdkTest'; + + /** + * @var string + */ public const SPRYKER_ECO_TEST_NAMESPACE = 'SprykerEcoTest'; + + /** + * @var string + */ public const SPRYKER_SHOP_TEST_NAMESPACE = 'SprykerShopTest'; + + /** + * @var string + */ public const SPRYKER_MERCHANT_PORTAL_SHOP_TEST_NAMESPACE = 'SprykerMerchantPortalTest'; + /** + * @var string + */ public const SPRYKER_NAMESPACE = 'Spryker'; + + /** + * @var string + */ + public const SPRYKER_FEATURE_NAMESPACE = 'SprykerFeature'; + + /** + * @var string + */ public const SPRYKER_SHOP_NAMESPACE = 'SprykerShop'; + + /** + * @var string + */ public const SPRYKER_ECO_NAMESPACE = 'SprykerEco'; + + /** + * @var string + */ public const SPRYKER_SDK_NAMESPACE = 'SprykerSdk'; + + /** + * @var string + */ public const SPRYKER_MERCHANT_PORTAL_NAMESPACE = 'SprykerMerchantPortal'; + /** + * @var string + */ public const PSR_0 = 'psr-0'; + + /** + * @var string + */ public const PSR_4 = 'psr-4'; + /** + * @var array + */ protected const RESERVED_NAMESPACES = [ 'vendor/', 'tests/_', @@ -56,10 +161,12 @@ class AutoloadUpdater implements UpdaterInterface * @var array */ protected $applications = [ + 'Service', 'Client', 'Shared', 'Yves', 'Zed', + 'Glue', ]; /** @@ -67,11 +174,18 @@ class AutoloadUpdater implements UpdaterInterface */ protected $autoloadPSR4Whitelist = [ self::SPRYKER_NAMESPACE, + self::SPRYKER_FEATURE_NAMESPACE, self::SPRYKER_SHOP_NAMESPACE, self::SPRYKER_ECO_NAMESPACE, self::BASE_HELPER_DIRECTORY, + self::BASE_PAGE_OBJECT_DIRECTORY, + self::BASE_TESTER_DIRECTORY, + self::BASE_STEP_OVERRIDE_DIRECTORY, + self::BASE_FIXTURES_DIRECTORY, + self::BASE_FILTER_DIRECTORY, self::SPRYKER_SDK_NAMESPACE, self::SPRYKER_MERCHANT_PORTAL_NAMESPACE, + self::POLYFILL_NAMESPACE, ]; /** @@ -102,7 +216,7 @@ class AutoloadUpdater implements UpdaterInterface * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { $composerJson = $this->updateAutoload($composerJson, $composerJsonFile); @@ -203,11 +317,17 @@ protected function updateAutoloadWithSupportTestClasses(array $composerJson, $mo */ protected function getNonEmptyDirectoriesWithHelpers($directory) { - $files = (new Finder())->files()->in($directory)->name('/Helper.php$/'); + $files = (new Finder())->files()->in($directory) + ->exclude('_generated') + ->name('*.php$') + ->notName('/Tester.php$/'); + $directories = []; foreach ($files as $file) { - $directoryName = dirname(str_replace('//', '/', $file)); - if (!in_array($directoryName, $directories)) { + /** @var string $name */ + $name = str_replace('//', '/', $file); + $directoryName = dirname($name); + if (!in_array($directoryName, $directories, true)) { $directories[] = $directoryName; } } @@ -223,6 +343,7 @@ protected function getNonEmptyDirectoriesWithHelpers($directory) protected function getLastPartOfPath($path) { $pathArray = explode(DIRECTORY_SEPARATOR, rtrim($path, DIRECTORY_SEPARATOR)); + return end($pathArray); } @@ -265,7 +386,7 @@ protected function updateAutoloadDevForDeprecatedTestKeys(array $composerJson, $ rtrim($modulePath, DIRECTORY_SEPARATOR), static::BASE_TESTS_DIRECTORY, $testDirectoryKey, - ] + ], ); if ($this->pathExists($directoryPath)) { @@ -317,13 +438,13 @@ protected function buildTestDirectoryKeys() } /** - * @param array $pathParts + * @param array $pathParts * * @return string */ protected function getPath(array $pathParts) { - return implode($pathParts, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + return implode(DIRECTORY_SEPARATOR, $pathParts) . DIRECTORY_SEPARATOR; } /** @@ -390,7 +511,7 @@ protected function cleanupAutoload(array $composerJson, $modulePath) static::AUTOLOAD_KEY => [$this, 'removeInvalidAutoloadPaths'], static::AUTOLOAD_DEV_KEY => [$this, 'removeInvalidAutoloadNamespaces'], ], - $modulePath + $modulePath, ); $composerJson = $this->removeAutoloadDuplicates($composerJson); @@ -439,7 +560,7 @@ protected function removeInvalidAutoloadPaths(array $autoload, $modulePath) $relativeDirectory, ]); - if (!$this->pathExists($path) || !in_array($this->getLastPartOfPath($relativeDirectory), $this->autoloadPSR4Whitelist)) { + if (!$this->pathExists($path) || !in_array($this->getLastPartOfPath($relativeDirectory), $this->autoloadPSR4Whitelist, true)) { if ($this->isFile($path)) { continue; } diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/BranchAliasUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/BranchAliasUpdater.php index 9adabc79..d97e73fd 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/BranchAliasUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/BranchAliasUpdater.php @@ -13,8 +13,19 @@ class BranchAliasUpdater implements UpdaterInterface { + /** + * @var string + */ public const KEY_EXTRA = 'extra'; + + /** + * @var string + */ public const KEY_BRANCH_ALIAS = 'branch-alias'; + + /** + * @var string + */ public const KEY_MASTER_BRANCH = 'dev-master'; /** @@ -23,7 +34,7 @@ class BranchAliasUpdater implements UpdaterInterface * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { if (!Config::hasValue(DevelopmentConstants::COMPOSER_BRANCH_ALIAS)) { return $composerJson; @@ -31,9 +42,9 @@ public function update(array $composerJson, SplFileInfo $composerJsonFile) $alias = Config::get(DevelopmentConstants::COMPOSER_BRANCH_ALIAS); $composerJson[static::KEY_EXTRA] = [ - static::KEY_BRANCH_ALIAS => [ - static::KEY_MASTER_BRANCH => $alias, - ], + static::KEY_BRANCH_ALIAS => [ + static::KEY_MASTER_BRANCH => $alias, + ], ]; return $composerJson; diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/ComposerUpdaterComposite.php b/src/Spryker/Zed/Development/Business/Composer/Updater/ComposerUpdaterComposite.php index 08735368..f55e8766 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/ComposerUpdaterComposite.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/ComposerUpdaterComposite.php @@ -12,7 +12,7 @@ class ComposerUpdaterComposite implements ComposerUpdaterCompositeInterface { /** - * @var \Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface[] + * @var array<\Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface> */ protected $updater; @@ -34,7 +34,7 @@ public function addUpdater(UpdaterInterface $updater) * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { foreach ($this->updater as $updater) { $composerJson = $updater->update($composerJson, $composerJsonFile); diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/DescriptionUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/DescriptionUpdater.php index e8749200..a23919d6 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/DescriptionUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/DescriptionUpdater.php @@ -7,13 +7,16 @@ namespace Spryker\Zed\Development\Business\Composer\Updater; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\DashToCamelCase; +use Laminas\Filter\Word\UnderscoreToCamelCase; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\DashToCamelCase; -use Zend\Filter\Word\UnderscoreToCamelCase; class DescriptionUpdater implements UpdaterInterface { + /** + * @var string + */ public const KEY_DESCRIPTION = 'description'; /** @@ -22,7 +25,7 @@ class DescriptionUpdater implements UpdaterInterface * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { $composerJson[static::KEY_DESCRIPTION] = $this->getModuleNameFromFullPath($composerJsonFile->getPath()) . ' module'; diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/LicenseUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/LicenseUpdater.php index d25a1856..bbbf97a8 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/LicenseUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/LicenseUpdater.php @@ -12,16 +12,34 @@ class LicenseUpdater implements UpdaterInterface { + /** + * @var string + */ protected const KEY_LICENSE = 'license'; + /** + * @var string + */ protected const LICENSE_TYPE_MIT = 'MIT'; + /** + * @var string + */ protected const LICENSE_TYPE_PROPRIETARY = 'proprietary'; + /** + * @var string + */ protected const MIT_LICENSE = 'The MIT License (MIT)'; + /** + * @var int + */ protected const LICENSE_FILE_DEPTH = 0; + /** + * @var string + */ protected const LICENSE_FILE_NAME = 'LICENSE'; /** @@ -30,7 +48,7 @@ class LicenseUpdater implements UpdaterInterface * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { $modulePath = dirname($composerJsonFile->getPathname()); $license = static::LICENSE_TYPE_PROPRIETARY; diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/RequireDevUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/RequireDevUpdater.php new file mode 100644 index 00000000..a4c6f01c --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/RequireDevUpdater.php @@ -0,0 +1,60 @@ +assertCodeSniffer($path, $composerJson); + + return $composerJson; + } + + /** + * @param string $path + * @param array $composerJson + * + * @return array + */ + protected function assertCodeSniffer(string $path, array $composerJson): array + { + $requiresCodeSniffer = is_dir($path . 'src'); + + if ($requiresCodeSniffer && isset($composerJson[static::KEY_REQUIRE_DEV][static::PACKAGE_CODE_SNIFFER])) { + return $composerJson; + } + + if ($requiresCodeSniffer && !isset($composerJson[static::KEY_REQUIRE_DEV][static::PACKAGE_CODE_SNIFFER])) { + $composerJson[static::KEY_REQUIRE_DEV][static::PACKAGE_CODE_SNIFFER] = '*'; + } elseif (!$requiresCodeSniffer) { + unset($composerJson[static::KEY_REQUIRE_DEV][static::PACKAGE_CODE_SNIFFER]); + } + + return $composerJson; + } +} diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/RequireExternalUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/RequireExternalUpdater.php index 19d5c682..71d4e4b3 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/RequireExternalUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/RequireExternalUpdater.php @@ -7,17 +7,28 @@ namespace Spryker\Zed\Development\Business\Composer\Updater; +use Laminas\Filter\Word\CamelCaseToDash; +use Laminas\Filter\Word\DashToCamelCase; use Spryker\Shared\Config\Config; use Spryker\Shared\Development\DevelopmentConstants; use Spryker\Zed\Development\Business\DependencyTree\DependencyTree; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\Word\CamelCaseToDash; -use Zend\Filter\Word\DashToCamelCase; class RequireExternalUpdater implements UpdaterInterface { + /** + * @var string + */ public const KEY_REQUIRE = 'require'; + + /** + * @var string + */ public const RELEASE_OPERATOR = '^'; + + /** + * @var string + */ public const KEY_NAME = 'name'; /** @@ -26,19 +37,19 @@ class RequireExternalUpdater implements UpdaterInterface protected $externalDependencyTree; /** - * @var array + * @var array */ protected $externalToInternalMap; /** - * @var array + * @var array */ protected $ignorableDependencies; /** * @param array $externalDependencyTree - * @param array $externalToInternalMap - * @param array $ignorableDependencies + * @param array $externalToInternalMap + * @param array $ignorableDependencies */ public function __construct(array $externalDependencyTree, array $externalToInternalMap, array $ignorableDependencies) { @@ -53,7 +64,7 @@ public function __construct(array $externalDependencyTree, array $externalToInte * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { $moduleName = $this->getModuleName($composerJson); @@ -69,11 +80,13 @@ public function update(array $composerJson, SplFileInfo $composerJsonFile) } foreach ($dependentModules as $dependentModule) { - if (empty($dependentModule) || $dependentModule === $composerJson[static::KEY_NAME]) { + if (!$dependentModule || $dependentModule === $composerJson[static::KEY_NAME]) { continue; } $filter = new CamelCaseToDash(); - $dependentModule = strtolower($filter->filter($dependentModule)); + /** @var string $camelCasedDependentModule */ + $camelCasedDependentModule = $filter->filter($dependentModule); + $dependentModule = strtolower($camelCasedDependentModule); $composerJson[static::KEY_REQUIRE][$dependentModule] = static::RELEASE_OPERATOR . $composerRequireVersion; } @@ -92,7 +105,10 @@ protected function getModuleName(array $composerJsonData) $moduleName = array_pop($nameParts); $filter = new DashToCamelCase(); - return (string)$filter->filter($moduleName); + /** @var string $camelCasedModuleName */ + $camelCasedModuleName = $filter->filter($moduleName); + + return (string)$camelCasedModuleName; } /** @@ -104,10 +120,17 @@ protected function getExternalModules($bundleName) { $dependentModules = []; foreach ($this->externalDependencyTree as $dependency) { - if ($dependency[DependencyTree::META_MODULE] === $bundleName - && !in_array($dependency[DependencyTree::META_COMPOSER_NAME], $this->ignorableDependencies) + if ( + $dependency[DependencyTree::META_MODULE] === $bundleName + && !in_array($dependency[DependencyTree::META_COMPOSER_NAME], $this->ignorableDependencies, true) ) { - $dependentModules[] = $this->mapExternalToInternal($dependency[DependencyTree::META_COMPOSER_NAME]); + $dependentModule = $this->mapExternalToInternal($dependency[DependencyTree::META_COMPOSER_NAME]); + + if ($dependentModule === null) { + continue; + } + + $dependentModules[] = $dependentModule; } } $dependentModules = array_unique($dependentModules); @@ -119,12 +142,12 @@ protected function getExternalModules($bundleName) /** * @param string $composerName * - * @return string + * @return string|null */ protected function mapExternalToInternal($composerName) { foreach ($this->externalToInternalMap as $external => $internal) { - if ($external[0] === '/') { + if (substr($external, 0, 1) === '/') { if (preg_match($external, $composerName)) { return $internal; } @@ -132,5 +155,7 @@ protected function mapExternalToInternal($composerName) return $internal; } } + + return null; } } diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/RequireUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/RequireUpdater.php index 7aaceceb..60414e69 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/RequireUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/RequireUpdater.php @@ -11,9 +11,20 @@ class RequireUpdater implements UpdaterInterface { + /** + * @var string + */ public const KEY_REQUIRE = 'require'; + + /** + * @var string + */ public const KEY_REQUIRE_PHP = 'php'; - public const PHP_MINIMUM = '>=7.1'; + + /** + * @var string + */ + public const PHP_MINIMUM = '>=8.0'; /** * @param array $composerJson @@ -21,7 +32,7 @@ class RequireUpdater implements UpdaterInterface * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { $composerJson = $this->requirePhpVersion($composerJson); diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/ScriptsUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/ScriptsUpdater.php new file mode 100644 index 00000000..730daa57 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/ScriptsUpdater.php @@ -0,0 +1,99 @@ +assertCsScripts($path, $composerJson); + + if (isset($composerJson[static::KEY_SCRIPTS]) && empty($composerJson[static::KEY_SCRIPTS])) { + $composerJson[static::KEY_SCRIPTS] = new stdClass(); + } + + return $composerJson; + } + + /** + * @param string $path + * @param array $jsonArray + * + * @return array + */ + protected function assertCsScripts(string $path, array $jsonArray): array + { + $requiresCodeSniffer = is_dir($path . 'src'); + if (!$requiresCodeSniffer) { + unset($jsonArray['scripts']['cs-check']); + unset($jsonArray['scripts']['cs-fix']); + + return $jsonArray; + } + + $standard = $this->extractStandard($path); + $folders = [ + 'src/', + ]; + if (is_dir($path . 'tests')) { + $folders[] = 'tests/'; + } + + $currentCsCheck = $jsonArray['scripts']['cs-check'] ?? ''; + $ignores = ''; + preg_match('/--ignore=[^ ]+/', $currentCsCheck, $matches); + if ($matches) { + $ignores = $matches[0] . ' '; + } + + $standardPath = '--standard=vendor/spryker/code-sniffer/' . $standard . '/ruleset.xml '; + + $newCsCheck = 'phpcs -p -s ' . $standardPath . $ignores . implode(' ', $folders); + $newCsFix = 'phpcbf -p ' . $standardPath . $ignores . implode(' ', $folders); + + $jsonArray['scripts']['cs-check'] = $newCsCheck; + $jsonArray['scripts']['cs-fix'] = $newCsFix; + + return $jsonArray; + } + + /** + * @param string $path + * + * @return string + */ + protected function extractStandard(string $path): string + { + $standard = 'Spryker'; + if (file_exists($path . 'tooling.yml')) { + $yamlParser = new Parser(); + $config = $yamlParser->parseFile($path . 'tooling.yml'); + if (!empty($config['code-sniffer']['level']) && $config['code-sniffer']['level'] === 2) { + return 'SprykerStrict'; + } + } + + return $standard; + } +} diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/StabilityUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/StabilityUpdater.php index 3e4dc43e..43235c5f 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/StabilityUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/StabilityUpdater.php @@ -11,7 +11,14 @@ class StabilityUpdater implements UpdaterInterface { + /** + * @var string + */ public const KEY_MINIMUM_STABILITY = 'minimum-stability'; + + /** + * @var string + */ public const KEY_PREFER_STABLE = 'prefer-stable'; /** @@ -33,7 +40,7 @@ public function __construct($stability) * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { $composerJson = $this->updateMinimumStability($composerJson); $composerJson = $this->updatePreferStable($composerJson); diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/TypeUpdater.php b/src/Spryker/Zed/Development/Business/Composer/Updater/TypeUpdater.php index 0dfe8307..fe14cb88 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/TypeUpdater.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/TypeUpdater.php @@ -11,6 +11,9 @@ class TypeUpdater implements UpdaterInterface { + /** + * @var string + */ public const KEY_TYPE = 'type'; /** @@ -19,7 +22,7 @@ class TypeUpdater implements UpdaterInterface * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile) + public function update(array $composerJson, SplFileInfo $composerJsonFile): array { $composerJson[static::KEY_TYPE] = 'library'; diff --git a/src/Spryker/Zed/Development/Business/Composer/Updater/UpdaterInterface.php b/src/Spryker/Zed/Development/Business/Composer/Updater/UpdaterInterface.php index 3a045754..1a681b7a 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Updater/UpdaterInterface.php +++ b/src/Spryker/Zed/Development/Business/Composer/Updater/UpdaterInterface.php @@ -17,5 +17,5 @@ interface UpdaterInterface * * @return array */ - public function update(array $composerJson, SplFileInfo $composerJsonFile); + public function update(array $composerJson, SplFileInfo $composerJsonFile): array; } diff --git a/src/Spryker/Zed/Development/Business/Composer/Util/ComposerJson.php b/src/Spryker/Zed/Development/Business/Composer/Util/ComposerJson.php new file mode 100644 index 00000000..e09b3375 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Composer/Util/ComposerJson.php @@ -0,0 +1,103 @@ + + */ + protected static $objectKeys = [ + 'autoload', + 'autoload-dev', + 'require', + 'require-dev', + 'config', + 'scripts', + ]; + + /** + * @param string $file + * + * @throws \RuntimeException + * + * @return array + */ + public static function fromFile(string $file): array + { + $content = file_get_contents($file); + if ($content === false) { + throw new RuntimeException('Cannot decode composer.json file'); + } + + return static::fromString($content); + } + + /** + * @param string $string + * + * @throws \RuntimeException + * + * @return array + */ + public static function fromString(string $string): array + { + $array = json_decode($string, true); + if (!$array) { + throw new RuntimeException('Cannot decode composer.json content'); + } + + return $array; + } + + /** + * @param array $array + * + * @throws \RuntimeException + * + * @return string + */ + public static function toString(array $array): string + { + $objectKeys = static::$objectKeys; + foreach ($objectKeys as $objectKey) { + if (!isset($array[$objectKey]) || !empty($array[$objectKey])) { + continue; + } + + $array[$objectKey] = (object)$array[$objectKey]; + } + + $json = json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + if ($json === false) { + throw new RuntimeException('Cannot encode fixed composer.json file'); + } + + return $json . PHP_EOL; + } + + /** + * @param string $file + * @param array $array + * + * @throws \RuntimeException + * + * @return void + */ + public static function toFile(string $file, array $array): void + { + $json = static::toString($array); + + $result = file_put_contents($file, $json); + if ($result === false) { + throw new RuntimeException('Cannot write to composer.json file'); + } + } +} diff --git a/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonPackageNameValidator.php b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonPackageNameValidator.php new file mode 100644 index 00000000..fd00548d --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonPackageNameValidator.php @@ -0,0 +1,66 @@ + $version) { + $composerJsonValidationResponseTransfer = $this->assertPackageName($packageName, $composerJsonValidationResponseTransfer); + } + + $requireDev = $composerJsonArray[static::REQUIRE_DEV] ?? []; + foreach ($requireDev as $packageName => $version) { + $composerJsonValidationResponseTransfer = $this->assertPackageName($packageName, $composerJsonValidationResponseTransfer); + } + + return $composerJsonValidationResponseTransfer; + } + + /** + * @param string $packageName + * @param \Generated\Shared\Transfer\ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer + * + * @return \Generated\Shared\Transfer\ComposerJsonValidationResponseTransfer + */ + protected function assertPackageName( + string $packageName, + ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer + ): ComposerJsonValidationResponseTransfer { + if (mb_strtolower($packageName) !== $packageName) { + $validationMessageTransfer = new ValidationMessageTransfer(); + $validationMessageTransfer->setMessage(sprintf('Package name `%s` is not in valid lowercase only format.', $packageName)); + $composerJsonValidationResponseTransfer->addValidationMessage($validationMessageTransfer); + } + + return $composerJsonValidationResponseTransfer; + } +} diff --git a/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonUnboundRequireConstraintValidator.php b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonUnboundRequireConstraintValidator.php index 0de5da4d..bdd122a1 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonUnboundRequireConstraintValidator.php +++ b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonUnboundRequireConstraintValidator.php @@ -12,6 +12,9 @@ class ComposerJsonUnboundRequireConstraintValidator implements ComposerJsonValidatorInterface { + /** + * @var string + */ protected const REQUIRE = 'require'; /** @@ -20,13 +23,18 @@ class ComposerJsonUnboundRequireConstraintValidator implements ComposerJsonValid * * @return \Generated\Shared\Transfer\ComposerJsonValidationResponseTransfer */ - public function validate(array $composerJsonArray, ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer): ComposerJsonValidationResponseTransfer - { + public function validate( + array $composerJsonArray, + ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer + ): ComposerJsonValidationResponseTransfer { if (!isset($composerJsonArray[static::REQUIRE])) { return $composerJsonValidationResponseTransfer; } foreach ($composerJsonArray[static::REQUIRE] as $packageName => $version) { + if (preg_match('/^ext-/', $packageName)) { + continue; + } if ($version === '*') { $validationMessageTransfer = new ValidationMessageTransfer(); $validationMessageTransfer->setMessage(sprintf('Package "%s" has an unbound version constraint (*).', $packageName)); diff --git a/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorComposite.php b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorComposite.php index 40339530..b158b81f 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorComposite.php +++ b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorComposite.php @@ -12,12 +12,12 @@ class ComposerJsonValidatorComposite implements ComposerJsonValidatorInterface { /** - * @var \Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonValidatorInterface[] + * @var array<\Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonValidatorInterface> */ protected $composerJsonValidator; /** - * @param \Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonValidatorInterface[] $composerJsonValidator + * @param array<\Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonValidatorInterface> $composerJsonValidator */ public function __construct(array $composerJsonValidator) { @@ -30,8 +30,10 @@ public function __construct(array $composerJsonValidator) * * @return \Generated\Shared\Transfer\ComposerJsonValidationResponseTransfer */ - public function validate(array $composerJsonArray, ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer): ComposerJsonValidationResponseTransfer - { + public function validate( + array $composerJsonArray, + ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer + ): ComposerJsonValidationResponseTransfer { foreach ($this->composerJsonValidator as $composerJsonValidator) { $composerJsonValidationResponseTransfer = $composerJsonValidator->validate($composerJsonArray, $composerJsonValidationResponseTransfer); } diff --git a/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorInterface.php b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorInterface.php index b801ab5e..bf4cd916 100644 --- a/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorInterface.php +++ b/src/Spryker/Zed/Development/Business/Composer/Validator/ComposerJsonValidatorInterface.php @@ -17,5 +17,8 @@ interface ComposerJsonValidatorInterface * * @return \Generated\Shared\Transfer\ComposerJsonValidationResponseTransfer */ - public function validate(array $composerJsonArray, ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer): ComposerJsonValidationResponseTransfer; + public function validate( + array $composerJsonArray, + ComposerJsonValidationResponseTransfer $composerJsonValidationResponseTransfer + ): ComposerJsonValidationResponseTransfer; } diff --git a/src/Spryker/Zed/Development/Business/Dependency/ComposerParser/ExternalDependencyParser.php b/src/Spryker/Zed/Development/Business/Dependency/ComposerParser/ExternalDependencyParser.php new file mode 100644 index 00000000..27b0334e --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Dependency/ComposerParser/ExternalDependencyParser.php @@ -0,0 +1,104 @@ + + */ + protected $resolvedComposerNameByClassNameMap = []; + + /** + * @param \Spryker\Zed\Development\DevelopmentConfig $config + */ + public function __construct(DevelopmentConfig $config) + { + $this->config = $config; + } + + /** + * @param string $className + * + * @return string|null + */ + public function findPackageNameByNamespace(string $className): ?string + { + if (isset($this->resolvedComposerNameByClassNameMap[$className])) { + return $this->resolvedComposerNameByClassNameMap[$className]; + } + + if ($this->isPhpInternalClass($className)) { + return null; + } + + try { + $reflectionClass = new ReflectionClass($className); + } catch (Throwable $throwable) { + return null; + } + + /** @var string $fileName */ + $fileName = $reflectionClass->getFileName(); + $pathFragments = explode(DIRECTORY_SEPARATOR, $fileName); + $vendorPosition = array_search('vendor', $pathFragments); + + if ($vendorPosition === false) { + return null; + } + + $vendorNameAndPackageName = array_slice($pathFragments, $vendorPosition + 1, 2); + + $composerName = implode('/', $vendorNameAndPackageName); + + $composerName = $this->mapExternalToInternalPackageName($composerName); + + $this->resolvedComposerNameByClassNameMap[$className] = $composerName; + + return $composerName; + } + + /** + * @param string $className + * + * @return bool + */ + protected function isPhpInternalClass(string $className): bool + { + if (strpos($className, '\\') === false) { + return true; + } + + return false; + } + + /** + * @param string $composerName + * + * @return string + */ + protected function mapExternalToInternalPackageName(string $composerName): string + { + $map = $this->config->getExternalToInternalMap(); + + if (isset($map[$composerName])) { + return $map[$composerName]; + } + + return $composerName; + } +} diff --git a/src/Spryker/Zed/Development/Business/Dependency/ComposerParser/ExternalDependencyParserInterface.php b/src/Spryker/Zed/Development/Business/Dependency/ComposerParser/ExternalDependencyParserInterface.php new file mode 100644 index 00000000..7f76fa20 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Dependency/ComposerParser/ExternalDependencyParserInterface.php @@ -0,0 +1,18 @@ +getModuleNameFromComposerName($composerName); + } + + $isOptional = $this->makeOptionalIfSilex($moduleName, $isOptional); + $dependencyTransfer = new DependencyTransfer(); $dependencyTransfer - ->setModule($module) + ->setModule($moduleName) + ->setComposerName($composerName) ->setType($type) ->setIsOptional($isOptional) ->setIsInTest($isTest); @@ -64,13 +76,18 @@ public function addDependency(string $module, string $type, bool $isOptional = f protected function getDependencyModuleTransfer(DependencyTransfer $dependencyTransfer): DependencyModuleTransfer { foreach ($this->dependencyCollectionTransfer->getDependencyModules() as $dependencyModuleTransfer) { - if ($dependencyModuleTransfer->getModule() === $dependencyTransfer->getModule()) { + if ($dependencyTransfer->getComposerName() === null && $dependencyModuleTransfer->getModule() === $dependencyTransfer->getModule()) { + return $dependencyModuleTransfer; + } + + if ($dependencyTransfer->getComposerName() !== null && $dependencyModuleTransfer->getComposerName() === $dependencyTransfer->getComposerName()) { return $dependencyModuleTransfer; } } $dependencyModuleTransfer = new DependencyModuleTransfer(); $dependencyModuleTransfer->setModule($dependencyTransfer->getModule()); + $dependencyModuleTransfer->setComposerName($dependencyTransfer->getComposerName()); $this->dependencyCollectionTransfer->addDependencyModule($dependencyModuleTransfer); @@ -108,4 +125,37 @@ protected function sortDependencies(DependencyCollectionTransfer $dependencyColl return $dependencyCollectionTransfer; } + + /** + * @param string $composerName + * + * @return string + */ + protected function getModuleNameFromComposerName(string $composerName): string + { + [$organizationName, $moduleName] = explode('/', $composerName); + + $filter = new DashToCamelCase(); + /** @var string $camelCasedModuleName */ + $camelCasedModuleName = $filter->filter($moduleName); + + return ucfirst($camelCasedModuleName); + } + + /** + * @deprecated Will be removed without replacement. + * + * @param string $moduleName + * @param bool $isOptional + * + * @return bool + */ + protected function makeOptionalIfSilex(string $moduleName, bool $isOptional): bool + { + if ($moduleName === 'Silex') { + $isOptional = true; + } + + return $isOptional; + } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainerInterface.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainerInterface.php index 600f20de..8a331048 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainerInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyContainer/DependencyContainerInterface.php @@ -20,14 +20,14 @@ interface DependencyContainerInterface public function initialize(ModuleTransfer $moduleTransfer); /** - * @param string $module + * @param string $moduleOrComposerName * @param string $type * @param bool $isOptional * @param bool $isTest * * @return $this */ - public function addDependency(string $module, string $type, bool $isOptional = false, bool $isTest = false); + public function addDependency(string $moduleOrComposerName, string $type, bool $isOptional = false, bool $isTest = false); /** * @return \Generated\Shared\Transfer\DependencyCollectionTransfer diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/AbstractFileDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/AbstractFileDependencyFinder.php index f1ff67a3..f01afc46 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/AbstractFileDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/AbstractFileDependencyFinder.php @@ -7,16 +7,25 @@ namespace Spryker\Zed\Development\Business\Dependency\DependencyFinder; +use Laminas\Filter\FilterChain; +use Laminas\Filter\StringToLower; +use Laminas\Filter\Word\CamelCaseToDash; + abstract class AbstractFileDependencyFinder implements DependencyFinderInterface { /** - * @param string $module + * @var \Laminas\Filter\FilterChain|null + */ + protected $filter; + + /** + * @param string $moduleOrComposerName * * @return bool */ - protected function isExtensionModule(string $module): bool + protected function isExtensionModule(string $moduleOrComposerName): bool { - return preg_match('/Extension$/', $module); + return (bool)preg_match('/Extension$|-extension$/', $moduleOrComposerName); } /** @@ -38,4 +47,34 @@ protected function isTestFile(string $filePath) { return !strpos($filePath, '/src/'); } + + /** + * @param string $organizationName + * @param string $moduleName + * + * @return string + */ + protected function buildComposerName(string $organizationName, string $moduleName): string + { + $filter = $this->getFilter(); + $composerName = sprintf('%s/%s', $filter->filter($organizationName), $filter->filter($moduleName)); + + return $composerName; + } + + /** + * @return \Laminas\Filter\FilterChain + */ + protected function getFilter(): FilterChain + { + if (!$this->filter) { + $filter = new FilterChain(); + $filter->attach(new CamelCaseToDash()) + ->attach(new StringToLower()); + + $this->filter = $filter; + } + + return $this->filter; + } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/BehaviorDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/BehaviorDependencyFinder.php index e938221e..56ab76f8 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/BehaviorDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/BehaviorDependencyFinder.php @@ -7,32 +7,35 @@ namespace Spryker\Zed\Development\Business\Dependency\DependencyFinder; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\DashToCamelCase; use Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\Context\DependencyFinderContextInterface; -use Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\DashToCamelCase; +use Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface; class BehaviorDependencyFinder implements DependencyFinderInterface { + /** + * @var string + */ public const TYPE_PERSISTENCE = 'persistence'; /** - * @var \Zend\Filter\FilterChain|null + * @var \Laminas\Filter\FilterChain|null */ protected $filter; /** - * @var \Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface + * @var \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface */ - protected $moduleFinder; + protected $moduleFinderFacade; /** - * @param \Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface $moduleFinder + * @param \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade */ - public function __construct(ModuleFinderInterface $moduleFinder) + public function __construct(DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade) { - $this->moduleFinder = $moduleFinder; + $this->moduleFinderFacade = $moduleFinderFacade; } /** @@ -94,7 +97,7 @@ protected function getModuleNameFromMatch(array $match): string } /** - * @return \Zend\Filter\FilterChain + * @return \Laminas\Filter\FilterChain */ protected function getFilter(): FilterChain { @@ -113,7 +116,7 @@ protected function getFilter(): FilterChain */ protected function isModule(string $moduleName): bool { - $moduleTransferCollection = $this->moduleFinder->getModules(); + $moduleTransferCollection = $this->moduleFinderFacade->getModules(); return isset($moduleTransferCollection['Spryker.' . $moduleName]); } @@ -128,7 +131,7 @@ protected function addModuleDependency(DependencyContainerInterface $dependencyC { $dependencyContainer->addDependency( $moduleName, - $this->getType() + $this->getType(), ); return $dependencyContainer; diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/CodeceptionDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/CodeceptionDependencyFinder.php index 321e1150..b32bbbfe 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/CodeceptionDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/CodeceptionDependencyFinder.php @@ -12,6 +12,9 @@ class CodeceptionDependencyFinder extends AbstractFileDependencyFinder { + /** + * @var string + */ public const TYPE_CODECEPTION = 'codeception'; /** @@ -50,7 +53,7 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe { if (preg_match_all('/SprykerTest\\\\(.*?)\\\\(.*?)\\\\/', $context->getFileInfo()->getContents(), $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { - $dependencyContainer->addDependency($match[2], $this->getType(), false, true); + $dependencyContainer->addDependency(sprintf('spryker/%s', $this->getFilter()->filter($match[2])), $this->getType(), false, true); } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ComposerScriptDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ComposerDependencyFinder.php similarity index 66% rename from src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ComposerScriptDependencyFinder.php rename to src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ComposerDependencyFinder.php index 0ba28f07..773e6932 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ComposerScriptDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ComposerDependencyFinder.php @@ -10,16 +10,19 @@ use Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\Context\DependencyFinderContextInterface; -class ComposerScriptDependencyFinder extends AbstractFileDependencyFinder +class ComposerDependencyFinder extends AbstractFileDependencyFinder { - public const TYPE_COMPOSER_SCRIPT = 'composer-script'; + /** + * @var string + */ + public const TYPE_COMPOSER = 'composer'; /** * @return string */ public function getType(): string { - return static::TYPE_COMPOSER_SCRIPT; + return static::TYPE_COMPOSER; } /** @@ -49,8 +52,21 @@ public function accept(DependencyFinderContextInterface $context): bool public function findDependencies(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface { $fileContent = $context->getFileInfo()->getContents(); - if (strpos($fileContent, 'code-sniffer/Spryker/ruleset.xml') !== false) { - $dependencyContainer->addDependency('CodeSniffer', $this->getType(), false, true); + + if (strpos($fileContent, 'cs-check') !== false) { + $dependencyContainer->addDependency('spryker/code-sniffer', $this->getType(), false, true); + } + + if (preg_match('/code-sniffer\/(Spryker|SprykerStrict)/', $fileContent)) { + $dependencyContainer->addDependency('spryker/code-sniffer', $this->getType(), false, true); + } + + if (strpos($fileContent, 'codecept run') !== false) { + $dependencyContainer->addDependency('spryker/testify', $this->getType(), false, true); + } + + if (strpos($fileContent, 'phpstan analyse') !== false) { + $dependencyContainer->addDependency('phpstan/phpstan', $this->getType(), false, true); } return $dependencyContainer; diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderComposite.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderComposite.php index e941a147..79f7362c 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderComposite.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderComposite.php @@ -13,12 +13,12 @@ class DependencyFinderComposite implements DependencyFinderInterface { /** - * @var \Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface[] + * @var array<\Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface> */ protected $dependencyFinder; /** - * @param \Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface[] $dependencyFinder + * @param array<\Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface> $dependencyFinder */ public function __construct(array $dependencyFinder) { diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderInterface.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderInterface.php index 16c0f840..f56f7beb 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/DependencyFinderInterface.php @@ -30,5 +30,8 @@ public function accept(DependencyFinderContextInterface $context): bool; * * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface */ - public function findDependencies(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface; + public function findDependencies( + DependencyFinderContextInterface $context, + DependencyContainerInterface $dependencyContainer + ): DependencyContainerInterface; } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php index 2847457a..e68ec3a9 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExtensionDependencyFinder.php @@ -9,10 +9,13 @@ use Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\Context\DependencyFinderContextInterface; -use Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface; +use Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface; class ExtensionDependencyFinder extends AbstractFileDependencyFinder { + /** + * @var string + */ public const TYPE_EXTENSION = 'extension'; /** @@ -21,16 +24,21 @@ class ExtensionDependencyFinder extends AbstractFileDependencyFinder protected $executedModules = []; /** - * @var \Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface + * @var \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface + */ + protected $moduleFinderFacade; + + /** + * @var \Laminas\Filter\FilterChain|null */ - protected $moduleFinder; + protected $filter; /** - * @param \Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface $moduleFinder + * @param \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade */ - public function __construct(ModuleFinderInterface $moduleFinder) + public function __construct(DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade) { - $this->moduleFinder = $moduleFinder; + $this->moduleFinderFacade = $moduleFinderFacade; } /** @@ -67,7 +75,8 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe $moduleExtensionKey = sprintf('%s.%sExtension', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName()); if ($this->hasExtensionModule($moduleExtensionKey)) { - $dependencyContainer->addDependency(sprintf('%sExtension', $moduleTransfer->getName()), $this->getType()); + $composerName = $this->buildComposerName($moduleTransfer->getOrganization()->getName(), sprintf('%sExtension', $moduleTransfer->getName())); + $dependencyContainer->addDependency($composerName, $this->getType()); } $this->executedModules[spl_object_hash($moduleTransfer)] = true; @@ -82,7 +91,7 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe */ protected function hasExtensionModule(string $moduleExtensionKey): bool { - $moduleTransferCollection = $this->moduleFinder->getModules(); + $moduleTransferCollection = $this->moduleFinderFacade->getModules(); return isset($moduleTransferCollection[$moduleExtensionKey]); } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExternalDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExternalDependencyFinder.php index 80cbed88..9c1517a6 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExternalDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ExternalDependencyFinder.php @@ -8,14 +8,18 @@ namespace Spryker\Zed\Development\Business\Dependency\DependencyFinder; use Exception; +use Laminas\Filter\Word\SeparatorToCamelCase; +use Spryker\Zed\Development\Business\Dependency\ComposerParser\ExternalDependencyParserInterface; use Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\Context\DependencyFinderContextInterface; use Spryker\Zed\Development\Business\Dependency\ModuleParser\UseStatementParserInterface; use Spryker\Zed\Development\DevelopmentConfig; -use Zend\Filter\Word\SeparatorToCamelCase; class ExternalDependencyFinder extends AbstractFileDependencyFinder { + /** + * @var string + */ public const TYPE_EXTERNAL = 'external'; /** @@ -23,18 +27,33 @@ class ExternalDependencyFinder extends AbstractFileDependencyFinder */ protected $useStatementParser; + /** + * @var \Spryker\Zed\Development\Business\Dependency\ComposerParser\ExternalDependencyParserInterface + */ + protected $externalDependencyParser; + /** * @var \Spryker\Zed\Development\DevelopmentConfig */ protected $config; + /** + * @var array + */ + protected $foundPackagesByUseStatement = []; + /** * @param \Spryker\Zed\Development\Business\Dependency\ModuleParser\UseStatementParserInterface $useStatementParser + * @param \Spryker\Zed\Development\Business\Dependency\ComposerParser\ExternalDependencyParserInterface $externalDependencyParser * @param \Spryker\Zed\Development\DevelopmentConfig $config */ - public function __construct(UseStatementParserInterface $useStatementParser, DevelopmentConfig $config) - { + public function __construct( + UseStatementParserInterface $useStatementParser, + ExternalDependencyParserInterface $externalDependencyParser, + DevelopmentConfig $config + ) { $this->useStatementParser = $useStatementParser; + $this->externalDependencyParser = $externalDependencyParser; $this->config = $config; } @@ -80,7 +99,7 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe $dependentModule, $this->getType(), $this->isPluginFile($filePath), - $this->isTestFile($filePath) + $this->isTestFile($filePath), ); } } @@ -108,7 +127,7 @@ protected function getDependencyModules(DependencyFinderContextInterface $contex } /** - * @param array $useStatements + * @param array $useStatements * * @return array */ @@ -116,8 +135,18 @@ protected function getModuleNamesFromUseStatements(array $useStatements): array { $dependentModules = []; foreach ($useStatements as $useStatement) { - if ($this->isExternalDependency($useStatement)) { + if ($this->isMappedExternalDependency($useStatement)) { $dependentModules[] = $this->getDependentModule($useStatement); + + continue; + } + + if ($this->isInternalNamespace($useStatement)) { + continue; + } + + if ($this->isUnMappedExternalDependency($useStatement)) { + $dependentModules[] = $this->externalDependencyParser->findPackageNameByNamespace($useStatement); } } @@ -129,7 +158,27 @@ protected function getModuleNamesFromUseStatements(array $useStatements): array * * @return bool */ - protected function isExternalDependency(string $useStatement): bool + protected function isInternalNamespace(string $useStatement): bool + { + if (strpos($useStatement, '\\') === false) { + return true; + } + + foreach ($this->config->getInternalNamespaces() as $namespace) { + if (strpos($useStatement, $namespace) === 0) { + return true; + } + } + + return false; + } + + /** + * @param string $useStatement + * + * @return bool + */ + protected function isMappedExternalDependency(string $useStatement): bool { foreach ($this->config->getExternalToInternalNamespaceMap() as $namespace => $package) { if (strpos($useStatement, $namespace) === 0) { @@ -140,6 +189,22 @@ protected function isExternalDependency(string $useStatement): bool return false; } + /** + * @param string $useStatement + * + * @return bool + */ + protected function isUnMappedExternalDependency(string $useStatement): bool + { + $packageName = $this->externalDependencyParser->findPackageNameByNamespace($useStatement); + + if ($packageName !== null) { + return true; + } + + return false; + } + /** * @param string $useStatement * @@ -151,11 +216,15 @@ protected function getDependentModule(string $useStatement): string { foreach ($this->config->getExternalToInternalNamespaceMap() as $namespace => $package) { if (strpos($useStatement, $namespace) === 0) { - return $this->getDependentModuleNameFromPackage($package); + return $package; } } - throw new Exception('Could not map external to internal dependency!'); + throw new Exception(sprintf( + 'Could not map "%s" to a internal dependency! Please update "%s" and add a new mapping.', + $useStatement, + '\Spryker\Zed\Development\DevelopmentConfig::getExternalToInternalNamespaceMap()', + )); } /** @@ -167,7 +236,9 @@ protected function getDependentModuleNameFromPackage(string $package): string { $dependentModule = substr($package, 8); $filter = new SeparatorToCamelCase('-'); + /** @var string $camelCasedDependentModule */ + $camelCasedDependentModule = $filter->filter($dependentModule); - return ucfirst($filter->filter($dependentModule)); + return ucfirst($camelCasedDependentModule); } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/InternalDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/InternalDependencyFinder.php index 10deef8d..755b8666 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/InternalDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/InternalDependencyFinder.php @@ -14,6 +14,9 @@ class InternalDependencyFinder extends AbstractFileDependencyFinder { + /** + * @var string + */ public const TYPE_INTERNAL = 'internal'; /** @@ -72,13 +75,13 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe { $dependencyModules = $this->getDependencyModules($context); - foreach ($dependencyModules as $filePath => $modules) { - foreach ($modules as $dependentModule) { + foreach ($dependencyModules as $filePath => $composerNames) { + foreach ($composerNames as $composerName) { $dependencyContainer->addDependency( - $dependentModule, + $composerName, $this->getType(), - $this->isOptional($filePath, $dependentModule), - $this->isTestFile($filePath) + $this->isOptional($filePath, $composerName), + $this->isTestFile($filePath), ); } } @@ -107,45 +110,54 @@ protected function getDependencyModules(DependencyFinderContextInterface $contex $dependencyModules = []; $useStatements = $this->useStatementParser->getUseStatements($context->getFileInfo()); - $modules = $this->getModuleNamesFromUseStatements($useStatements, $context->getModule()->getName()); + $composerNames = $this->getNamesFromUseStatements($useStatements, $context->getModule()->getName()); - if (count($modules) > 0) { - $dependencyModules[$context->getFileInfo()->getRealPath()] = array_unique($modules); + if (count($composerNames) > 0) { + $dependencyModules[$context->getFileInfo()->getRealPath()] = array_unique($composerNames); } return $dependencyModules; } /** - * @param array $useStatements + * @param array $useStatements * @param string $module * * @return array */ - protected function getModuleNamesFromUseStatements(array $useStatements, string $module): array + protected function getNamesFromUseStatements(array $useStatements, string $module): array { - $dependentModules = []; + $dependentComposerNames = []; foreach ($useStatements as $useStatement) { $useStatementFragments = explode('\\', $useStatement); if ($this->isIgnorableUseStatement($useStatementFragments)) { continue; } + $foreignModule = $useStatementFragments[2]; - if ($foreignModule !== $module) { - $dependentModules[] = $foreignModule; + if ($foreignModule === $module) { + continue; } + + if ($useStatementFragments[0] === 'Orm') { + $dependentComposerNames[] = $useStatementFragments[2]; + + continue; + } + + $dependentComposerNames[] = $this->buildComposerName($useStatementFragments[0], $useStatementFragments[2]); } - return $dependentModules; + return $dependentComposerNames; } /** - * @param array $useStatementFragments + * @param array $useStatementFragments * * @return bool */ protected function isIgnorableUseStatement(array $useStatementFragments): bool { - return (!in_array($useStatementFragments[0], $this->config->getInternalNamespaces()) || !in_array($useStatementFragments[1], $this->config->getApplications())); + return (!in_array($useStatementFragments[0], $this->config->getInternalNamespaces(), true) || !in_array($useStatementFragments[1], $this->config->getApplications(), true)); } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/LocatorDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/LocatorDependencyFinder.php index 860b8681..a92fc205 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/LocatorDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/LocatorDependencyFinder.php @@ -13,6 +13,9 @@ class LocatorDependencyFinder implements DependencyFinderInterface { + /** + * @var string + */ public const TYPE_LOCATOR = 'locator'; /** @@ -54,7 +57,7 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe foreach ($dependencyModules as $module) { $dependencyContainer->addDependency( $module, - $this->getType() + $this->getType(), ); } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/MappedDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/MappedDependencyFinder.php new file mode 100644 index 00000000..527efe57 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/MappedDependencyFinder.php @@ -0,0 +1,86 @@ +config = $config; + } + + /** + * @return string + */ + public function getType(): string + { + return static::TYPE_MAPPED; + } + + /** + * @param \Spryker\Zed\Development\Business\Dependency\DependencyFinder\Context\DependencyFinderContextInterface $context + * + * @return bool + */ + public function accept(DependencyFinderContextInterface $context): bool + { + if ($context->getDependencyType() !== null && $context->getDependencyType() !== $this->getType()) { + return false; + } + + if ($context->getFileInfo()->getFilename() !== 'composer.json') { + return false; + } + + return true; + } + + /** + * @param \Spryker\Zed\Development\Business\Dependency\DependencyFinder\Context\DependencyFinderContextInterface $context + * @param \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface $dependencyContainer + * + * @throws \RuntimeException + * + * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface + */ + public function findDependencies(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface + { + $fileContent = $context->getFileInfo()->getContents(); + $composerJsonAsArray = json_decode($fileContent, true); + $composerName = $composerJsonAsArray['name'] ?? null; + if (!$composerName) { + throw new RuntimeException('Composer name missing: ' . $context->getFileInfo()->getPath()); + } + + foreach ($this->config->getExternalToInternalMap() as $externalPackageName => $internalModulePackageName) { + if ($internalModulePackageName === $composerName) { + $dependencyContainer->addDependency($externalPackageName, $this->getType()); + } + } + + return $dependencyContainer; + } +} diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ModuleAnnotationDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ModuleAnnotationDependencyFinder.php index 62ea8fa7..13b72390 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ModuleAnnotationDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/ModuleAnnotationDependencyFinder.php @@ -12,10 +12,13 @@ class ModuleAnnotationDependencyFinder implements DependencyFinderInterface { + /** + * @var string + */ public const TYPE = 'module-annotation'; /** - * @var string[] + * @var array */ protected $acceptedFileNames = [ 'Repository.php', @@ -63,12 +66,13 @@ public function accept(DependencyFinderContextInterface $context): bool */ protected function isAcceptedFile(DependencyFinderContextInterface $context): bool { - $isAccepted = false; foreach ($this->acceptedFileNames as $fileName) { - $isAccepted = substr($context->getFileInfo()->getFilename(), - strlen($fileName)) === $fileName; + if (substr($context->getFileInfo()->getFilename(), - strlen($fileName)) === $fileName) { + return true; + } } - return $isAccepted; + return false; } /** diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/PersistenceDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/PersistenceDependencyFinder.php index a50c9703..2a95b1d5 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/PersistenceDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/PersistenceDependencyFinder.php @@ -13,6 +13,9 @@ class PersistenceDependencyFinder implements DependencyFinderInterface { + /** + * @var string + */ public const TYPE_PERSISTENCE = 'persistence'; /** @@ -68,7 +71,7 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe $dependentModule = $this->propelSchemaParser->getModuleNameByForeignReference($foreignIdColumnName, $context->getModule()->getName()); $dependencyContainer->addDependency( $dependentModule, - $this->getType() + $this->getType(), ); } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/SprykerSdkDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/SprykerSdkDependencyFinder.php index 6d94fa25..4401a1fe 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/SprykerSdkDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/SprykerSdkDependencyFinder.php @@ -14,6 +14,9 @@ class SprykerSdkDependencyFinder extends AbstractFileDependencyFinder { + /** + * @var string + */ public const TYPE_INTERNAL = 'internal'; /** @@ -78,7 +81,7 @@ public function findDependencies(DependencyFinderContextInterface $context, Depe $dependentModule, $this->getType(), $this->isOptional($filePath, $dependentModule), - $this->isTestFile($filePath) + $this->isTestFile($filePath), ); } } @@ -117,7 +120,7 @@ protected function getDependencyModules(DependencyFinderContextInterface $contex } /** - * @param array $useStatements + * @param array $useStatements * @param string $module * * @return array @@ -132,7 +135,7 @@ protected function getModuleNamesFromUseStatements(array $useStatements, string } $foreignModule = $useStatementFragments[1]; if ($foreignModule !== $module) { - $dependentModules[] = $foreignModule; + $dependentModules[] = $this->buildComposerName($useStatementFragments[0], $useStatementFragments[1]); } } @@ -140,14 +143,14 @@ protected function getModuleNamesFromUseStatements(array $useStatements, string } /** - * @param array $useStatementFragments + * @param array $useStatementFragments * * @return bool */ protected function isIgnorableUseStatement(array $useStatementFragments): bool { return $useStatementFragments[0] !== 'SprykerSdk' - || !in_array($useStatementFragments[0], $this->config->getInternalNamespaces()) - || in_array($useStatementFragments[1], $this->config->getApplications()); + || !in_array($useStatementFragments[0], $this->config->getInternalNamespaces(), true) + || in_array($useStatementFragments[1], $this->config->getApplications(), true); } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TravisDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TravisDependencyFinder.php index eb45933f..272bf790 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TravisDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TravisDependencyFinder.php @@ -12,6 +12,9 @@ class TravisDependencyFinder extends AbstractFileDependencyFinder { + /** + * @var string + */ public const TYPE_TRAVIS = 'travis'; /** @@ -49,11 +52,16 @@ public function accept(DependencyFinderContextInterface $context): bool public function findDependencies(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface { $fileContent = $context->getFileInfo()->getContents(); - if (strpos($fileContent, 'code-sniffer/Spryker/ruleset.xml') !== false) { + + if (preg_match('/composer cs-check/', $fileContent)) { + $dependencyContainer->addDependency('CodeSniffer', $this->getType(), false, true); + } + + if (preg_match('/code-sniffer\/(Spryker|SprykerStrict)/', $fileContent)) { $dependencyContainer->addDependency('CodeSniffer', $this->getType(), false, true); } - if (strpos($fileContent, 'vendor/bin/codecept') !== false) { + if (strpos($fileContent, 'codecept run') !== false) { $dependencyContainer->addDependency('Testify', $this->getType(), false, true); } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder.php index 5f2b188b..33410632 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder.php @@ -12,15 +12,18 @@ class TwigDependencyFinder implements DependencyFinderInterface { + /** + * @var string + */ public const TYPE_TWIG = 'twig'; /** - * @var \Spryker\Zed\Development\Business\Dependency\DependencyFinder\TwigDependencyFinder\TwigDependencyFinderInterface[] + * @var array<\Spryker\Zed\Development\Business\Dependency\DependencyFinder\TwigDependencyFinder\TwigDependencyFinderInterface> */ protected $twigDependencyFinder; /** - * @param array $twigDependencyFinder + * @param array<\Spryker\Zed\Development\Business\Dependency\DependencyFinder\TwigDependencyFinder\TwigDependencyFinderInterface> $twigDependencyFinder */ public function __construct(array $twigDependencyFinder) { diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/AtomFunctionDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/AtomFunctionDependencyFinder.php index 68caa827..65cd0db3 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/AtomFunctionDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/AtomFunctionDependencyFinder.php @@ -13,6 +13,9 @@ class AtomFunctionDependencyFinder implements TwigDependencyFinderInterface { + /** + * @var string + */ protected const TEMPLATE_FUNCTION_PATTERN = '/atom\(\'(.*?),\s\'(.*?)\'/'; /** @@ -21,8 +24,10 @@ class AtomFunctionDependencyFinder implements TwigDependencyFinderInterface * * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface */ - public function checkDependencyInFile(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface - { + public function checkDependencyInFile( + DependencyFinderContextInterface $context, + DependencyContainerInterface $dependencyContainer + ): DependencyContainerInterface { $twigFileContent = $context->getFileInfo()->getContents(); $pregMatchResult = preg_match_all(static::TEMPLATE_FUNCTION_PATTERN, $twigFileContent, $matches, PREG_SET_ORDER); diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/MoleculeFunctionDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/MoleculeFunctionDependencyFinder.php index 43cdbd0c..4ebaeca7 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/MoleculeFunctionDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/MoleculeFunctionDependencyFinder.php @@ -13,6 +13,9 @@ class MoleculeFunctionDependencyFinder implements TwigDependencyFinderInterface { + /** + * @var string + */ protected const TEMPLATE_FUNCTION_PATTERN = '/molecule\(\'(.*?),\s\'(.*?)\'/'; /** @@ -21,8 +24,10 @@ class MoleculeFunctionDependencyFinder implements TwigDependencyFinderInterface * * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface */ - public function checkDependencyInFile(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface - { + public function checkDependencyInFile( + DependencyFinderContextInterface $context, + DependencyContainerInterface $dependencyContainer + ): DependencyContainerInterface { $twigFileContent = $context->getFileInfo()->getContents(); $pregMatchResult = preg_match_all(static::TEMPLATE_FUNCTION_PATTERN, $twigFileContent, $matches, PREG_SET_ORDER); diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/OrganismFunctionDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/OrganismFunctionDependencyFinder.php index 41b4fbd0..98f82c67 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/OrganismFunctionDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/OrganismFunctionDependencyFinder.php @@ -13,6 +13,9 @@ class OrganismFunctionDependencyFinder implements TwigDependencyFinderInterface { + /** + * @var string + */ protected const TEMPLATE_FUNCTION_PATTERN = '/organism\(\'(.*?),\s\'(.*?)\'/'; /** @@ -21,8 +24,10 @@ class OrganismFunctionDependencyFinder implements TwigDependencyFinderInterface * * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface */ - public function checkDependencyInFile(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface - { + public function checkDependencyInFile( + DependencyFinderContextInterface $context, + DependencyContainerInterface $dependencyContainer + ): DependencyContainerInterface { $twigFileContent = $context->getFileInfo()->getContents(); $pregMatchResult = preg_match_all(static::TEMPLATE_FUNCTION_PATTERN, $twigFileContent, $matches, PREG_SET_ORDER); diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TemplateFunctionDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TemplateFunctionDependencyFinder.php index f15a750e..61348ac5 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TemplateFunctionDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TemplateFunctionDependencyFinder.php @@ -13,6 +13,9 @@ class TemplateFunctionDependencyFinder implements TwigDependencyFinderInterface { + /** + * @var string + */ protected const TEMPLATE_FUNCTION_PATTERN = '/template\(\'(.*?),\s\'(.*?)\'/'; /** @@ -21,8 +24,10 @@ class TemplateFunctionDependencyFinder implements TwigDependencyFinderInterface * * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface */ - public function checkDependencyInFile(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface - { + public function checkDependencyInFile( + DependencyFinderContextInterface $context, + DependencyContainerInterface $dependencyContainer + ): DependencyContainerInterface { $twigFileContent = $context->getFileInfo()->getContents(); $pregMatchResult = preg_match_all(static::TEMPLATE_FUNCTION_PATTERN, $twigFileContent, $matches, PREG_SET_ORDER); diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TwigDependencyFinderInterface.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TwigDependencyFinderInterface.php index 1af1aede..d3e6ac7f 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TwigDependencyFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/TwigDependencyFinderInterface.php @@ -23,5 +23,8 @@ public function getType(): string; * * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface */ - public function checkDependencyInFile(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface; + public function checkDependencyInFile( + DependencyFinderContextInterface $context, + DependencyContainerInterface $dependencyContainer + ): DependencyContainerInterface; } diff --git a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/ViewFunctionDependencyFinder.php b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/ViewFunctionDependencyFinder.php index 8a65f91c..3b8960c3 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/ViewFunctionDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/DependencyFinder/TwigDependencyFinder/ViewFunctionDependencyFinder.php @@ -13,6 +13,9 @@ class ViewFunctionDependencyFinder implements TwigDependencyFinderInterface { + /** + * @var string + */ protected const TEMPLATE_FUNCTION_PATTERN = '/view\(\'(.*?),\s\'(.*?)\'/'; /** @@ -21,8 +24,10 @@ class ViewFunctionDependencyFinder implements TwigDependencyFinderInterface * * @return \Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface */ - public function checkDependencyInFile(DependencyFinderContextInterface $context, DependencyContainerInterface $dependencyContainer): DependencyContainerInterface - { + public function checkDependencyInFile( + DependencyFinderContextInterface $context, + DependencyContainerInterface $dependencyContainer + ): DependencyContainerInterface { $twigFileContent = $context->getFileInfo()->getContents(); $pregMatchResult = preg_match_all(static::TEMPLATE_FUNCTION_PATTERN, $twigFileContent, $matches, PREG_SET_ORDER); diff --git a/src/Spryker/Zed/Development/Business/Dependency/Manager.php b/src/Spryker/Zed/Development/Business/Dependency/Manager.php index afa51a09..abe8b0e3 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/Manager.php +++ b/src/Spryker/Zed/Development/Business/Dependency/Manager.php @@ -8,12 +8,15 @@ namespace Spryker\Zed\Development\Business\Dependency; use Generated\Shared\Transfer\DependencyCollectionTransfer; +use Generated\Shared\Transfer\DependencyModuleTransfer; +use Generated\Shared\Transfer\DependencyModuleViewTransfer; use Generated\Shared\Transfer\ModuleTransfer; use Generated\Shared\Transfer\OrganizationTransfer; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\DashToCamelCase; +use Spryker\Zed\Development\Business\Dependency\Mapper\DependencyModuleMapperInterface; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Finder\Finder; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\DashToCamelCase; class Manager implements ManagerInterface { @@ -27,43 +30,58 @@ class Manager implements ManagerInterface */ protected $config; + /** + * @var \Spryker\Zed\Development\Business\Dependency\Mapper\DependencyModuleMapperInterface + */ + protected $dependencyModuleMapper; + /** * @param \Spryker\Zed\Development\Business\Dependency\ModuleDependencyParserInterface $moduleParser * @param \Spryker\Zed\Development\DevelopmentConfig $config + * @param \Spryker\Zed\Development\Business\Dependency\Mapper\DependencyModuleMapperInterface $dependencyModuleMapper */ - public function __construct(ModuleDependencyParserInterface $moduleParser, DevelopmentConfig $config) - { + public function __construct( + ModuleDependencyParserInterface $moduleParser, + DevelopmentConfig $config, + DependencyModuleMapperInterface $dependencyModuleMapper + ) { $this->moduleParser = $moduleParser; $this->config = $config; + $this->dependencyModuleMapper = $dependencyModuleMapper; } /** * @param string $moduleName * - * @return array + * @return array<\Generated\Shared\Transfer\DependencyModuleViewTransfer> */ - public function parseIncomingDependencies($moduleName) + public function parseIncomingDependencies(string $moduleName): array { - $allForeignModules = $this->collectAllForeignModules($moduleName); + $allForeignModuleNames = $this->collectAllForeignModules($moduleName); $incomingDependencies = []; - foreach ($allForeignModules as $foreignModule) { - $organizationTransfer = new OrganizationTransfer(); - $organizationTransfer->setName('Spryker'); - $moduleTransfer = new ModuleTransfer(); - $moduleTransfer - ->setName($moduleName) + + foreach ($allForeignModuleNames as $foreignModuleName) { + $organizationTransfer = (new OrganizationTransfer())->setName('Spryker'); + $moduleTransfer = (new ModuleTransfer()) + ->setName($foreignModuleName) ->setOrganization($organizationTransfer); $moduleDependencyCollectionTransfer = $this->moduleParser->parseOutgoingDependencies($moduleTransfer); - $dependencyModule = $this->findDependencyTo($moduleName, $moduleDependencyCollectionTransfer); - if ($dependencyModule) { - if (array_key_exists($foreignModule, $incomingDependencies) === false) { - $incomingDependencies[$foreignModule] = 0; - } - $incomingDependencies[$foreignModule] += count($dependencyModule->getDependencies()); + $dependencyModuleTransfer = $this->findDependencyTo($moduleName, $moduleDependencyCollectionTransfer); + + if ($dependencyModuleTransfer === null) { + continue; } + + $dependencyModuleViewTransfer = $this->dependencyModuleMapper->mapDependencyModuleTransferToDependencyModuleViewTransfer( + $dependencyModuleTransfer, + new DependencyModuleViewTransfer(), + ); + $dependencyModuleViewTransfer->setName($foreignModuleName); + + $incomingDependencies[] = $dependencyModuleViewTransfer; } return $incomingDependencies; @@ -73,21 +91,21 @@ public function parseIncomingDependencies($moduleName) * @param string $moduleName * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $moduleDependencyCollectionTransfer * - * @return bool|\Generated\Shared\Transfer\DependencyBundleTransfer|mixed + * @return \Generated\Shared\Transfer\DependencyModuleTransfer|null */ - protected function findDependencyTo($moduleName, DependencyCollectionTransfer $moduleDependencyCollectionTransfer) - { + protected function findDependencyTo( + string $moduleName, + DependencyCollectionTransfer $moduleDependencyCollectionTransfer + ): ?DependencyModuleTransfer { foreach ($moduleDependencyCollectionTransfer->getDependencyModules() as $dependencyModule) { - if ($dependencyModule->getModule() === $moduleName) { - foreach ($dependencyModule->getDependencies() as $dependencyTransfer) { - if (!$dependencyTransfer->getIsInTest() && !$dependencyTransfer->getIsOptional()) { - return $dependencyModule; - } - } + if ($dependencyModule->getModule() !== $moduleName) { + continue; } + + return $dependencyModule; } - return false; + return null; } /** @@ -131,7 +149,7 @@ public function collectAllModules() } /** - * @return \Symfony\Component\Finder\Finder|\Symfony\Component\Finder\SplFileInfo[] + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ protected function collectCoreModules() { diff --git a/src/Spryker/Zed/Development/Business/Dependency/ManagerInterface.php b/src/Spryker/Zed/Development/Business/Dependency/ManagerInterface.php index 3288d38c..412a281d 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/ManagerInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/ManagerInterface.php @@ -12,9 +12,9 @@ interface ManagerInterface /** * @param string $moduleName * - * @return array + * @return array<\Generated\Shared\Transfer\DependencyModuleViewTransfer> */ - public function parseIncomingDependencies($moduleName); + public function parseIncomingDependencies(string $moduleName): array; /** * @return array diff --git a/src/Spryker/Zed/Development/Business/Dependency/Mapper/DependencyModuleMapper.php b/src/Spryker/Zed/Development/Business/Dependency/Mapper/DependencyModuleMapper.php new file mode 100644 index 00000000..6ae0fde5 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Dependency/Mapper/DependencyModuleMapper.php @@ -0,0 +1,59 @@ +collectDependencyCount($dependencyModuleTransfer); + + return $dependencyModuleViewTransfer + ->setTotalDependencyCount($totalCount) + ->setTestDependencyCount($testCount) + ->setOptionalDependencyCount($optionalCount); + } + + /** + * @param \Generated\Shared\Transfer\DependencyModuleTransfer $dependencyModuleTransfer + * + * @return array + */ + protected function collectDependencyCount( + DependencyModuleTransfer $dependencyModuleTransfer + ): array { + $totalCount = 0; + $optionalCount = 0; + $testCount = 0; + + foreach ($dependencyModuleTransfer->getDependencies() as $dependencyTransfer) { + if ($dependencyTransfer->getIsOptional()) { + $optionalCount++; + } + + if ($dependencyTransfer->getIsInTest()) { + $testCount++; + } + + $totalCount++; + } + + return [$totalCount, $optionalCount, $testCount]; + } +} diff --git a/src/Spryker/Zed/Development/Business/Dependency/Mapper/DependencyModuleMapperInterface.php b/src/Spryker/Zed/Development/Business/Dependency/Mapper/DependencyModuleMapperInterface.php new file mode 100644 index 00000000..9f9a5cb7 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Dependency/Mapper/DependencyModuleMapperInterface.php @@ -0,0 +1,25 @@ +moduleFileFinder = $moduleFileFinder; $this->dependencyContainer = $dependencyContainer; $this->dependencyFinder = $dependencyFinder; @@ -51,6 +57,10 @@ public function __construct(ModuleFileFinderInterface $moduleFileFinder, Depende */ public function parseOutgoingDependencies(ModuleTransfer $moduleTransfer, ?string $dependencyType = null): DependencyCollectionTransfer { + if ($moduleTransfer->getNameDashed() == null) { + $moduleTransfer->setNameDashed($this->dasherize($moduleTransfer->getName())); + } + $dependencyContainer = $this->dependencyContainer->initialize($moduleTransfer); if (!$this->moduleFileFinder->hasFiles($moduleTransfer)) { @@ -66,4 +76,19 @@ public function parseOutgoingDependencies(ModuleTransfer $moduleTransfer, ?strin return $dependencyContainer->getDependencyCollection(); } + + /** + * @param string $value + * + * @return string + */ + protected function dasherize(string $value): string + { + $filterChain = new FilterChain(); + $filterChain + ->attach(new CamelCaseToDash()) + ->attach(new StringToLower()); + + return $filterChain->filter($value); + } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParser.php b/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParser.php index 97196a27..e94a1e40 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParser.php +++ b/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParser.php @@ -14,7 +14,7 @@ class UseStatementParser implements UseStatementParserInterface /** * @param \Symfony\Component\Finder\SplFileInfo $fileInfo * - * @return array + * @return array */ public function getUseStatements(SplFileInfo $fileInfo): array { @@ -28,10 +28,10 @@ public function getUseStatements(SplFileInfo $fileInfo): array */ protected function getUseStatementsInFile(SplFileInfo $fileInfo): array { - preg_match_all('#use (.*);#', $fileInfo->getContents(), $matches); + preg_match_all('/^(use\s([^\s|;]+))/m', $fileInfo->getContents(), $matches); $useStatements = []; - foreach ($matches[1] as $useStatement) { + foreach ($matches[2] as $useStatement) { $useStatements[] = $useStatement; } diff --git a/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParserInterface.php b/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParserInterface.php index a50f676f..e53aa9f7 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParserInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/ModuleParser/UseStatementParserInterface.php @@ -14,7 +14,7 @@ interface UseStatementParserInterface /** * @param \Symfony\Component\Finder\SplFileInfo $fileInfo * - * @return array + * @return array */ public function getUseStatements(SplFileInfo $fileInfo): array; } diff --git a/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParser.php b/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParser.php index 7108a0ee..c6842684 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParser.php +++ b/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParser.php @@ -7,6 +7,7 @@ namespace Spryker\Zed\Development\Business\Dependency\SchemaParser; +use SimpleXMLElement; use Spryker\Zed\Development\Business\Exception\Dependency\PropelSchemaParserException; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Finder\Finder; @@ -14,6 +15,9 @@ class PropelSchemaParser implements PropelSchemaParserInterface { + /** + * @var string + */ protected const PROPEL_SCHEMA_PATH_PATTERN = '*/src/%s/Zed/*/Persistence/Propel/Schema'; /** @@ -22,12 +26,12 @@ class PropelSchemaParser implements PropelSchemaParserInterface protected $config; /** - * @var string[] + * @var array */ protected static $idFieldToModuleNameMap; /** - * @var string[] + * @var array */ protected static $uniqueFieldToModuleNameMap; @@ -48,8 +52,14 @@ public function getForeignColumnNames(SplFileInfo $fileInfo): array { $foreignReferenceColumnNames = []; + /** @var \SimpleXMLElement $simpleXmlElement */ $simpleXmlElement = simplexml_load_file($fileInfo->getPathname()); - $foreignReferences = $simpleXmlElement->xpath('//table/foreign-key/reference'); + $hasNamespace = $this->hasNamespaceInSchema($simpleXmlElement); + if ($hasNamespace) { + $simpleXmlElement->registerXPathNamespace('s', 'spryker:schema-01'); + } + /** @var iterable $foreignReferences */ + $foreignReferences = $simpleXmlElement->xpath($hasNamespace ? '//s:table/s:foreign-key/s:reference' : '//table/foreign-key/reference'); foreach ($foreignReferences as $foreignReference) { $parentNode = $foreignReference->xpath('parent::*')[0]; $foreignTableName = (string)$parentNode['foreignTable']; @@ -98,7 +108,7 @@ protected function getIdFieldToModuleNameMap(): array } /** - * @return array + * @return array */ protected function getUniqueFieldToModuleNameMap(): array { @@ -110,7 +120,7 @@ protected function getUniqueFieldToModuleNameMap(): array } /** - * @return array + * @return array */ protected function buildIdFieldToModuleNameMap(): array { @@ -125,7 +135,7 @@ protected function buildIdFieldToModuleNameMap(): array } /** - * @return array + * @return array */ protected function buildUniqueFieldToModuleNameMap(): array { @@ -141,7 +151,7 @@ protected function buildUniqueFieldToModuleNameMap(): array } /** - * @return \Symfony\Component\Finder\Finder|\Symfony\Component\Finder\SplFileInfo[] + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ protected function getSchemaFileFinder(): Finder { @@ -156,17 +166,28 @@ protected function getSchemaFileFinder(): Finder /** * @param \Symfony\Component\Finder\SplFileInfo $splFileInfo * - * @return string[] + * @return array */ protected function getIdColumnNames(SplFileInfo $splFileInfo): array { + /** @var \SimpleXMLElement $simpleXmlElement */ $simpleXmlElement = simplexml_load_file($splFileInfo->getPathname()); + $hasNamespace = $this->hasNamespaceInSchema($simpleXmlElement); + if ($hasNamespace) { + $simpleXmlElement->registerXPathNamespace('s', 'spryker:schema-01'); + } + $idColumnNames = []; - foreach ($simpleXmlElement->xpath('//table') as $simpleXmlTableElement) { + /** @var iterable $simpleXmlTableElements */ + $simpleXmlTableElements = $simpleXmlElement->xpath($hasNamespace ? '//s:table' : '//table'); + foreach ($simpleXmlTableElements as $simpleXmlTableElement) { $tableName = (string)$simpleXmlTableElement['name']; - $idColumnSimpleXmlElements = $simpleXmlTableElement->xpath('//table[@name="' . $tableName . '"]/column[starts-with(@name, "id_")]'); + if ($hasNamespace) { + $simpleXmlTableElement->registerXPathNamespace('s', 'spryker:schema-01'); + } + $idColumnSimpleXmlElements = $simpleXmlTableElement->xpath($hasNamespace ? '//s:table[@name="' . $tableName . '"]/s:column[starts-with(@name, "id_")]' : '//table[@name="' . $tableName . '"]/column[starts-with(@name, "id_")]'); if ($idColumnSimpleXmlElements === false) { continue; } @@ -183,17 +204,28 @@ protected function getIdColumnNames(SplFileInfo $splFileInfo): array /** * @param \Symfony\Component\Finder\SplFileInfo $splFileInfo * - * @return string[] + * @return array */ protected function getUniqueColumnNames(SplFileInfo $splFileInfo): array { + /** @var \SimpleXMLElement $simpleXmlElement */ $simpleXmlElement = simplexml_load_file($splFileInfo->getPathname()); + $hasNamespace = $this->hasNamespaceInSchema($simpleXmlElement); + if ($hasNamespace) { + $simpleXmlElement->registerXPathNamespace('s', 'spryker:schema-01'); + } + $uniqueColumnNames = []; - foreach ($simpleXmlElement->xpath('//table') as $simpleXmlTableElement) { + /** @var iterable $simpleXmlTableElements */ + $simpleXmlTableElements = $simpleXmlElement->xpath($hasNamespace ? '//s:table' : '//table'); + foreach ($simpleXmlTableElements as $simpleXmlTableElement) { $tableName = (string)$simpleXmlTableElement['name']; - $uniqueColumnSimpleXmlElements = $simpleXmlTableElement->xpath('//table[@name="' . $tableName . '"]/unique/unique-column'); + if ($hasNamespace) { + $simpleXmlTableElement->registerXPathNamespace('s', 'spryker:schema-01'); + } + $uniqueColumnSimpleXmlElements = $simpleXmlTableElement->xpath($hasNamespace ? '//s:table[@name="' . $tableName . '"]/s:unique/s:unique-column' : '//table[@name="' . $tableName . '"]/unique/unique-column'); if ($uniqueColumnSimpleXmlElements === false) { continue; } @@ -210,10 +242,11 @@ protected function getUniqueColumnNames(SplFileInfo $splFileInfo): array /** * @param \Symfony\Component\Finder\SplFileInfo $splFileInfo * - * @return string[] + * @return array */ protected function getRequiredColumnNames(SplFileInfo $splFileInfo): array { + /** @var \SimpleXMLElement $simpleXmlElement */ $simpleXmlElement = simplexml_load_file($splFileInfo->getPathname()); $requiredColumnNames = []; @@ -249,13 +282,13 @@ protected function getModuleNameFromFile(SplFileInfo $splFileInfo): string } /** - * @param array $idFieldToModuleNameMap - * @param array $idColumnNames + * @param array $idFieldToModuleNameMap + * @param array $idColumnNames * @param string $module * * @throws \Spryker\Zed\Development\Business\Exception\Dependency\PropelSchemaParserException * - * @return string[] + * @return array */ protected function addIdColumnNames(array $idFieldToModuleNameMap, array $idColumnNames, string $module): array { @@ -270,20 +303,21 @@ protected function addIdColumnNames(array $idFieldToModuleNameMap, array $idColu } /** - * @param array $uniqueFieldToModuleNameMap - * @param array $requiredColumnNames - * @param array $uniqueColumnNames + * @param array $uniqueFieldToModuleNameMap + * @param array $requiredColumnNames + * @param array $uniqueColumnNames * @param string $module * * @throws \Spryker\Zed\Development\Business\Exception\Dependency\PropelSchemaParserException * - * @return string[] + * @return array */ protected function addUniqueColumnNames(array $uniqueFieldToModuleNameMap, array $requiredColumnNames, array $uniqueColumnNames, string $module): array { foreach ($uniqueColumnNames as $uniqueColumnName) { - if (isset($uniqueFieldToModuleNameMap[$uniqueColumnName]) && $uniqueFieldToModuleNameMap[$uniqueColumnName] !== $module && - in_array($module . '.' . $uniqueColumnName, $requiredColumnNames) + if ( + isset($uniqueFieldToModuleNameMap[$uniqueColumnName]) && $uniqueFieldToModuleNameMap[$uniqueColumnName] !== $module && + in_array($module . '.' . $uniqueColumnName, $requiredColumnNames, true) ) { throw new PropelSchemaParserException(sprintf('Unique column "%s" was already found in the module "%s".', $uniqueColumnName, $uniqueFieldToModuleNameMap[$uniqueColumnName])); } @@ -294,7 +328,7 @@ protected function addUniqueColumnNames(array $uniqueFieldToModuleNameMap, array } /** - * @return string[] + * @return array */ protected function computeLookupPaths(): array { @@ -306,4 +340,18 @@ protected function computeLookupPaths(): array return array_filter($lookupPaths, 'glob'); } + + /** + * @param \SimpleXMLElement $simpleXmlElement + * + * @return bool + */ + protected function hasNamespaceInSchema(SimpleXMLElement $simpleXmlElement): bool + { + if (in_array('spryker:schema-01', $simpleXmlElement->getNamespaces(), true)) { + return true; + } + + return false; + } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParserInterface.php b/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParserInterface.php index 1428b214..1fb973dc 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParserInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParserInterface.php @@ -14,7 +14,7 @@ interface PropelSchemaParserInterface /** * @param \Symfony\Component\Finder\SplFileInfo $fileInfo * - * @return string[] + * @return array */ public function getForeignColumnNames(SplFileInfo $fileInfo): array; diff --git a/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinder.php b/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinder.php index 65591f79..650acb3d 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinder.php +++ b/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinder.php @@ -28,7 +28,7 @@ public function __construct(DevelopmentConfig $config) /** * @param string $module * - * @return \Symfony\Component\Finder\SplFileInfo[]|\Symfony\Component\Finder\Finder + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ public function findTwigFiles(string $module): Finder { @@ -62,6 +62,11 @@ protected function buildTwigFilePaths(string $module): array $twigFilePaths[] = sprintf($pathPattern, $module); } - return $twigFilePaths = array_filter($twigFilePaths, 'glob'); + return array_filter( + $twigFilePaths, + function (string $twigFilePath) { + return glob($twigFilePath, GLOB_NOSORT); + }, + ); } } diff --git a/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinderInterface.php b/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinderInterface.php index 0aeed3d0..36f4afaf 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/TwigFileFinder/TwigFileFinderInterface.php @@ -14,7 +14,7 @@ interface TwigFileFinderInterface /** * @param string $module * - * @return \Symfony\Component\Finder\SplFileInfo[]|\Symfony\Component\Finder\Finder + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ public function findTwigFiles(string $module): Finder; diff --git a/src/Spryker/Zed/Development/Business/Dependency/Validator/DependencyValidator.php b/src/Spryker/Zed/Development/Business/Dependency/Validator/DependencyValidator.php index d3b7c252..f8006597 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/Validator/DependencyValidator.php +++ b/src/Spryker/Zed/Development/Business/Dependency/Validator/DependencyValidator.php @@ -10,6 +10,7 @@ use Generated\Shared\Transfer\DependencyValidationRequestTransfer; use Generated\Shared\Transfer\DependencyValidationResponseTransfer; use Generated\Shared\Transfer\ModuleDependencyTransfer; +use Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface; use Spryker\Zed\Development\Business\Dependency\ModuleDependencyParserInterface; use Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface; use Spryker\Zed\Development\Business\DependencyTree\ComposerDependencyParserInterface; @@ -31,19 +32,27 @@ class DependencyValidator implements DependencyValidatorInterface */ protected $validationRule; + /** + * @var \Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface + */ + protected $composerNameFinder; + /** * @param \Spryker\Zed\Development\Business\Dependency\ModuleDependencyParserInterface $moduleDependencyParser * @param \Spryker\Zed\Development\Business\DependencyTree\ComposerDependencyParserInterface $composerDependencyParser * @param \Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface $validationRule + * @param \Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface $composerNameFinder */ public function __construct( ModuleDependencyParserInterface $moduleDependencyParser, ComposerDependencyParserInterface $composerDependencyParser, - ValidationRuleInterface $validationRule + ValidationRuleInterface $validationRule, + ComposerNameFinderInterface $composerNameFinder ) { $this->moduleDependencyParser = $moduleDependencyParser; $this->composerDependencyParser = $composerDependencyParser; $this->validationRule = $validationRule; + $this->composerNameFinder = $composerNameFinder; } /** @@ -66,7 +75,7 @@ public function validate(DependencyValidationRequestTransfer $dependencyValidati /** * @param \Generated\Shared\Transfer\DependencyValidationRequestTransfer $dependencyValidationRequestTransfer * - * @return \Generated\Shared\Transfer\ModuleDependencyTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleDependencyTransfer> */ protected function buildModuleDependencyTransferCollection(DependencyValidationRequestTransfer $dependencyValidationRequestTransfer): array { @@ -82,11 +91,15 @@ protected function buildModuleDependencyTransferCollection(DependencyValidationR */ protected function getComposerDependencies(DependencyValidationRequestTransfer $dependencyValidationRequestTransfer): array { - $moduleDependencies = $this->moduleDependencyParser->parseOutgoingDependencies( + $dependencyCollectionTransfer = $this->moduleDependencyParser->parseOutgoingDependencies( $dependencyValidationRequestTransfer->getModule(), - $dependencyValidationRequestTransfer->getDependencyType() + $dependencyValidationRequestTransfer->getDependencyType(), ); - $composerDependencies = $this->composerDependencyParser->getComposerDependencyComparison($moduleDependencies); + foreach ($dependencyCollectionTransfer->getDependencyModules() as $dependencyModuleTransfer) { + $composerName = $dependencyModuleTransfer->getComposerName() ?? $this->composerNameFinder->findComposerNameByModuleName($dependencyModuleTransfer->getModule()); + $dependencyModuleTransfer->setComposerName($composerName); + } + $composerDependencies = $this->composerDependencyParser->getComposerDependencyComparison($dependencyCollectionTransfer); return $composerDependencies; } @@ -94,7 +107,7 @@ protected function getComposerDependencies(DependencyValidationRequestTransfer $ /** * @param array $composerDependencies * - * @return \Generated\Shared\Transfer\ModuleDependencyTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleDependencyTransfer> */ protected function formatDependencies(array $composerDependencies): array { @@ -102,7 +115,7 @@ protected function formatDependencies(array $composerDependencies): array foreach ($composerDependencies as $composerDependency) { $moduleDependencyTransfer = new ModuleDependencyTransfer(); $moduleDependencyTransfer - ->setModule($composerDependency['dependencyModule']) + ->setComposerName($composerDependency['composerName']) ->setIsValid(true) ->setDependencyTypes($this->getDependencyTypes($composerDependency)) ->setIsOptionalDependency($composerDependency['isOptional']) diff --git a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleAmbiguousModuleName.php b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleAmbiguousModuleName.php new file mode 100644 index 00000000..0c8c044b --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleAmbiguousModuleName.php @@ -0,0 +1,33 @@ +getComposerName() === null) { + $moduleDependencyTransfer->setIsValid(false); + $validationMessageTransfer = new ValidationMessageTransfer(); + $validationMessageTransfer->setMessage('Module name was found in more than one organization. Find the correct composer name manually and add it to your dependency.json.'); + $validationMessageTransfer->setFixType(static::MANUAL_FIX); + + $moduleDependencyTransfer->addValidationMessage($validationMessageTransfer); + } + + return $moduleDependencyTransfer; + } +} diff --git a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleComposite.php b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleComposite.php index c82eb66e..a39fa4a1 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleComposite.php +++ b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleComposite.php @@ -12,12 +12,12 @@ class ValidationRuleComposite implements ValidationRuleInterface { /** - * @var \Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface[] + * @var array<\Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface> */ protected $validationRules; /** - * @param \Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface[] $validationRules + * @param array<\Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface> $validationRules */ public function __construct(array $validationRules) { diff --git a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInSourceNotInRequire.php b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInSourceNotInRequire.php index 7b824256..514b2d42 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInSourceNotInRequire.php +++ b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInSourceNotInRequire.php @@ -19,7 +19,10 @@ class ValidationRuleInSourceNotInRequire implements ValidationRuleInterface */ public function validateModuleDependency(ModuleDependencyTransfer $moduleDependencyTransfer): ModuleDependencyTransfer { - if ($moduleDependencyTransfer->getIsSrcDependency() && (!$moduleDependencyTransfer->getIsInComposerRequire() && !$moduleDependencyTransfer->getIsOptionalDependency())) { + if ( + $moduleDependencyTransfer->getIsSrcDependency() && (!$moduleDependencyTransfer->getIsInComposerRequire() && !$moduleDependencyTransfer->getIsOptionalDependency()) && + !$moduleDependencyTransfer->getIsInComposerRequireDev() + ) { $moduleDependencyTransfer->setIsValid(false); $validationMessageTransfer = new ValidationMessageTransfer(); $validationMessageTransfer->setMessage('Source dependency not listed in composer require'); diff --git a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInterface.php b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInterface.php index 0b0490fa..543800d9 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInterface.php +++ b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleInterface.php @@ -11,14 +11,39 @@ interface ValidationRuleInterface { + /** + * @var string + */ public const ADD_REQUIRE = 'add-require'; + + /** + * @var string + */ public const ADD_REQUIRE_DEV = 'add-require-dev'; + + /** + * @var string + */ public const ADD_SUGGEST = 'add-suggest'; + /** + * @var string + */ public const REMOVE_REQUIRE = 'remove-require'; + + /** + * @var string + */ public const REMOVE_REQUIRE_DEV = 'remove-require-dev'; + + /** + * @var string + */ public const REMOVE_SUGGEST = 'remove-suggest'; + /** + * @var string + */ public const MANUAL_FIX = 'manual-fix'; /** diff --git a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleIsOptionalButNotSuggested.php b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleIsOptionalButNotSuggested.php index 579f3ab7..73384e43 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleIsOptionalButNotSuggested.php +++ b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleIsOptionalButNotSuggested.php @@ -22,7 +22,7 @@ public function validateModuleDependency(ModuleDependencyTransfer $moduleDepende if ($moduleDependencyTransfer->getIsOptionalDependency() && $moduleDependencyTransfer->getIsSrcDependency() && !$moduleDependencyTransfer->getIsSuggested()) { $moduleDependencyTransfer->setIsValid(false); $validationMessageTransfer = new ValidationMessageTransfer(); - $validationMessageTransfer->setMessage('Optional dependency should be listed in composer suggests'); + $validationMessageTransfer->setMessage('Optional dependency should be listed in composer suggest'); $validationMessageTransfer->setFixType(static::ADD_SUGGEST); $moduleDependencyTransfer->addValidationMessage($validationMessageTransfer); diff --git a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleNotInTestButInRequireDev.php b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleNotInTestButInRequireDev.php index 5ef14ad4..01412e54 100644 --- a/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleNotInTestButInRequireDev.php +++ b/src/Spryker/Zed/Development/Business/Dependency/Validator/ValidationRules/ValidationRuleNotInTestButInRequireDev.php @@ -23,7 +23,7 @@ public function validateModuleDependency(ModuleDependencyTransfer $moduleDepende $moduleDependencyTransfer->setIsValid(false); $validationMessageTransfer = new ValidationMessageTransfer(); $validationMessageTransfer->setMessage('Dependency listed in composer require-dev not found in tests'); - $validationMessageTransfer->setFixType(self::REMOVE_REQUIRE_DEV); + $validationMessageTransfer->setFixType(static::REMOVE_REQUIRE_DEV); $moduleDependencyTransfer->addValidationMessage($validationMessageTransfer); } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/AdjacencyMatrixBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/AdjacencyMatrixBuilder.php index 20879619..fe20b6b3 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/AdjacencyMatrixBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/AdjacencyMatrixBuilder.php @@ -15,25 +15,25 @@ class AdjacencyMatrixBuilder implements AdjacencyMatrixBuilderInterface /** * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyTreeReader\DependencyTreeReaderInterface */ - private $dependencyTreeReader; + protected $dependencyTreeReader; /** * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\TreeFilterInterface */ - private $filter; + protected $filter; /** - * @var array + * @var array */ - private $bundleList; + protected $bundleList; /** * @var array */ - private $matrix = []; + protected $matrix = []; /** - * @param array $bundleList + * @param array $bundleList * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyTreeReader\DependencyTreeReaderInterface $dependencyTreeReader * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\TreeFilterInterface $filter */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php b/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php index 5da3112e..08862c5a 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/ComposerDependencyParser.php @@ -14,19 +14,48 @@ use Generated\Shared\Transfer\DependencyModuleTransfer; use Generated\Shared\Transfer\DependencyTransfer; use Generated\Shared\Transfer\ModuleTransfer; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\DashToCamelCase; +use Laminas\Filter\Word\SeparatorToCamelCase; +use Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface; use Spryker\Zed\Development\Business\Exception\DependencyTree\InvalidComposerJsonException; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\DashToCamelCase; -use Zend\Filter\Word\SeparatorToCamelCase; class ComposerDependencyParser implements ComposerDependencyParserInterface { + /** + * @var string + */ public const TYPE_INCLUDE = 'include'; + + /** + * @var string + */ public const TYPE_EXCLUDE = 'exclude'; + + /** + * @var string + */ public const TYPE_INCLUDE_DEV = 'include-dev'; + + /** + * @var string + */ public const TYPE_EXCLUDE_DEV = 'exclude-dev'; + /** + * @var \Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface + */ + protected $composerNameFinder; + + /** + * @param \Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface $composerNameFinder + */ + public function __construct(ComposerNameFinderInterface $composerNameFinder) + { + $this->composerNameFinder = $composerNameFinder; + } + /** * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $dependencyCollectionTransfer * @@ -34,37 +63,40 @@ class ComposerDependencyParser implements ComposerDependencyParserInterface */ public function getComposerDependencyComparison(DependencyCollectionTransfer $dependencyCollectionTransfer): array { + // Code dependencies $dependencyCollectionTransfer = $this->getOverwrittenDependenciesForBundle($dependencyCollectionTransfer); - $composerDependencyCollectionTransfer = $this->getParsedComposerDependenciesForBundle($dependencyCollectionTransfer->getModule()); - - $moduleNames = $this->getBundleDependencyNames($dependencyCollectionTransfer); - $moduleNamesInSrc = $this->getBundleDependencyNamesInSrc($dependencyCollectionTransfer); - $moduleNamesInTests = $this->getBundleDependencyNamesInTests($dependencyCollectionTransfer); + $composerNames = $this->getComposerNames($dependencyCollectionTransfer); + $composerNamesInSrc = $this->getComposerNamesForInSrcUsedModules($dependencyCollectionTransfer); + $composerNamesInTests = $this->getComposerNamesForInTestsUsedModules($dependencyCollectionTransfer); - $suggestedNames = $this->getSuggested($composerDependencyCollectionTransfer); - $requireNames = $this->getRequireNames($composerDependencyCollectionTransfer); - $requireDevNames = $this->getRequireNames($composerDependencyCollectionTransfer, true); + // Declared composer dependencies + $composerDependencyCollectionTransfer = $this->parseComposerJson($dependencyCollectionTransfer->getModule()); + $composerSuggestedNames = $this->getSuggested($composerDependencyCollectionTransfer); + $composerRequiredNames = $this->getRequireNames($composerDependencyCollectionTransfer); + $composerRequiredDevNames = $this->getRequireNames($composerDependencyCollectionTransfer, true); - $allModuleNames = array_unique(array_merge($moduleNames, $requireNames, $requireDevNames, $suggestedNames)); - sort($allModuleNames); + $allComposerNames = array_unique(array_merge($composerNames, $composerRequiredNames, $composerRequiredDevNames, $composerSuggestedNames)); + asort($allComposerNames); $dependencies = []; - foreach ($allModuleNames as $moduleName) { - if ($dependencyCollectionTransfer->getModule()->getName() === $moduleName) { + $currentComposerName = sprintf('%s/%s', $dependencyCollectionTransfer->getModule()->getOrganization()->getNameDashed(), $dependencyCollectionTransfer->getModule()->getNameDashed()); + + foreach ($allComposerNames as $composerName) { + if ($currentComposerName === $composerName) { continue; } $dependencies[] = [ - 'dependencyModule' => $moduleName, - 'types' => $this->getDependencyTypes($moduleName, $dependencyCollectionTransfer), - 'isOptional' => $this->getIsOptional($moduleName, $dependencyCollectionTransfer), - 'src' => in_array($moduleName, $moduleNamesInSrc) ? $moduleName : '', - 'tests' => in_array($moduleName, $moduleNamesInTests) ? $moduleName : '', - 'composerRequire' => in_array($moduleName, $requireNames) ? $moduleName : '', - 'composerRequireDev' => in_array($moduleName, $requireDevNames) ? $moduleName : '', - 'suggested' => in_array($moduleName, $suggestedNames) ? $moduleName : '', - 'isOwnExtensionModule' => $this->isOwnExtensionModule($moduleName, $dependencyCollectionTransfer), + 'composerName' => $composerName, + 'types' => $this->getDependencyTypes($composerName, $dependencyCollectionTransfer), + 'isOptional' => $this->getIsOptional($composerName, $dependencyCollectionTransfer), + 'src' => in_array($composerName, $composerNamesInSrc, true) ? $composerName : '', + 'tests' => in_array($composerName, $composerNamesInTests, true) ? $composerName : '', + 'composerRequire' => in_array($composerName, $composerRequiredNames, true) ? $composerName : '', + 'composerRequireDev' => in_array($composerName, $composerRequiredDevNames, true) ? $composerName : '', + 'suggested' => in_array($composerName, $composerSuggestedNames, true) ? $composerName : '', + 'isOwnExtensionModule' => $this->isOwnExtensionModule($composerName, $dependencyCollectionTransfer), ]; } @@ -72,17 +104,17 @@ public function getComposerDependencyComparison(DependencyCollectionTransfer $de } /** - * @param string $moduleName + * @param string $composerName * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $moduleDependencyCollectionTransfer * * @return bool */ - protected function getIsOptional($moduleName, DependencyCollectionTransfer $moduleDependencyCollectionTransfer) + protected function getIsOptional($composerName, DependencyCollectionTransfer $moduleDependencyCollectionTransfer) { $isOptional = true; $isInTestsOnly = true; foreach ($moduleDependencyCollectionTransfer->getDependencyModules() as $moduleDependencyTransfer) { - if ($moduleDependencyTransfer->getModule() === $moduleName) { + if ($moduleDependencyTransfer->getComposerName() === $composerName) { foreach ($moduleDependencyTransfer->getDependencies() as $dependencyTransfer) { if (!$dependencyTransfer->getIsInTest()) { $isInTestsOnly = false; @@ -98,16 +130,16 @@ protected function getIsOptional($moduleName, DependencyCollectionTransfer $modu } /** - * @param string $moduleName + * @param string $composerName * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $moduleDependencyCollectionTransfer * - * @return string[] + * @return array */ - protected function getDependencyTypes($moduleName, DependencyCollectionTransfer $moduleDependencyCollectionTransfer): array + protected function getDependencyTypes($composerName, DependencyCollectionTransfer $moduleDependencyCollectionTransfer): array { $dependencyTypes = []; foreach ($moduleDependencyCollectionTransfer->getDependencyModules() as $moduleDependencyTransfer) { - if ($moduleDependencyTransfer->getModule() !== $moduleName) { + if ($moduleDependencyTransfer->getComposerName() !== $composerName) { continue; } @@ -124,14 +156,14 @@ protected function getDependencyTypes($moduleName, DependencyCollectionTransfer * * @return array */ - protected function getBundleDependencyNames(DependencyCollectionTransfer $moduleDependencyCollectionTransfer) + protected function getComposerNames(DependencyCollectionTransfer $moduleDependencyCollectionTransfer): array { - $moduleNames = []; + $composerNames = []; foreach ($moduleDependencyCollectionTransfer->getDependencyModules() as $moduleDependencyTransfer) { - $moduleNames[] = $moduleDependencyTransfer->getModule(); + $composerNames[] = $moduleDependencyTransfer->getComposerName(); } - return $moduleNames; + return array_unique($composerNames); } /** @@ -139,18 +171,18 @@ protected function getBundleDependencyNames(DependencyCollectionTransfer $module * * @return array */ - protected function getBundleDependencyNamesInSrc(DependencyCollectionTransfer $moduleDependencyCollectionTransfer) + protected function getComposerNamesForInSrcUsedModules(DependencyCollectionTransfer $moduleDependencyCollectionTransfer) { - $moduleNames = []; + $composerNames = []; foreach ($moduleDependencyCollectionTransfer->getDependencyModules() as $moduleDependencyTransfer) { foreach ($moduleDependencyTransfer->getDependencies() as $dependencyTransfer) { if (!$dependencyTransfer->getIsInTest()) { - $moduleNames[] = $moduleDependencyTransfer->getModule(); + $composerNames[] = $moduleDependencyTransfer->getComposerName(); } } } - return $moduleNames; + return $composerNames; } /** @@ -158,23 +190,23 @@ protected function getBundleDependencyNamesInSrc(DependencyCollectionTransfer $m * * @return array */ - protected function getBundleDependencyNamesInTests(DependencyCollectionTransfer $moduleDependencyCollectionTransfer) + protected function getComposerNamesForInTestsUsedModules(DependencyCollectionTransfer $moduleDependencyCollectionTransfer) { - $moduleNames = []; - foreach ($moduleDependencyCollectionTransfer->getDependencyModules() as $dependencyBundleTransfer) { - foreach ($dependencyBundleTransfer->getDependencies() as $dependencyTransfer) { + $composerNames = []; + foreach ($moduleDependencyCollectionTransfer->getDependencyModules() as $moduleDependencyTransfer) { + foreach ($moduleDependencyTransfer->getDependencies() as $dependencyTransfer) { if ($dependencyTransfer->getIsInTest()) { - $moduleNames[] = $dependencyBundleTransfer->getModule(); + $composerNames[] = $moduleDependencyTransfer->getComposerName(); } } } - return $moduleNames; + return $composerNames; } /** * If a dependency is optional it needs to be in suggest. - * Return all module names which are marked as optional. + * Return all composer names which are marked as optional. * * @param \Generated\Shared\Transfer\ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer * @@ -182,14 +214,14 @@ protected function getBundleDependencyNamesInTests(DependencyCollectionTransfer */ protected function getSuggested(ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer) { - $composerModuleNames = []; + $composerNames = []; foreach ($composerDependencyCollectionTransfer->getComposerDependencies() as $composerDependency) { if ($composerDependency->getName() && $composerDependency->getIsOptional()) { - $composerModuleNames[] = $composerDependency->getName(); + $composerNames[] = $composerDependency->getName(); } } - return $composerModuleNames; + return $composerNames; } /** @@ -200,14 +232,14 @@ protected function getSuggested(ComposerDependencyCollectionTransfer $composerDe */ protected function getRequireNames(ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer, $isDev = false) { - $composerModuleNames = []; + $composerNames = []; foreach ($composerDependencyCollectionTransfer->getComposerDependencies() as $composerDependency) { if ($composerDependency->getName() && $composerDependency->getIsDev() === $isDev) { - $composerModuleNames[] = $composerDependency->getName(); + $composerNames[] = $composerDependency->getName(); } } - return $composerModuleNames; + return $composerNames; } /** @@ -228,17 +260,47 @@ protected function getOverwrittenDependenciesForBundle(DependencyCollectionTrans $dependencyCollectionTransfer->setDependencyModules(new ArrayObject()); foreach ($dependencyModulesCollectionTransfer as $moduleDependencyTransfer) { - if (!in_array($moduleDependencyTransfer->getModule(), $excluded)) { + if (!in_array($moduleDependencyTransfer->getComposerName(), $excluded, true)) { $dependencyCollectionTransfer->addDependencyModule($moduleDependencyTransfer); } } + + $overwrittenRequiredDependencies = []; foreach ($declaredDependencies[static::TYPE_INCLUDE] as $declaredDependency) { $dependencyCollectionTransfer = $this->addDeclaredDependency($dependencyCollectionTransfer, $declaredDependency); + $overwrittenRequiredDependencies[] = $declaredDependency; } + foreach ($declaredDependencies[static::TYPE_INCLUDE_DEV] as $declaredDependency) { $dependencyCollectionTransfer = $this->addDeclaredDependency($dependencyCollectionTransfer, $declaredDependency, true); } + $dependencyCollectionTransfer = $this->addNonOverwrittenRequiredDependencies($dependencyCollectionTransfer, $overwrittenRequiredDependencies); + + return $dependencyCollectionTransfer; + } + + /** + * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $dependencyCollectionTransfer + * @param array $overwrittenRequiredDependencies + * + * @return \Generated\Shared\Transfer\DependencyCollectionTransfer + */ + protected function addNonOverwrittenRequiredDependencies( + DependencyCollectionTransfer $dependencyCollectionTransfer, + array $overwrittenRequiredDependencies + ): DependencyCollectionTransfer { + $composerDependencyCollectionTransfer = $this->parseComposerJson($dependencyCollectionTransfer->getModule()); + + foreach ($composerDependencyCollectionTransfer->getComposerDependencies() as $composerDependency) { + if ( + $composerDependency->getName() && $composerDependency->getIsDev() === false && + in_array($composerDependency->getName(), $overwrittenRequiredDependencies) + ) { + $dependencyCollectionTransfer = $this->addDeclaredDependency($dependencyCollectionTransfer, $composerDependency->getName()); + } + } + return $dependencyCollectionTransfer; } @@ -257,6 +319,7 @@ protected function parseDeclaredDependenciesForBundle(ModuleTransfer $moduleTran return []; } + /** @var string $content */ $content = file_get_contents($dependencyJsonFilePath); $content = json_decode($content, true); @@ -264,7 +327,7 @@ protected function parseDeclaredDependenciesForBundle(ModuleTransfer $moduleTran throw new InvalidComposerJsonException(sprintf( 'Unable to parse %s: %s.', $dependencyJsonFilePath, - json_last_error_msg() + json_last_error_msg(), )); } @@ -283,7 +346,7 @@ protected function parseDeclaredDependenciesForBundle(ModuleTransfer $moduleTran * * @return \Generated\Shared\Transfer\ComposerDependencyCollectionTransfer */ - protected function getParsedComposerDependenciesForBundle(ModuleTransfer $moduleTransfer): ComposerDependencyCollectionTransfer + protected function parseComposerJson(ModuleTransfer $moduleTransfer): ComposerDependencyCollectionTransfer { $composerDependencies = new ComposerDependencyCollectionTransfer(); @@ -293,6 +356,7 @@ protected function getParsedComposerDependenciesForBundle(ModuleTransfer $module return $composerDependencies; } + /** @var string $content */ $content = file_get_contents($composerJsonFilePath); $content = json_decode($content, true); @@ -300,24 +364,24 @@ protected function getParsedComposerDependenciesForBundle(ModuleTransfer $module throw new InvalidComposerJsonException(sprintf( 'Unable to parse %s: %s.', $composerJsonFilePath, - json_last_error_msg() + json_last_error_msg(), )); } - $require = isset($content['require']) ? $content['require'] : []; + $require = $content['require'] ?? []; $this->addComposerDependencies($require, $composerDependencies); - $requireDev = isset($content['require-dev']) ? $content['require-dev'] : []; + $requireDev = $content['require-dev'] ?? []; $this->addComposerDependencies($requireDev, $composerDependencies, true); - $suggested = isset($content['suggest']) ? $content['suggest'] : []; + $suggested = $content['suggest'] ?? []; $this->addSuggestedDependencies($suggested, $composerDependencies); return $composerDependencies; } /** - * @param array $require + * @param array $require * @param \Generated\Shared\Transfer\ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer * @param bool $isDev * @@ -326,14 +390,15 @@ protected function getParsedComposerDependenciesForBundle(ModuleTransfer $module protected function addComposerDependencies(array $require, ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer, $isDev = false) { foreach ($require as $package => $version) { - if (strpos($package, 'spryker') !== 0) { + if (strpos($package, '/') === false) { continue; } - $bundle = $this->getBundleName($package); + $module = $this->getBundleName($package); $composerDependencyTransfer = new ComposerDependencyTransfer(); $composerDependencyTransfer - ->setName($bundle) + ->setName($package) + ->setModuleName($module) ->setIsDev($isDev); $composerDependencyCollectionTransfer->addComposerDependency($composerDependencyTransfer); @@ -341,22 +406,20 @@ protected function addComposerDependencies(array $require, ComposerDependencyCol } /** - * @param array $require + * @param array $suggested * @param \Generated\Shared\Transfer\ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer * * @return void */ - protected function addSuggestedDependencies(array $require, ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer) + protected function addSuggestedDependencies(array $suggested, ComposerDependencyCollectionTransfer $composerDependencyCollectionTransfer) { - foreach ($require as $package => $version) { - if (strpos($package, 'spryker') !== 0) { - continue; - } - $bundle = $this->getBundleName($package); + foreach ($suggested as $package => $description) { + $module = $this->getBundleName($package); $composerDependencyTransfer = new ComposerDependencyTransfer(); $composerDependencyTransfer - ->setName($bundle) + ->setName($package) + ->setModuleName($module) ->setIsOptional(true); $composerDependencyCollectionTransfer->addComposerDependency($composerDependencyTransfer); @@ -387,7 +450,9 @@ protected function getBundleName($package) { $name = substr($package, strpos($package, '/') + 1); $filter = new SeparatorToCamelCase('-'); - $name = ucfirst($filter->filter($name)); + /** @var string $camelCasedName */ + $camelCasedName = $filter->filter($name); + $name = ucfirst($camelCasedName); return $name; } @@ -405,19 +470,23 @@ protected function isOwnExtensionModule($moduleName, $dependencyCollectionTransf /** * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $moduleDependencyCollectionTransfer - * @param string $declaredDependency + * @param string $composerName * @param bool $isInTest * * @return \Generated\Shared\Transfer\DependencyCollectionTransfer */ - protected function addDeclaredDependency(DependencyCollectionTransfer $moduleDependencyCollectionTransfer, $declaredDependency, $isInTest = false) + protected function addDeclaredDependency(DependencyCollectionTransfer $moduleDependencyCollectionTransfer, string $composerName, $isInTest = false) { + $moduleName = $this->getBundleName($composerName); + $dependencyModuleTransfer = new DependencyModuleTransfer(); $dependencyTransfer = new DependencyTransfer(); - $dependencyTransfer->setModule($declaredDependency); + $dependencyTransfer->setModule($moduleName); + $dependencyTransfer->setComposerName($composerName); $dependencyTransfer->setIsInTest($isInTest); $dependencyModuleTransfer->addDependency($dependencyTransfer); - $dependencyModuleTransfer->setModule($declaredDependency); + $dependencyModuleTransfer->setModule($moduleName); + $dependencyModuleTransfer->setComposerName($composerName); $moduleDependencyCollectionTransfer->addDependencyModule($dependencyModuleTransfer); return $moduleDependencyCollectionTransfer; diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/BundleToViewFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/BundleToViewFilter.php index 5ac8c347..18f382db 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/BundleToViewFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/BundleToViewFilter.php @@ -14,7 +14,7 @@ class BundleToViewFilter implements DependencyFilterInterface /** * @var string */ - private $bundle; + protected $bundle; /** * @param string $bundle @@ -25,7 +25,7 @@ public function __construct($bundle) } /** - * @param array $dependency + * @param array $dependency * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ClassNameFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ClassNameFilter.php index 98a95e14..06dd8f86 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ClassNameFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ClassNameFilter.php @@ -14,7 +14,7 @@ class ClassNameFilter implements DependencyFilterInterface /** * @var string */ - private $pattern; + protected $pattern; /** * @param string $pattern @@ -25,7 +25,7 @@ public function __construct($pattern) } /** - * @param array $dependency + * @param array $dependency * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ConstantsToForeignConstantsFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ConstantsToForeignConstantsFilter.php index db922158..5ca90fb1 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ConstantsToForeignConstantsFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ConstantsToForeignConstantsFilter.php @@ -12,7 +12,7 @@ class ConstantsToForeignConstantsFilter implements DependencyFilterInterface { /** - * @param array $dependency + * @param array $dependency * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilter.php index 51c513d9..2be684c3 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilter.php @@ -10,9 +10,9 @@ class DependencyFilter implements DependencyFilterCompositeInterface { /** - * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface[] + * @var array<\Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface> */ - private $dependencyFilter = []; + protected $dependencyFilter = []; /** * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface $dependencyFilter @@ -27,7 +27,7 @@ public function addFilter(DependencyFilterInterface $dependencyFilter) } /** - * @param array $dependency + * @param array $dependency * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilterInterface.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilterInterface.php index 9d019079..2c86080b 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilterInterface.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/DependencyFilterInterface.php @@ -10,7 +10,7 @@ interface DependencyFilterInterface { /** - * @param array $dependency + * @param array $dependency * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/EngineBundleFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/EngineBundleFilter.php index 9af91fa2..5d4e265c 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/EngineBundleFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/EngineBundleFilter.php @@ -14,24 +14,26 @@ class EngineBundleFilter implements DependencyFilterInterface /** * @var array */ - private $filterBundles = []; + protected $filterBundles = []; /** * @param string $pathToBundleConfig */ public function __construct($pathToBundleConfig) { - $bundleList = json_decode(file_get_contents($pathToBundleConfig), true); + /** @var string $bundles */ + $bundles = file_get_contents($pathToBundleConfig); + $bundleList = json_decode($bundles, true); $this->filterBundles = array_keys($bundleList); } /** - * @param array $dependency + * @param array $dependency * * @return bool */ public function filter(array $dependency) { - return in_array($dependency[DependencyTree::META_MODULE], $this->filterBundles); + return in_array($dependency[DependencyTree::META_MODULE], $this->filterBundles, true); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ExternalDependencyFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ExternalDependencyFilter.php index 09c66808..d3943d21 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ExternalDependencyFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ExternalDependencyFilter.php @@ -12,7 +12,7 @@ class ExternalDependencyFilter implements DependencyFilterInterface { /** - * @param array $dependency + * @param array $dependency * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ForeignEngineBundleFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ForeignEngineBundleFilter.php index bb8a52a9..c7a840ae 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ForeignEngineBundleFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/ForeignEngineBundleFilter.php @@ -14,24 +14,26 @@ class ForeignEngineBundleFilter implements DependencyFilterInterface /** * @var array */ - private $filterBundles = []; + protected $filterBundles = []; /** * @param string $pathToBundleConfig */ public function __construct($pathToBundleConfig) { - $bundleList = json_decode(file_get_contents($pathToBundleConfig), true); + /** @var string $bundles */ + $bundles = file_get_contents($pathToBundleConfig); + $bundleList = json_decode($bundles, true); $this->filterBundles = array_keys($bundleList); } /** - * @param array $dependency + * @param array $dependency * * @return bool */ public function filter(array $dependency) { - return in_array($dependency[DependencyTree::META_FOREIGN_BUNDLE], $this->filterBundles); + return in_array($dependency[DependencyTree::META_FOREIGN_BUNDLE], $this->filterBundles, true); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InTestDependencyFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InTestDependencyFilter.php index d80f9407..bed75684 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InTestDependencyFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InTestDependencyFilter.php @@ -15,12 +15,12 @@ class InTestDependencyFilter implements DependencyFilterInterface { /** - * @param array $dependency + * @param array $dependency * * @return bool */ public function filter(array $dependency) { - return $dependency[DependencyTree::META_IN_TEST]; + return (bool)$dependency[DependencyTree::META_IN_TEST]; } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InternalDependencyFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InternalDependencyFilter.php index 4e6dab05..bc7d8799 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InternalDependencyFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InternalDependencyFilter.php @@ -12,7 +12,7 @@ class InternalDependencyFilter implements DependencyFilterInterface { /** - * @param array $dependency + * @param array $dependency * * @return bool */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InvalidForeignBundleFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InvalidForeignBundleFilter.php index c47ef115..28e6c154 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InvalidForeignBundleFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/InvalidForeignBundleFilter.php @@ -12,12 +12,12 @@ class InvalidForeignBundleFilter implements DependencyFilterInterface { /** - * @var array + * @var array */ - private $allowedBundles; + protected $allowedBundles; /** - * @param array $allowedBundles + * @param array $allowedBundles */ public function __construct(array $allowedBundles) { @@ -25,12 +25,12 @@ public function __construct(array $allowedBundles) } /** - * @param array $dependency + * @param array $dependency * * @return bool */ public function filter(array $dependency) { - return (!in_array($dependency[DependencyTree::META_FOREIGN_BUNDLE], $this->allowedBundles) && !isset($dependency[DependencyTree::META_FOREIGN_IS_EXTERNAL])); + return (!in_array($dependency[DependencyTree::META_FOREIGN_BUNDLE], $this->allowedBundles, true) && !isset($dependency[DependencyTree::META_FOREIGN_IS_EXTERNAL])); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/TreeFilter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/TreeFilter.php index df66d4a3..3fb18549 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/TreeFilter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFilter/TreeFilter.php @@ -10,9 +10,9 @@ class TreeFilter implements TreeFilterCompositeInterface { /** - * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface[] + * @var array<\Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface> */ - private $filter; + protected $filter; /** * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface $filter diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/AbstractDependencyFinder.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/AbstractDependencyFinder.php index d0fa3516..ca1e2e90 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/AbstractDependencyFinder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/AbstractDependencyFinder.php @@ -13,15 +13,30 @@ abstract class AbstractDependencyFinder { + /** + * @var string + */ public const DEPENDS_LAYER = 'dependsLayer'; + + /** + * @var string + */ public const LAYER_BUSINESS = 'Business'; + + /** + * @var string + */ public const LAYER_PERSISTENCE = 'Persistence'; + + /** + * @var string + */ public const LAYER_COMMUNICATION = 'Communication'; /** * @var \Spryker\Zed\Development\Business\DependencyTree\AbstractDependencyTree */ - private $dependencyTree; + protected $dependencyTree; /** * @param \Spryker\Zed\Development\Business\DependencyTree\AbstractDependencyTree $dependencyTree diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependency.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependency.php index 0a784f06..dc4a2341 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependency.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependency.php @@ -7,17 +7,19 @@ namespace Spryker\Zed\Development\Business\DependencyTree\DependencyFinder; +use Laminas\Filter\Word\SeparatorToCamelCase; use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Ruleset; use PHP_CodeSniffer\Runner; use Spryker\Zed\Development\Business\DependencyTree\DependencyTree; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\Word\SeparatorToCamelCase; -$manualAutoload = APPLICATION_VENDOR_DIR . '/squizlabs/php_codesniffer/autoload.php'; -if (!class_exists(Config::class) && file_exists($manualAutoload)) { - require $manualAutoload; +if (defined('APPLICATION_VENDOR_DIR')) { + $manualAutoload = APPLICATION_VENDOR_DIR . '/squizlabs/php_codesniffer/autoload.php'; + if (!class_exists(Config::class) && file_exists($manualAutoload)) { + require $manualAutoload; + } } class ExternalDependency extends AbstractDependencyFinder @@ -80,7 +82,8 @@ public function addDependencies(SplFileInfo $fileInfo) continue; } - if (strpos($className, 'Spryker') !== false + if ( + strpos($className, 'Spryker') !== false || strpos($className, 'Generated') !== false || strpos($className, 'Orm') !== false || strpos($className, 'static') !== false @@ -89,6 +92,7 @@ public function addDependencies(SplFileInfo $fileInfo) continue; } + $dependencyInformation = []; $dependencyInformation[DependencyTree::META_FOREIGN_LAYER] = 'external'; $dependencyInformation[DependencyTree::META_FOREIGN_CLASS_NAME] = $className; $dependencyInformation[DependencyTree::META_FOREIGN_IS_EXTERNAL] = true; @@ -136,8 +140,10 @@ protected function getInternalBundleNameForExternalDependency($className) if (strpos($className, $namespace) !== false) { $foreignBundle = substr($internalComposerBundleName, 8); $filter = new SeparatorToCamelCase('-'); + /** @var string $camelCasedForeignBundle */ + $camelCasedForeignBundle = $filter->filter($foreignBundle); - return ucfirst($filter->filter($foreignBundle)); + return ucfirst($camelCasedForeignBundle); } } @@ -164,6 +170,7 @@ private function buildClassName(array $classNameParts) */ private function cleanAutoloader() { + /** @var iterable $autoloadFunctions */ $autoloadFunctions = spl_autoload_functions(); $codeSnifferAutoloadFunction = false; diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorClient.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorClient.php index 2e5a8b5a..e203dda2 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorClient.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorClient.php @@ -12,7 +12,14 @@ class LocatorClient extends AbstractDependencyFinder { + /** + * @var string + */ public const NO_LAYER = 'Default'; + + /** + * @var string + */ public const BUNDLE = 'bundle'; /** diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorFacade.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorFacade.php index 8e834b33..c9dcf413 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorFacade.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorFacade.php @@ -12,6 +12,9 @@ class LocatorFacade extends AbstractDependencyFinder { + /** + * @var string + */ public const BUNDLE = 'bundle'; /** diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorQueryContainer.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorQueryContainer.php index 2a5ee4c5..e20cf1f2 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorQueryContainer.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorQueryContainer.php @@ -12,6 +12,9 @@ class LocatorQueryContainer extends AbstractDependencyFinder { + /** + * @var string + */ public const BUNDLE = 'bundle'; /** diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorService.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorService.php index 4c870435..73b7b92e 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorService.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/LocatorService.php @@ -12,7 +12,14 @@ class LocatorService extends AbstractDependencyFinder { + /** + * @var string + */ public const NO_LAYER = 'Default'; + + /** + * @var string + */ public const BUNDLE = 'bundle'; /** diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/UseStatement.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/UseStatement.php index 86d6c301..520b3b77 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/UseStatement.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyFinder/UseStatement.php @@ -12,7 +12,14 @@ class UseStatement extends AbstractDependencyFinder { + /** + * @var string + */ public const LAYER_DEFAULT = 'Default'; + + /** + * @var string + */ public const BUNDLE = 'bundle'; /** @@ -29,8 +36,10 @@ public function addDependencies(SplFileInfo $fileInfo) $className = str_replace(['use ', ';'], '', $match[0]); $toBundle = $match[static::BUNDLE]; $layer = $this->getLayerFromUseStatement($match); - $dependencyInformation[DependencyTree::META_FOREIGN_LAYER] = $layer; - $dependencyInformation[DependencyTree::META_FOREIGN_CLASS_NAME] = $className; + $dependencyInformation = [ + DependencyTree::META_FOREIGN_LAYER => $layer, + DependencyTree::META_FOREIGN_CLASS_NAME => $className, + ]; $this->addDependency($fileInfo, $toBundle, $dependencyInformation); } @@ -38,15 +47,17 @@ public function addDependencies(SplFileInfo $fileInfo) if (preg_match('/use Spryker\\\Shared\\\Config/', $content)) { $toBundle = 'Config'; - $dependencyInformation[DependencyTree::META_FOREIGN_LAYER] = ''; - $dependencyInformation[DependencyTree::META_FOREIGN_CLASS_NAME] = 'Spryker\\Shared\\Config'; + $dependencyInformation = [ + DependencyTree::META_FOREIGN_LAYER => '', + DependencyTree::META_FOREIGN_CLASS_NAME => 'Spryker\\Shared\\Config', + ]; $this->addDependency($fileInfo, $toBundle, $dependencyInformation); } } /** - * @param string $match + * @param array $match * * @return string */ @@ -56,7 +67,7 @@ protected function getLayerFromUseStatement($match) if (preg_match('/\\\/', $relativeClassName)) { $classNameParts = explode('\\', $relativeClassName); $layer = array_shift($classNameParts); - if (in_array($layer, [static::LAYER_BUSINESS, static::LAYER_COMMUNICATION, static::LAYER_PERSISTENCE])) { + if (in_array($layer, [static::LAYER_BUSINESS, static::LAYER_COMMUNICATION, static::LAYER_PERSISTENCE], true)) { return $layer; } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/DetailedGraphBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/DetailedGraphBuilder.php index 527be1ed..716ec2d6 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/DetailedGraphBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/DetailedGraphBuilder.php @@ -21,7 +21,7 @@ class DetailedGraphBuilder implements GraphBuilderInterface /** * @var \Spryker\Shared\Graph\GraphInterface */ - private $graph; + protected $graph; /** * @var array @@ -184,7 +184,7 @@ private function addForeignBundleLayer(array $dependencyInformation, $group) [ 'label' => $this->getForeignUsage($dependencyInformation[DependencyTree::META_FINDER]) . ' : ' . $dependencyInformation[DependencyTree::META_FOREIGN_CLASS_NAME], 'fontsize' => 8, - ] + ], ); } @@ -200,7 +200,7 @@ private function getForeignBundleLayerNodeId(array $dependencyInformation) [ $dependencyInformation[DependencyTree::META_FOREIGN_BUNDLE], $dependencyInformation[DependencyTree::META_FOREIGN_LAYER], - ] + ], ); } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/ExternalGraphBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/ExternalGraphBuilder.php index e8066ec6..94bde1ea 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/ExternalGraphBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/ExternalGraphBuilder.php @@ -12,13 +12,20 @@ class ExternalGraphBuilder implements GraphBuilderInterface { + /** + * @var string + */ public const FONT_COLOR = 'fontcolor'; + + /** + * @var string + */ public const LABEL = 'label'; /** * @var \Spryker\Shared\Graph\GraphInterface */ - private $graph; + protected $graph; /** * @param \Spryker\Shared\Graph\GraphInterface $graph diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/GraphBuilderInterface.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/GraphBuilderInterface.php index 3372d951..9beceb4f 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/GraphBuilderInterface.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/GraphBuilderInterface.php @@ -9,7 +9,14 @@ interface GraphBuilderInterface { + /** + * @var string + */ public const ENGINE_BUNDLE_FONT_COLOR = 'grey'; + + /** + * @var string + */ public const ENGINE_BUNDLE_INFO_TEXT = '
(engine)'; /** diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/OutgoingGraphBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/OutgoingGraphBuilder.php index 9113e0e3..b836d98e 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/OutgoingGraphBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/OutgoingGraphBuilder.php @@ -38,7 +38,7 @@ class OutgoingGraphBuilder protected $dependencyManager; /** - * @var array + * @var array */ protected $bundlesToFilter; @@ -47,10 +47,15 @@ class OutgoingGraphBuilder * @param \Spryker\Zed\Graph\Communication\Plugin\GraphPlugin $graph * @param \Spryker\Zed\Development\Business\Dependency\ModuleDependencyParserInterface $moduleDependencyParser * @param \Spryker\Zed\Development\Business\Dependency\ManagerInterface $dependencyManager - * @param array $bundlesToFilter + * @param array $bundlesToFilter */ - public function __construct($bundleName, GraphPlugin $graph, ModuleDependencyParserInterface $moduleDependencyParser, ManagerInterface $dependencyManager, array $bundlesToFilter = []) - { + public function __construct( + $bundleName, + GraphPlugin $graph, + ModuleDependencyParserInterface $moduleDependencyParser, + ManagerInterface $dependencyManager, + array $bundlesToFilter = [] + ) { $this->bundleName = $bundleName; $this->graph = $graph; $this->moduleDependencyParser = $moduleDependencyParser; @@ -105,20 +110,20 @@ public function build($showIncomingDependencies = false) */ protected function addIncomingDependencies() { - $incomingDependencies = array_keys($this->dependencyManager->parseIncomingDependencies($this->bundleName)); + $incomingDependencies = $this->dependencyManager->parseIncomingDependencies($this->bundleName); foreach ($incomingDependencies as $incomingBundle) { $attributes = [ - 'url' => '/development/dependency/outgoing-graph?bundle=' . $incomingBundle, + 'url' => '/development/dependency/outgoing-graph?bundle=' . $incomingBundle->getName(), ]; - $this->graph->addNode($incomingBundle, $attributes); - $this->graph->addEdge($incomingBundle, $this->bundleName); + $this->graph->addNode($incomingBundle->getName(), $attributes); + $this->graph->addEdge($incomingBundle->getName(), $this->bundleName); } } /** * @param string $moduleName - * @param \ArrayObject $allDependencies + * @param \ArrayObject $allDependencies * * @return void */ @@ -138,9 +143,9 @@ protected function buildGraph($moduleName, ArrayObject $allDependencies) $dependencies = $this->filterBundles($dependencies); } - $allDependencies[$moduleName] = $dependencies; + $allDependencies->offsetSet($moduleName, $dependencies); foreach ($dependencies as $dependentBundle) { - if (array_key_exists($dependentBundle, $allDependencies)) { + if ($allDependencies->offsetExists($dependentBundle)) { continue; } $this->buildGraph($dependentBundle, $allDependencies); @@ -180,7 +185,7 @@ protected function getBundleNames(DependencyCollectionTransfer $bundleDependency protected function filterBundles(array $dependencies) { $callback = function ($bundle) { - return !in_array($bundle, $this->bundlesToFilter); + return !in_array($bundle, $this->bundlesToFilter, true); }; return array_filter($dependencies, $callback); diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/SimpleGraphBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/SimpleGraphBuilder.php index c143b1ae..9b46eb6c 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/SimpleGraphBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraph/SimpleGraphBuilder.php @@ -12,13 +12,20 @@ class SimpleGraphBuilder implements GraphBuilderInterface { + /** + * @var string + */ public const FONT_COLOR = 'fontcolor'; + + /** + * @var string + */ public const LABEL = 'label'; /** * @var \Spryker\Shared\Graph\GraphInterface */ - private $graph; + protected $graph; /** * @param \Spryker\Shared\Graph\GraphInterface $graph diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraphBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraphBuilder.php index d1490d66..1e161d50 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraphBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyGraphBuilder.php @@ -14,12 +14,12 @@ class DependencyGraphBuilder implements DependencyGraphBuilderInterface /** * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyGraph\GraphBuilderInterface */ - private $graphBuilder; + protected $graphBuilder; /** * @var array */ - private $dependencyTree; + protected $dependencyTree; /** * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyGraph\GraphBuilderInterface $graphBuilder diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/DependencyHydrator.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/DependencyHydrator.php index a86139b3..c9903467 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/DependencyHydrator.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/DependencyHydrator.php @@ -10,9 +10,9 @@ class DependencyHydrator implements DependencyHydratorCompositeInterface { /** - * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyHydrator\DependencyHydratorInterface[] + * @var array<\Spryker\Zed\Development\Business\DependencyTree\DependencyHydrator\DependencyHydratorInterface> */ - private $hydrator; + protected $hydrator; /** * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyHydrator\DependencyHydratorInterface $hydrator diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageNameHydrator.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageNameHydrator.php index 7753854e..9211a47d 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageNameHydrator.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageNameHydrator.php @@ -26,12 +26,13 @@ public function hydrate(array &$dependency) /** * @param array $dependency * - * @return bool|string + * @return string|bool */ private function getComposerNameByClassName(array $dependency) { try { $reflection = new ReflectionClass($dependency[DependencyTree::META_FOREIGN_CLASS_NAME]); + /** @var string $filePath */ $filePath = $reflection->getFileName(); $this->cleanAutoloader(); @@ -47,7 +48,9 @@ private function getComposerNameByClassName(array $dependency) $composerPath = $path . 'composer.json'; if (file_exists($composerPath)) { - $composerConfig = json_decode(file_get_contents($composerPath)); + /** @var string $composerConfigContent */ + $composerConfigContent = file_get_contents($composerPath); + $composerConfig = json_decode($composerConfigContent); return $composerConfig->name; } @@ -65,6 +68,7 @@ private function getComposerNameByClassName(array $dependency) */ private function cleanAutoloader() { + /** @var iterable $autoloadFunctions */ $autoloadFunctions = spl_autoload_functions(); $codeSnifferAutoloadFunction = false; diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageVersionHydrator.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageVersionHydrator.php index b0b3a14b..6fbb8fc0 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageVersionHydrator.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyHydrator/PackageVersionHydrator.php @@ -11,13 +11,20 @@ class PackageVersionHydrator implements DependencyHydratorInterface { + /** + * @var string + */ public const NAME = 'name'; + + /** + * @var string + */ public const VERSION = 'version'; /** * @var array */ - private $installedPackages; + protected $installedPackages; /** * @param array $installedPackages @@ -34,13 +41,19 @@ public function __construct(array $installedPackages) */ public function hydrate(array &$dependency) { - $dependency[DependencyTree::META_COMPOSER_VERSION] = $this->getComposerVersion($dependency); + $composerVersion = $this->getComposerVersion($dependency); + + if ($composerVersion === null) { + return; + } + + $dependency[DependencyTree::META_COMPOSER_VERSION] = $composerVersion; } /** * @param array $dependency * - * @return bool|string + * @return string|bool|null */ private function getComposerVersion(array $dependency) { @@ -53,5 +66,7 @@ private function getComposerVersion(array $dependency) return $installedPackage[static::VERSION]; } } + + return null; } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTree.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTree.php index 0172c5a4..3df5ab0f 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTree.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTree.php @@ -11,37 +11,104 @@ class DependencyTree extends AbstractDependencyTree { + /** + * @var string + */ public const META_FINDER = 'finder'; + + /** + * @var string + */ public const META_FILE = 'file'; + + /** + * @var string + */ public const META_IN_TEST = 'in test'; + + /** + * @var string + */ public const META_IS_OPTIONAL = 'is optional'; + + /** + * @var string + */ public const META_ORGANIZATION = 'organization'; + + /** + * @var string + */ public const META_CLASS_NAME = 'class name'; + + /** + * @var string + */ public const META_FOREIGN_BUNDLE = 'foreign bundle'; + + /** + * @var string + */ public const META_FOREIGN_BUNDLE_IS_ENGINE = 'foreign bundle is engine'; + + /** + * @var string + */ public const META_FOREIGN_LAYER = 'foreign layer'; + + /** + * @var string + */ public const META_FOREIGN_CLASS_NAME = 'foreign class name'; + + /** + * @var string + */ public const META_FOREIGN_IS_EXTERNAL = 'foreign is external'; + + /** + * @var string + */ public const META_APPLICATION = 'application'; + + /** + * @var string + */ public const META_MODULE = 'bundle'; + + /** + * @var string + */ public const META_MODULE_IS_ENGINE = 'is engine'; + + /** + * @var string + */ public const META_LAYER = 'layer'; + + /** + * @var string + */ public const META_COMPOSER_NAME = 'composer name'; + + /** + * @var string + */ public const META_COMPOSER_VERSION = 'composer version'; /** * @var \Spryker\Zed\Development\Business\DependencyTree\FileInfoExtractor */ - private $fileInfoExtractor; + protected $fileInfoExtractor; /** - * @var array + * @var array */ - private $engineBundles; + protected $engineBundles; /** * @param \Spryker\Zed\Development\Business\DependencyTree\FileInfoExtractor $fileInfoExtractor - * @param array $engineBundles + * @param array $engineBundles */ public function __construct(FileInfoExtractor $fileInfoExtractor, array $engineBundles) { @@ -90,7 +157,7 @@ public function addDependency(SplFileInfo $fileInfo, $to, array $dependency = [] */ private function isEngineBundle($bundle) { - return (in_array($bundle, $this->engineBundles)); + return (in_array($bundle, $this->engineBundles, true)); } /** diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeBuilder.php index 76e13637..4afe84bd 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeBuilder.php @@ -15,22 +15,22 @@ class DependencyTreeBuilder implements DependencyTreeBuilderInterface /** * @var \Spryker\Zed\Development\Business\DependencyTree\Finder\FinderInterface */ - private $finder; + protected $finder; /** * @var \Spryker\Zed\Development\Business\DependencyTree\AbstractDependencyTree */ - private $dependencyTree; + protected $dependencyTree; /** * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyTreeWriter\DependencyTreeWriterInterface */ - private $writer; + protected $writer; /** - * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyFinder\AbstractDependencyFinder[] + * @var array<\Spryker\Zed\Development\Business\DependencyTree\DependencyFinder\AbstractDependencyFinder> */ - private $dependencyChecker = []; + protected $dependencyChecker = []; /** * @param \Spryker\Zed\Development\Business\DependencyTree\Finder\FinderInterface $finder diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeReader/JsonDependencyTreeReader.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeReader/JsonDependencyTreeReader.php index c1a38976..2e1ba2b6 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeReader/JsonDependencyTreeReader.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeReader/JsonDependencyTreeReader.php @@ -14,7 +14,7 @@ class JsonDependencyTreeReader implements DependencyTreeReaderInterface /** * @var string */ - private $pathToJson; + protected $pathToJson; /** * @param string $pathToJson @@ -35,6 +35,9 @@ public function read() throw new RuntimeException('You need to run "vendor/bin/console dev:dependency:build-tree" before being able to use the dependency tree.'); } - return json_decode(file_get_contents($this->pathToJson), true); + /** @var string $json */ + $json = file_get_contents($this->pathToJson); + + return json_decode($json, true); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeWriter/JsonDependencyTreeWriter.php b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeWriter/JsonDependencyTreeWriter.php index 8e4c5b01..dba5757a 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeWriter/JsonDependencyTreeWriter.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/DependencyTreeWriter/JsonDependencyTreeWriter.php @@ -14,7 +14,7 @@ class JsonDependencyTreeWriter implements DependencyTreeWriterInterface /** * @var string */ - private $pathToFile; + protected $pathToFile; /** * @param string $pathToFile @@ -32,6 +32,8 @@ public function __construct($pathToFile) public function write(array $dependencyTree) { $filesystem = new Filesystem(); - $filesystem->dumpFile($this->pathToFile, json_encode($dependencyTree, JSON_PRETTY_PRINT)); + /** @var string $content */ + $content = json_encode($dependencyTree, JSON_PRETTY_PRINT); + $filesystem->dumpFile($this->pathToFile, $content); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/FileInfoExtractor.php b/src/Spryker/Zed/Development/Business/DependencyTree/FileInfoExtractor.php index 240cc414..8181d5ff 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/FileInfoExtractor.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/FileInfoExtractor.php @@ -8,11 +8,14 @@ namespace Spryker\Zed\Development\Business\DependencyTree; use Exception; +use Laminas\Filter\Word\CamelCaseToDash; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\Word\CamelCaseToDash; class FileInfoExtractor { + /** + * @var string + */ public const LAYER = 'Default'; /** @@ -52,7 +55,7 @@ public function getLayerNameFromFileInfo(SplFileInfo $fileInfo) return 'tests'; } $layer = $classNameParts[3]; - if (in_array($layer, ['Business', 'Communication', 'Persistence'])) { + if (in_array($layer, ['Business', 'Communication', 'Persistence'], true)) { return $layer; } @@ -78,8 +81,10 @@ public function getOrganizationFromFile(SplFileInfo $fileInfo) { $classNameParts = $this->getClassNameParts($fileInfo); $filter = new CamelCaseToDash(); + /** @var string $camelCasedClassName */ + $camelCasedClassName = $filter->filter($classNameParts[0]); - return strtolower($filter->filter($classNameParts[0])); + return strtolower($camelCasedClassName); } /** @@ -102,6 +107,7 @@ private function getClassNameParts(SplFileInfo $fileInfo) if (array_search('_support', $pathParts)) { return ['Spryker', 'tests', $pathParts[$testsDirectoryPosition - 1], '_support']; } + return array_slice($pathParts, $testsDirectoryPosition + 2); } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder.php index ca0b0673..3aeeecbb 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder.php @@ -14,40 +14,40 @@ class Finder /** * @var string */ - private $bundleDirectory; + protected $moduleDirectory; /** * @var string */ - private $application; + protected $application; /** * @var string */ - private $bundle; + protected $module; /** * @var string */ - private $layer; + protected $layer; /** * @var string */ - private $name; + protected $name; /** - * @param string $bundleDirectory + * @param string $moduleDirectory * @param string $application - * @param string $bundle + * @param string $module * @param string $layer * @param string $name */ - public function __construct($bundleDirectory, $application = '*', $bundle = '*', $layer = '*', $name = '*.php') + public function __construct($moduleDirectory, $application = '*', $module = '*', $layer = '*', $name = '*.php') { - $this->bundleDirectory = $bundleDirectory; + $this->moduleDirectory = $moduleDirectory; $this->application = $application; - $this->bundle = $bundle; + $this->module = $module; $this->layer = $layer; $this->name = $name; } @@ -59,7 +59,7 @@ public function getFiles() { $directories = $this->getDirectories(); foreach ($directories as $key => $directory) { - if (!glob($directory)) { + if (!glob($directory, GLOB_NOSORT)) { unset($directories[$key]); } } @@ -69,6 +69,7 @@ public function getFiles() } $finder = new SymfonyFinder(); + /** @phpstan-var array $directories */ $finder->files()->in($directories); if ($this->name !== null) { @@ -89,7 +90,7 @@ private function getDirectories() $this->getYvesDirectories(), $this->getClientDirectories(), $this->getSharedDirectories(), - $this->getServiceDirectories() + $this->getServiceDirectories(), )); return $directories; @@ -111,9 +112,9 @@ private function getZedDirectories() } return [ - $this->bundleDirectory . '/' . $this->bundle . '/src/Spryker/Zed/' . $this->bundle . '/' . $layer, - $this->bundleDirectory . '/' . $this->bundle . '/tests/_support/', - $this->bundleDirectory . '/' . $this->bundle . '/tests/SprykerTest/', + $this->moduleDirectory . '/' . $this->module . '/src/Spryker/Zed/' . $this->module . '/' . $layer, + $this->moduleDirectory . '/' . $this->module . '/tests/_support/', + $this->moduleDirectory . '/' . $this->module . '/tests/SprykerTest/', ]; } @@ -123,9 +124,9 @@ private function getZedDirectories() private function getServiceDirectories() { return [ - $this->bundleDirectory . '/' . $this->bundle . '/src/Spryker/Service/' . $this->bundle, - $this->bundleDirectory . '/' . $this->bundle . '/tests/_support/', - $this->bundleDirectory . '/' . $this->bundle . '/tests/SprykerTest/', + $this->moduleDirectory . '/' . $this->module . '/src/Spryker/Service/' . $this->module, + $this->moduleDirectory . '/' . $this->module . '/tests/_support/', + $this->moduleDirectory . '/' . $this->module . '/tests/SprykerTest/', ]; } @@ -135,9 +136,9 @@ private function getServiceDirectories() private function getYvesDirectories() { return [ - $this->bundleDirectory . '/' . $this->bundle . '/src/Spryker/Yves/' . $this->bundle, - $this->bundleDirectory . '/' . $this->bundle . '/tests/_support/', - $this->bundleDirectory . '/' . $this->bundle . '/tests/SprykerTest/', + $this->moduleDirectory . '/' . $this->module . '/src/Spryker/Yves/' . $this->module, + $this->moduleDirectory . '/' . $this->module . '/tests/_support/', + $this->moduleDirectory . '/' . $this->module . '/tests/SprykerTest/', ]; } @@ -147,9 +148,9 @@ private function getYvesDirectories() private function getClientDirectories() { return [ - $this->bundleDirectory . '/' . $this->bundle . '/src/Spryker/Client/' . $this->bundle, - $this->bundleDirectory . '/' . $this->bundle . '/tests/_support/', - $this->bundleDirectory . '/' . $this->bundle . '/tests/SprykerTest/', + $this->moduleDirectory . '/' . $this->module . '/src/Spryker/Client/' . $this->module, + $this->moduleDirectory . '/' . $this->module . '/tests/_support/', + $this->moduleDirectory . '/' . $this->module . '/tests/SprykerTest/', ]; } @@ -159,9 +160,9 @@ private function getClientDirectories() private function getSharedDirectories() { return [ - $this->bundleDirectory . '/' . $this->bundle . '/src/Spryker/Shared/' . $this->bundle . '/', - $this->bundleDirectory . '/' . $this->bundle . '/tests/_support/', - $this->bundleDirectory . '/' . $this->bundle . '/tests/SprykerTest/', + $this->moduleDirectory . '/' . $this->module . '/src/Spryker/Shared/' . $this->module . '/', + $this->moduleDirectory . '/' . $this->module . '/tests/_support/', + $this->moduleDirectory . '/' . $this->module . '/tests/SprykerTest/', ]; } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FileFinder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FileFinder.php index 35838491..da8c7114 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FileFinder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FileFinder.php @@ -28,24 +28,30 @@ public function __construct(PathBuilderInterface $pathBuilder) /** * @param string $module * - * @return \Symfony\Component\Finder\SplFileInfo[] + * @return array<\Symfony\Component\Finder\SplFileInfo> */ public function find(string $module): array { $directories = $this->pathBuilder->buildPaths($module); $directories = array_filter($directories, function (string $directory) { - return glob($directory); + return glob($directory, GLOB_NOSORT); }); if (count($directories) === 0) { return []; } - $finder = new Finder(); - $finder->files()->in($directories); + $res = []; + foreach ($directories as $directory) { + $finder = new Finder(); + $finder->files()->ignoreVCSIgnored(true)->in($directory); - $finder->name('*.php'); + $finder->name('*.php'); + $res = array_merge($res, iterator_to_array($finder)); - return iterator_to_array($finder); + unset($finder); + } + + return $res; } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderComposite.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderComposite.php index 80a6b10b..1164bc11 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderComposite.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderComposite.php @@ -10,7 +10,7 @@ class FinderComposite implements FinderCompositeInterface { /** - * @var \Spryker\Zed\Development\Business\DependencyTree\Finder\FinderInterface[] + * @var array<\Spryker\Zed\Development\Business\DependencyTree\Finder\FinderInterface> */ protected $finder = []; diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderInterface.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderInterface.php index bee6b691..d30e72c8 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderInterface.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/FinderInterface.php @@ -12,7 +12,7 @@ interface FinderInterface /** * @param string $module * - * @return \Symfony\Component\Finder\SplFileInfo[] + * @return array<\Symfony\Component\Finder\SplFileInfo> */ public function find(string $module): array; } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/AbstractPathBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/AbstractPathBuilder.php index bd8821b8..8470937f 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/AbstractPathBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/AbstractPathBuilder.php @@ -7,15 +7,21 @@ namespace Spryker\Zed\Development\Business\DependencyTree\Finder\PathBuilder; +use Laminas\Filter\FilterChain; +use Laminas\Filter\StringToLower; +use Laminas\Filter\Word\CamelCaseToDash; use Spryker\Zed\Development\DevelopmentConfig; -use Zend\Filter\FilterChain; -use Zend\Filter\StringToLower; -use Zend\Filter\Word\CamelCaseToDash; class AbstractPathBuilder { + /** + * @var string + */ protected const ORGANIZATION = ''; + /** + * @var array + */ protected const LOOKUP_NAMESPACES = []; /** @@ -53,7 +59,7 @@ public function buildPaths(string $module): array } /** - * @param string[] $pathComponents + * @param array $pathComponents * * @return string */ diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerEcoPathBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerEcoPathBuilder.php index bac04e80..5ed92633 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerEcoPathBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerEcoPathBuilder.php @@ -9,8 +9,14 @@ class SprykerEcoPathBuilder extends AbstractPathBuilder implements PathBuilderInterface { + /** + * @var string + */ protected const ORGANIZATION = 'SprykerEco'; + /** + * @var array + */ protected const LOOKUP_NAMESPACES = [ 'src' => 'SprykerEco', 'tests' => 'SprykerEcoTest', diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerMerchantPortalPathBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerMerchantPortalPathBuilder.php index 3e70474b..751ff5fe 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerMerchantPortalPathBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerMerchantPortalPathBuilder.php @@ -9,8 +9,14 @@ class SprykerMerchantPortalPathBuilder extends AbstractPathBuilder implements PathBuilderInterface { + /** + * @var string + */ protected const ORGANIZATION = 'SprykerMerchantPortal'; + /** + * @var array + */ protected const LOOKUP_NAMESPACES = [ 'src' => 'SprykerMerchantPortal', 'tests' => 'SprykerMerchantPortalTest', diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerPathBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerPathBuilder.php index 6e29473c..c7f3d129 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerPathBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerPathBuilder.php @@ -9,8 +9,14 @@ class SprykerPathBuilder extends AbstractPathBuilder implements PathBuilderInterface { + /** + * @var string + */ protected const ORGANIZATION = 'Spryker'; + /** + * @var array + */ protected const LOOKUP_NAMESPACES = [ 'src' => 'Spryker', 'tests' => 'SprykerTest', diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerSdkPathBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerSdkPathBuilder.php index 9411dc0e..aea073a5 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerSdkPathBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerSdkPathBuilder.php @@ -9,8 +9,14 @@ class SprykerSdkPathBuilder extends AbstractPathBuilder implements PathBuilderInterface { + /** + * @var string + */ protected const ORGANIZATION = 'SprykerSdk'; + /** + * @var array + */ protected const LOOKUP_NAMESPACES = [ 'src' => 'SprykerSdk', 'tests' => 'SprykerSdkTest', diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerShopPathBuilder.php b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerShopPathBuilder.php index e3ca42c2..bc39cfe4 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerShopPathBuilder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/Finder/PathBuilder/SprykerShopPathBuilder.php @@ -9,8 +9,14 @@ class SprykerShopPathBuilder extends AbstractPathBuilder implements PathBuilderInterface { + /** + * @var string + */ protected const ORGANIZATION = 'SprykerShop'; + /** + * @var array + */ protected const LOOKUP_NAMESPACES = [ 'src' => 'SprykerShop', 'tests' => 'SprykerShopTest', diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationChecker/DependencyViolationChecker.php b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationChecker/DependencyViolationChecker.php index eef6d40c..84fe2b13 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationChecker/DependencyViolationChecker.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationChecker/DependencyViolationChecker.php @@ -20,30 +20,33 @@ class DependencyViolationChecker implements DependencyViolationCheckerInterface /** * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyTreeReader\DependencyTreeReaderInterface */ - private $treeReader; + protected $treeReader; /** * @var \Spryker\Zed\Development\Business\DependencyTree\ViolationFinder\ViolationFinderInterface */ - private $violationFinder; + protected $violationFinder; /** * @var \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface */ - private $dependencyFilter; + protected $dependencyFilter; /** * @var array */ - private $dependencyViolations = []; + protected $dependencyViolations = []; /** * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyTreeReader\DependencyTreeReaderInterface $treeReader * @param \Spryker\Zed\Development\Business\DependencyTree\ViolationFinder\ViolationFinderInterface $violationFinder * @param \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\DependencyFilterInterface $dependencyFilter */ - public function __construct(DependencyTreeReaderInterface $treeReader, ViolationFinderInterface $violationFinder, DependencyFilterInterface $dependencyFilter) - { + public function __construct( + DependencyTreeReaderInterface $treeReader, + ViolationFinderInterface $violationFinder, + DependencyFilterInterface $dependencyFilter + ) { $this->treeReader = $treeReader; $this->violationFinder = $violationFinder; $this->dependencyFilter = $dependencyFilter; diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/BundleUsesConnector.php b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/BundleUsesConnector.php index 7d8f8319..58a270e6 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/BundleUsesConnector.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/BundleUsesConnector.php @@ -21,6 +21,6 @@ class BundleUsesConnector implements ViolationFinderInterface */ public function isViolation(array $dependency) { - return (preg_match('/Connector/', $dependency[DependencyTree::META_FOREIGN_BUNDLE])); + return (bool)preg_match('/Connector/', $dependency[DependencyTree::META_FOREIGN_BUNDLE]); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignConstants.php b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignConstants.php index 36830742..ed20333f 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignConstants.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignConstants.php @@ -18,6 +18,6 @@ class UseForeignConstants implements ViolationFinderInterface */ public function isViolation(array $dependency) { - return (preg_match('/Spryker\\\\Shared\\\\(.*?)Constants/', $dependency[DependencyTree::META_FOREIGN_CLASS_NAME])); + return (bool)preg_match('/Spryker\\\\Shared\\\\(.*?)Constants/', $dependency[DependencyTree::META_FOREIGN_CLASS_NAME]); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignException.php b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignException.php index 6875fb84..b03a0959 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignException.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/UseForeignException.php @@ -18,6 +18,6 @@ class UseForeignException implements ViolationFinderInterface */ public function isViolation(array $dependency) { - return (preg_match('/Exception/', $dependency[DependencyTree::META_FOREIGN_CLASS_NAME])); + return (bool)preg_match('/Exception/', $dependency[DependencyTree::META_FOREIGN_CLASS_NAME]); } } diff --git a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/ViolationFinder.php b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/ViolationFinder.php index 25e92d0f..85e70091 100644 --- a/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/ViolationFinder.php +++ b/src/Spryker/Zed/Development/Business/DependencyTree/ViolationFinder/ViolationFinder.php @@ -10,9 +10,9 @@ class ViolationFinder implements ViolationFinderInterface { /** - * @var \Spryker\Zed\Development\Business\DependencyTree\ViolationFinder\ViolationFinderInterface[] + * @var array<\Spryker\Zed\Development\Business\DependencyTree\ViolationFinder\ViolationFinderInterface> */ - private $violationFinder; + protected $violationFinder; /** * @param \Spryker\Zed\Development\Business\DependencyTree\ViolationFinder\ViolationFinderInterface $violationFinder @@ -41,6 +41,7 @@ public function isViolation(array $dependency) } $isViolation = true; + break; } diff --git a/src/Spryker/Zed/Development/Business/DevelopmentBusinessFactory.php b/src/Spryker/Zed/Development/Business/DevelopmentBusinessFactory.php index abcaa74f..fefc6f1c 100644 --- a/src/Spryker/Zed/Development/Business/DevelopmentBusinessFactory.php +++ b/src/Spryker/Zed/Development/Business/DevelopmentBusinessFactory.php @@ -7,12 +7,18 @@ namespace Spryker\Zed\Development\Business; +use Laminas\Config\Reader\Xml; +use Laminas\Filter\Word\CamelCaseToDash; use Nette\DI\Config\Loader; use Spryker\Zed\Development\Business\ArchitectureSniffer\AllBundleFinder; +use Spryker\Zed\Development\Business\ArchitectureSniffer\AllModuleFinder; +use Spryker\Zed\Development\Business\ArchitectureSniffer\AllModuleFinderInterface; use Spryker\Zed\Development\Business\ArchitectureSniffer\ArchitectureSniffer; use Spryker\Zed\Development\Business\ArchitectureSniffer\ArchitectureSnifferInterface; use Spryker\Zed\Development\Business\CodeBuilder\Bridge\BridgeBuilder; use Spryker\Zed\Development\Business\CodeBuilder\Module\ModuleBuilder; +use Spryker\Zed\Development\Business\Codeception\Argument\Builder\CodeceptionArgumentsBuilder; +use Spryker\Zed\Development\Business\Codeception\Argument\Builder\CodeceptionArgumentsBuilderInterface; use Spryker\Zed\Development\Business\CodeStyleSniffer\CodeStyleSniffer; use Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfiguration; use Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationInterface; @@ -25,28 +31,37 @@ use Spryker\Zed\Development\Business\Composer\ComposerJsonInterface; use Spryker\Zed\Development\Business\Composer\ComposerJsonUpdater; use Spryker\Zed\Development\Business\Composer\ComposerJsonUpdaterInterface; +use Spryker\Zed\Development\Business\Composer\ComposerNameFinder; +use Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface; +use Spryker\Zed\Development\Business\Composer\Updater\AllowPluginsUpdater; use Spryker\Zed\Development\Business\Composer\Updater\AutoloadUpdater; use Spryker\Zed\Development\Business\Composer\Updater\BranchAliasUpdater; use Spryker\Zed\Development\Business\Composer\Updater\ComposerUpdaterComposite; use Spryker\Zed\Development\Business\Composer\Updater\DescriptionUpdater; use Spryker\Zed\Development\Business\Composer\Updater\LicenseUpdater; +use Spryker\Zed\Development\Business\Composer\Updater\RequireDevUpdater; use Spryker\Zed\Development\Business\Composer\Updater\RequireUpdater; +use Spryker\Zed\Development\Business\Composer\Updater\ScriptsUpdater; use Spryker\Zed\Development\Business\Composer\Updater\StabilityUpdater; use Spryker\Zed\Development\Business\Composer\Updater\TypeUpdater; +use Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonPackageNameValidator; use Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonUnboundRequireConstraintValidator; use Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonValidatorComposite; use Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonValidatorInterface; +use Spryker\Zed\Development\Business\Dependency\ComposerParser\ExternalDependencyParser; +use Spryker\Zed\Development\Business\Dependency\ComposerParser\ExternalDependencyParserInterface; use Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainer; use Spryker\Zed\Development\Business\Dependency\DependencyContainer\DependencyContainerInterface; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\BehaviorDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\CodeceptionDependencyFinder; -use Spryker\Zed\Development\Business\Dependency\DependencyFinder\ComposerScriptDependencyFinder; +use Spryker\Zed\Development\Business\Dependency\DependencyFinder\ComposerDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderComposite; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\ExtensionDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\ExternalDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\InternalDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\LocatorDependencyFinder; +use Spryker\Zed\Development\Business\Dependency\DependencyFinder\MappedDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\ModuleAnnotationDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\PersistenceDependencyFinder; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\SprykerSdkDependencyFinder; @@ -59,6 +74,8 @@ use Spryker\Zed\Development\Business\Dependency\DependencyFinder\TwigDependencyFinder\TwigDependencyFinderInterface; use Spryker\Zed\Development\Business\Dependency\DependencyFinder\TwigDependencyFinder\ViewFunctionDependencyFinder; use Spryker\Zed\Development\Business\Dependency\Manager; +use Spryker\Zed\Development\Business\Dependency\Mapper\DependencyModuleMapper; +use Spryker\Zed\Development\Business\Dependency\Mapper\DependencyModuleMapperInterface; use Spryker\Zed\Development\Business\Dependency\ModuleDependencyParser; use Spryker\Zed\Development\Business\Dependency\ModuleDependencyParserInterface; use Spryker\Zed\Development\Business\Dependency\ModuleParser\UseStatementParser; @@ -69,6 +86,7 @@ use Spryker\Zed\Development\Business\Dependency\TwigFileFinder\TwigFileFinderInterface; use Spryker\Zed\Development\Business\Dependency\Validator\DependencyValidator; use Spryker\Zed\Development\Business\Dependency\Validator\DependencyValidatorInterface; +use Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleAmbiguousModuleName; use Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleComposite; use Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleDevelopmentOnlyDependency; use Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInRequireAndRequireDev; @@ -138,6 +156,12 @@ use Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\BundleGenerator; use Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\BundleMethodGenerator; use Spryker\Zed\Development\Business\IdeAutoCompletion\IdeAutoCompletionWriter; +use Spryker\Zed\Development\Business\IdeAutoCompletion\IdeAutoCompletionWriterInterface; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\DirectoryRemover; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\DirectoryRemoverInterface; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\GeneratedFileFinder; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\GeneratedFileFinderInterface; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\TargetDirectoryResolver; use Spryker\Zed\Development\Business\Integration\DependencyProviderUsedPluginFinder; use Spryker\Zed\Development\Business\Integration\DependencyProviderUsedPluginFinderInterface; use Spryker\Zed\Development\Business\Module\ModuleFileFinder\ModuleFileFinder; @@ -151,6 +175,7 @@ use Spryker\Zed\Development\Business\Module\PathBuilder\PathBuilderComposite; use Spryker\Zed\Development\Business\Module\PathBuilder\PathBuilderInterface; use Spryker\Zed\Development\Business\Module\PathBuilder\SprykerEcoModulePathBuilder; +use Spryker\Zed\Development\Business\Module\PathBuilder\SprykerFeatureModulePathBuilder; use Spryker\Zed\Development\Business\Module\PathBuilder\SprykerMerchantPortalModulePathBuilder; use Spryker\Zed\Development\Business\Module\PathBuilder\SprykerModulePathBuilder; use Spryker\Zed\Development\Business\Module\PathBuilder\SprykerSdkModulePathBuilder; @@ -158,6 +183,8 @@ use Spryker\Zed\Development\Business\Module\PathBuilder\SprykerStandaloneModulePathBuilder; use Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinder; use Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizer; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface; use Spryker\Zed\Development\Business\Package\PackageFinder\PackageFinder; use Spryker\Zed\Development\Business\Package\PackageFinder\PackageFinderInterface; use Spryker\Zed\Development\Business\PhpMd\PhpMdRunner; @@ -165,21 +192,25 @@ use Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileFinderInterface; use Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileManager; use Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileManagerInterface; +use Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileSaver; +use Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileSaverInterface; use Spryker\Zed\Development\Business\Phpstan\PhpstanRunner; use Spryker\Zed\Development\Business\Propel\PropelAbstractClassValidator; use Spryker\Zed\Development\Business\Propel\PropelAbstractClassValidatorInterface; +use Spryker\Zed\Development\Business\Resolver\CodeStylePathResolver; +use Spryker\Zed\Development\Business\Resolver\PathResolverInterface; use Spryker\Zed\Development\Business\SnifferConfiguration\Builder\ArchitectureSnifferConfigurationBuilder; use Spryker\Zed\Development\Business\SnifferConfiguration\Builder\SnifferConfigurationBuilderInterface; use Spryker\Zed\Development\Business\SnifferConfiguration\ConfigurationReader\ConfigurationReader; use Spryker\Zed\Development\Business\SnifferConfiguration\ConfigurationReader\ConfigurationReaderInterface; use Spryker\Zed\Development\Business\Stability\StabilityCalculator; +use Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface; use Spryker\Zed\Development\DevelopmentDependencyProvider; use Spryker\Zed\Kernel\Business\AbstractBusinessFactory; use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder as SymfonyFinder; use Symfony\Component\Yaml\Parser; -use Zend\Config\Reader\Xml; -use Zend\Filter\Word\CamelCaseToDash; /** * @method \Spryker\Zed\Development\DevelopmentConfig getConfig() @@ -193,7 +224,7 @@ public function createCodeStyleSniffer(): CodeStyleSniffer { return new CodeStyleSniffer( $this->getConfig(), - $this->createCodeStyleSnifferConfigurationLoader() + $this->createCodeStylePathResolver(), ); } @@ -204,7 +235,7 @@ public function createCodeStyleSnifferConfigurationLoader(): CodeStyleSnifferCon { return new CodeStyleSnifferConfigurationLoader( $this->createConfigurationReader(), - $this->createCodeStyleSnifferConfiguration() + $this->createCodeStyleSnifferConfiguration(), ); } @@ -222,8 +253,10 @@ public function createCodeStyleSnifferConfiguration(): CodeStyleSnifferConfigura public function createCodeTester() { return new CodeTester( - $this->getConfig()->getPathToRoot(), - $this->getConfig()->getPathToCore() + $this->getModuleFinderFacade(), + $this->createConfigArgumentCollectionBuilder(), + $this->getConfig(), + $this->createNameNormalizer(), ); } @@ -233,7 +266,8 @@ public function createCodeTester() public function createPhpMdRunner() { return new PhpMdRunner( - $this->getConfig() + $this->getConfig(), + $this->createNameNormalizer(), ); } @@ -245,7 +279,8 @@ public function createPhpstanRunner() return new PhpstanRunner( $this->getConfig(), $this->createPhpstanConfigFileFinder(), - $this->createPhpstanConfigFileManager() + $this->createPhpstanConfigFileManager(), + $this->createNameNormalizer(), ); } @@ -263,7 +298,7 @@ public function createBridgeBuilder() public function createModuleBuilder() { return new ModuleBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -283,7 +318,7 @@ public function createModuleDependencyParser(): ModuleDependencyParserInterface return new ModuleDependencyParser( $this->createModuleFileFinder(), $this->createDependencyContainer(), - $this->createDependencyFinder() + $this->createDependencyFinder(), ); } @@ -303,6 +338,7 @@ public function createPathBuilder(): PathBuilderInterface return new PathBuilderComposite([ $this->createSprykerStandaloneModuleFilePathBuilder(), $this->createSprykerModuleFilePathBuilder(), + $this->createSprykerFeatureModuleFilePathBuilder(), $this->createSprykerShopModuleFilePathBuilder(), $this->createSprykerEcoModuleFilePathBuilder(), $this->createSprykerSdkModulePathBuilder(), @@ -324,7 +360,17 @@ public function createSprykerStandaloneModuleFilePathBuilder(): PathBuilderInter public function createSprykerModuleFilePathBuilder(): PathBuilderInterface { return new SprykerModulePathBuilder( - $this->getConfig() + $this->getConfig(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\Module\PathBuilder\PathBuilderInterface + */ + public function createSprykerFeatureModuleFilePathBuilder(): PathBuilderInterface + { + return new SprykerFeatureModulePathBuilder( + $this->getConfig(), ); } @@ -334,7 +380,7 @@ public function createSprykerModuleFilePathBuilder(): PathBuilderInterface public function createSprykerShopModuleFilePathBuilder(): PathBuilderInterface { return new SprykerShopModulePathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -344,7 +390,7 @@ public function createSprykerShopModuleFilePathBuilder(): PathBuilderInterface public function createSprykerEcoModuleFilePathBuilder(): PathBuilderInterface { return new SprykerEcoModulePathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -354,7 +400,7 @@ public function createSprykerEcoModuleFilePathBuilder(): PathBuilderInterface public function createSprykerSdkModulePathBuilder(): PathBuilderInterface { return new SprykerSdkModulePathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -383,13 +429,14 @@ public function createDependencyFinder(): DependencyFinderInterface $this->createSprykerSdkDependencyFinder(), $this->createInternalDependencyFinder(), $this->createExternalDependencyFinder(), + $this->createMappedDependencyFinder(), $this->createExtensionDependencyFinder(), $this->createLocatorDependencyFinder(), $this->createPersistenceDependencyFinder(), $this->createBehaviorDependencyFinder(), $this->createTwigDependencyFinder(), + $this->createComposerDependencyFinder(), $this->createTravisDependencyFinder(), - $this->createComposerScriptDependencyFinder(), $this->createCodeceptionDependencyFinder(), $this->createModuleAnnotationDependencyFinder(), ]); @@ -402,7 +449,7 @@ public function createSprykerSdkDependencyFinder(): DependencyFinderInterface { return new SprykerSdkDependencyFinder( $this->createUseStatementParser(), - $this->getConfig() + $this->getConfig(), ); } @@ -413,7 +460,7 @@ public function createInternalDependencyFinder(): DependencyFinderInterface { return new InternalDependencyFinder( $this->createUseStatementParser(), - $this->getConfig() + $this->getConfig(), ); } @@ -424,17 +471,34 @@ public function createExternalDependencyFinder(): DependencyFinderInterface { return new ExternalDependencyFinder( $this->createUseStatementParser(), - $this->getConfig() + $this->createExternalDependencyParser(), + $this->getConfig(), ); } + /** + * @return \Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface + */ + public function createMappedDependencyFinder(): DependencyFinderInterface + { + return new MappedDependencyFinder($this->getConfig()); + } + + /** + * @return \Spryker\Zed\Development\Business\Dependency\ComposerParser\ExternalDependencyParserInterface + */ + public function createExternalDependencyParser(): ExternalDependencyParserInterface + { + return new ExternalDependencyParser($this->getConfig()); + } + /** * @return \Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface */ public function createExtensionDependencyFinder(): DependencyFinderInterface { return new ExtensionDependencyFinder( - $this->createModuleFinder() + $this->getModuleFinderFacade(), ); } @@ -452,7 +516,7 @@ public function createLocatorDependencyFinder(): DependencyFinderInterface public function createPersistenceDependencyFinder(): DependencyFinderInterface { return new PersistenceDependencyFinder( - $this->createPropelSchemaParser() + $this->createPropelSchemaParser(), ); } @@ -462,7 +526,7 @@ public function createPersistenceDependencyFinder(): DependencyFinderInterface public function createBehaviorDependencyFinder(): DependencyFinderInterface { return new BehaviorDependencyFinder( - $this->createModuleFinder() + $this->getModuleFinderFacade(), ); } @@ -472,7 +536,7 @@ public function createBehaviorDependencyFinder(): DependencyFinderInterface public function createPropelSchemaParser(): PropelSchemaParserInterface { return new PropelSchemaParser( - $this->getConfig() + $this->getConfig(), ); } @@ -490,24 +554,24 @@ public function createUseStatementParser(): UseStatementParserInterface public function createTwigDependencyFinder(): DependencyFinderInterface { return new TwigDependencyFinder( - $this->getTwigDependencyFinder() + $this->getTwigDependencyFinder(), ); } /** * @return \Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface */ - public function createTravisDependencyFinder(): DependencyFinderInterface + public function createComposerDependencyFinder(): DependencyFinderInterface { - return new TravisDependencyFinder(); + return new ComposerDependencyFinder(); } /** * @return \Spryker\Zed\Development\Business\Dependency\DependencyFinder\DependencyFinderInterface */ - public function createComposerScriptDependencyFinder(): DependencyFinderInterface + public function createTravisDependencyFinder(): DependencyFinderInterface { - return new ComposerScriptDependencyFinder(); + return new TravisDependencyFinder(); } /** @@ -535,7 +599,7 @@ public function createTwigFinder(): TwigFileFinderInterface } /** - * @return \Spryker\Zed\Development\Business\Dependency\DependencyFinder\TwigDependencyFinder\TwigDependencyFinderInterface[] + * @return array<\Spryker\Zed\Development\Business\Dependency\DependencyFinder\TwigDependencyFinder\TwigDependencyFinderInterface> */ public function getTwigDependencyFinder(): array { @@ -595,10 +659,19 @@ public function createDependencyManager() { return new Manager( $this->createModuleDependencyParser(), - $this->getConfig() + $this->getConfig(), + $this->createDependencyModuleMapper(), ); } + /** + * @return \Spryker\Zed\Development\Business\Dependency\Mapper\DependencyModuleMapperInterface + */ + protected function createDependencyModuleMapper(): DependencyModuleMapperInterface + { + return new DependencyModuleMapper(); + } + /** * @return \Spryker\Zed\Development\Business\Stability\StabilityCalculatorInterface */ @@ -642,7 +715,7 @@ protected function createDependencyTreeFinder() protected function createSprykerFinder() { $finder = new FileFinder( - $this->createSprykerPathBuilder() + $this->createSprykerPathBuilder(), ); return $finder; @@ -654,7 +727,7 @@ protected function createSprykerFinder() protected function createSprykerMerchantPortalFinder() { $finder = new FileFinder( - $this->createSprykerMerchantPortalPathBuilder() + $this->createSprykerMerchantPortalPathBuilder(), ); return $finder; @@ -666,7 +739,7 @@ protected function createSprykerMerchantPortalFinder() protected function createSprykerPathBuilder() { return new SprykerPathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -676,7 +749,7 @@ protected function createSprykerPathBuilder() protected function createSprykerMerchantPortalPathBuilder() { return new SprykerMerchantPortalPathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -688,7 +761,8 @@ public function createDependencyValidator(): DependencyValidatorInterface return new DependencyValidator( $this->createModuleDependencyParser(), $this->createComposerDependencyParser(), - $this->createDependencyValidationRules() + $this->createDependencyValidationRules(), + $this->createComposerNameFinder(), ); } @@ -698,6 +772,7 @@ public function createDependencyValidator(): DependencyValidatorInterface public function createDependencyValidationRules(): ValidationRuleInterface { return new ValidationRuleComposite([ + $this->createValidationRuleAmbiguousModuleName(), $this->createValidationRuleDevelopmentOnlyDependency(), $this->createValidationRuleInSourceNotInRequire(), $this->createValidationRuleNotInSourceButInRequire(), @@ -711,6 +786,14 @@ public function createDependencyValidationRules(): ValidationRuleInterface ]); } + /** + * @return \Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface + */ + public function createValidationRuleAmbiguousModuleName(): ValidationRuleInterface + { + return new ValidationRuleAmbiguousModuleName(); + } + /** * @return \Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface */ @@ -792,6 +875,8 @@ public function createValidationRuleInRequireAndRequireDev(): ValidationRuleInte } /** + * @deprecated Use `spryker/module-finder` instead. + * * @return \Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface */ public function createModuleFinder(): ModuleFinderInterface @@ -800,6 +885,8 @@ public function createModuleFinder(): ModuleFinderInterface } /** + * @deprecated Use `spryker/module-finder` instead. + * * @return \Spryker\Zed\Development\Business\Module\ModuleMatcher\ModuleMatcherInterface */ public function createModuleMatcher(): ModuleMatcherInterface @@ -813,7 +900,7 @@ public function createModuleMatcher(): ModuleMatcherInterface public function createComposerJsonValidator(): ComposerJsonInterface { return new ComposerJson( - $this->createComposerJsonValidatorComposite() + $this->createComposerJsonValidatorComposite(), ); } @@ -823,6 +910,7 @@ public function createComposerJsonValidator(): ComposerJsonInterface public function createComposerJsonValidatorComposite(): ComposerJsonValidatorInterface { return new ComposerJsonValidatorComposite([ + $this->createComposerJsonPackageNameValidator(), $this->createComposerJsonUnboundRequireConstraintValidator(), ]); } @@ -835,14 +923,22 @@ public function createComposerJsonUnboundRequireConstraintValidator(): ComposerJ return new ComposerJsonUnboundRequireConstraintValidator(); } + /** + * @return \Spryker\Zed\Development\Business\Composer\Validator\ComposerJsonValidatorInterface + */ + public function createComposerJsonPackageNameValidator(): ComposerJsonValidatorInterface + { + return new ComposerJsonPackageNameValidator(); + } + /** * @return \Spryker\Zed\Development\Business\Integration\DependencyProviderUsedPluginFinderInterface */ public function createDependencyProviderUsedPluginFinder(): DependencyProviderUsedPluginFinderInterface { return new DependencyProviderUsedPluginFinder( - $this->createProjectModuleFinder(), - $this->getConfig() + $this->getModuleFinderFacade(), + $this->getConfig(), ); } @@ -851,7 +947,7 @@ public function createDependencyProviderUsedPluginFinder(): DependencyProviderUs */ public function createModuleOverview(): ModuleOverviewInterface { - return new ModuleOverview($this->createProjectModuleFinder(), $this->createModuleFinder()); + return new ModuleOverview($this->getModuleFinderFacade()); } /** @@ -860,7 +956,7 @@ public function createModuleOverview(): ModuleOverviewInterface protected function createSdkFinder() { $finder = new FileFinder( - $this->createSprykerSdkPathBuilder() + $this->createSprykerSdkPathBuilder(), ); return $finder; @@ -872,7 +968,7 @@ protected function createSdkFinder() protected function createSprykerSdkPathBuilder() { return new SprykerSdkPathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -890,7 +986,7 @@ public function createPropelAbstractValidator(): PropelAbstractClassValidatorInt protected function createEcoFinder() { $finder = new FileFinder( - $this->createSprykerEcoPathBuilder() + $this->createSprykerEcoPathBuilder(), ); return $finder; @@ -902,7 +998,7 @@ protected function createEcoFinder() protected function createSprykerEcoPathBuilder() { return new SprykerEcoPathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -912,7 +1008,7 @@ protected function createSprykerEcoPathBuilder() protected function createShopFinder() { $finder = new FileFinder( - $this->createSprykerShopPathBuilder() + $this->createSprykerShopPathBuilder(), ); return $finder; @@ -924,7 +1020,7 @@ protected function createShopFinder() protected function createSprykerShopPathBuilder() { return new SprykerShopPathBuilder( - $this->getConfig() + $this->getConfig(), ); } @@ -1038,7 +1134,7 @@ public function createDetailedDependencyGraphBuilder($bundleToView) $dependencyGraphBuilder = new DependencyGraphBuilder( $this->createDetailedGraphBuilder(), - $dependencyTreeFilter->filter($dependencyTreeReader->read()) + $dependencyTreeFilter->filter($dependencyTreeReader->read()), ); return $dependencyGraphBuilder; @@ -1073,7 +1169,7 @@ protected function createDetailedDependencyTreeFilter($bundleToView) /** * @param string $bundleToView - * @param array $excludedBundles + * @param array $excludedBundles * * @return \Spryker\Zed\Development\Business\DependencyTree\DependencyGraph\OutgoingGraphBuilder */ @@ -1084,7 +1180,7 @@ public function createOutgoingDependencyGraphBuilder($bundleToView, array $exclu $this->getGraph(), $this->createModuleDependencyParser(), $this->createDependencyManager(), - $excludedBundles + $excludedBundles, ); return $outgoingDependencyGraphBuilder; @@ -1111,7 +1207,7 @@ public function createSimpleDependencyGraphBuilder($showEngineBundle, $bundleToV $dependencyGraphBuilder = new DependencyGraphBuilder( $this->createSimpleGraphBuilder(), - $dependencyTreeFilter->filter($dependencyTreeReader->read()) + $dependencyTreeFilter->filter($dependencyTreeReader->read()), ); return $dependencyGraphBuilder; @@ -1166,7 +1262,9 @@ public function createExternalDependencyTree($bundleToView = null) $treeFilter->addFilter($this->createDependencyTreeBundleToViewFilter($bundleToView)); } - $composerLock = json_decode(file_get_contents(APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'composer.lock'), true); + /** @var string $composerContent */ + $composerContent = file_get_contents(APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'composer.lock'); + $composerLock = json_decode($composerContent, true); $packageVersionHydrator = new PackageVersionHydrator(array_merge($composerLock['packages'], $composerLock['packages-dev'])); $treeHydrator = new DependencyHydrator(); @@ -1189,7 +1287,7 @@ public function createExternalDependencyGraphBuilder($bundleToView) { $dependencyGraphBuilder = new DependencyGraphBuilder( $this->createExternalGraphBuilder(), - $this->createExternalDependencyTree($bundleToView) + $this->createExternalDependencyTree($bundleToView), ); return $dependencyGraphBuilder; @@ -1211,7 +1309,7 @@ public function createAdjacencyMatrixBuilder() $adjacencyMatrixBuilder = new AdjacencyMatrixBuilder( $this->createDependencyManager()->collectAllModules(), $this->createDependencyTreeReader(), - $this->createAdjacencyMatrixDependencyTreeFilter() + $this->createAdjacencyMatrixDependencyTreeFilter(), ); return $adjacencyMatrixBuilder; @@ -1239,7 +1337,7 @@ public function createDependencyViolationChecker() return new DependencyViolationChecker( $this->createDependencyTreeReader(), $this->createViolationFinder(), - $this->createDependencyViolationFilter() + $this->createDependencyViolationFilter(), ); } @@ -1340,7 +1438,7 @@ protected function createDependencyTreeConstantsToForeignConstantsFilter() protected function createDependencyTreeForeignEngineBundleFilter() { return new ForeignEngineBundleFilter( - $this->getConfig()->getPathToBundleConfig() + $this->getConfig()->getPathToBundleConfig(), ); } @@ -1350,7 +1448,7 @@ protected function createDependencyTreeForeignEngineBundleFilter() protected function createDependencyTreeEngineBundleFilter() { return new EngineBundleFilter( - $this->getConfig()->getPathToBundleConfig() + $this->getConfig()->getPathToBundleConfig(), ); } @@ -1360,7 +1458,7 @@ protected function createDependencyTreeEngineBundleFilter() protected function createDependencyTreeInvalidForeignBundleFilter() { return new InvalidForeignBundleFilter( - $this->createDependencyManager()->collectAllModules() + $this->createDependencyManager()->collectAllModules(), ); } @@ -1389,12 +1487,15 @@ protected function createDependencyTreeFilter() } /** - * @return array + * @return array */ public function getEngineBundleList() { - $bundleList = json_decode(file_get_contents($this->getConfig()->getPathToBundleConfig()), true); + /** @var string $bundleContent */ + $bundleContent = file_get_contents($this->getConfig()->getPathToBundleConfig()); + $bundleList = json_decode($bundleContent, true); + /** @phpstan-var array */ return array_keys($bundleList); } @@ -1405,7 +1506,7 @@ public function createComposerJsonUpdater(): ComposerJsonUpdaterInterface { return new ComposerJsonUpdater( $this->createComposerJsonFinder(), - $this->createComposerJsonUpdaterComposite() + $this->createComposerJsonUpdaterComposite(), ); } @@ -1415,7 +1516,7 @@ public function createComposerJsonUpdater(): ComposerJsonUpdaterInterface protected function createComposerJsonFinder(): ComposerJsonFinderInterface { $composerJsonFinder = new ComposerJsonFinder( - $this->createFinder() + $this->createFinder(), ); return $composerJsonFinder; @@ -1432,9 +1533,12 @@ protected function createComposerJsonUpdaterComposite() ->addUpdater($this->createComposerJsonDescriptionUpdater()) ->addUpdater($this->createComposerJsonLicenseUpdater()) ->addUpdater($this->createComposerJsonRequireUpdater()) + ->addUpdater($this->createComposerJsonRequireDevUpdater()) ->addUpdater($this->createComposerJsonStabilityUpdater()) ->addUpdater($this->createComposerJsonAutoloadUpdater()) - ->addUpdater($this->createComposerJsonBranchAliasUpdater()); + ->addUpdater($this->createComposerJsonScriptsUpdater()) + ->addUpdater($this->createComposerJsonBranchAliasUpdater()) + ->addUpdater($this->createComposerJsonAllowPluginsUpdater()); return $updaterComposite; } @@ -1455,6 +1559,14 @@ protected function createComposerJsonTypeUpdater() return new TypeUpdater(); } + /** + * @return \Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface + */ + protected function createComposerJsonScriptsUpdater() + { + return new ScriptsUpdater(); + } + /** * @return \Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface */ @@ -1479,6 +1591,14 @@ protected function createComposerJsonRequireUpdater() return new RequireUpdater(); } + /** + * @return \Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface + */ + protected function createComposerJsonRequireDevUpdater() + { + return new RequireDevUpdater(); + } + /** * @return \Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface */ @@ -1503,6 +1623,14 @@ protected function createComposerJsonBranchAliasUpdater() return new BranchAliasUpdater(); } + /** + * @return \Spryker\Zed\Development\Business\Composer\Updater\UpdaterInterface + */ + protected function createComposerJsonAllowPluginsUpdater() + { + return new AllowPluginsUpdater(); + } + /** * @return \Spryker\Zed\Development\Business\DependencyTree\DependencyFilter\TreeFilterCompositeInterface */ @@ -1521,7 +1649,9 @@ protected function createComposerJsonRequireUpdaterTreeFilter() */ public function createComposerDependencyParser() { - return new ComposerDependencyParser(); + return new ComposerDependencyParser( + $this->createComposerNameFinder(), + ); } /** @@ -1531,7 +1661,7 @@ public function createYvesIdeAutoCompletionWriter() { return $this->createIdeAutoCompletionWriter( $this->createYvesIdeAutoCompletionBundleBuilder(), - $this->getConfig()->getYvesIdeAutoCompletionOptions() + $this->getConfig()->getYvesIdeAutoCompletionOptions(), ); } @@ -1542,7 +1672,19 @@ protected function createYvesIdeAutoCompletionBundleBuilder() { return new IdeAutoCompletionBundleBuilder( $this->getYvesIdeAutoCompletionMethodBuilderStack(), - $this->getConfig()->getYvesIdeAutoCompletionOptions() + $this->getConfig()->getYvesIdeAutoCompletionOptions(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\DirectoryRemoverInterface + */ + public function createIdeAutoCompletionDirectoryRemover(): DirectoryRemoverInterface + { + return new DirectoryRemover( + $this->createTargetDirectoryResolver(), + $this->getFilesystem(), + $this->createGeneratedFileFinder(), ); } @@ -1553,7 +1695,7 @@ public function createZedIdeAutoCompletionWriter() { return $this->createIdeAutoCompletionWriter( $this->createZedIdeAutoCompletionBundleBuilder(), - $this->getConfig()->getZedIdeAutoCompletionOptions() + $this->getConfig()->getZedIdeAutoCompletionOptions(), ); } @@ -1564,7 +1706,7 @@ protected function createZedIdeAutoCompletionBundleBuilder() { return new IdeAutoCompletionBundleBuilder( $this->getZedIdeAutoCompletionMethodBuilderStack(), - $this->getConfig()->getZedIdeAutoCompletionOptions() + $this->getConfig()->getZedIdeAutoCompletionOptions(), ); } @@ -1575,21 +1717,51 @@ protected function createGlueIdeAutoCompletionBundleBuilder() { return new IdeAutoCompletionBundleBuilder( $this->createGlueAutoCompletionMethodBuilderStack(), - $this->getConfig()->getGlueIdeAutoCompletionOptions() + $this->getConfig()->getGlueIdeAutoCompletionOptions(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\BundleBuilderInterface + */ + protected function createGlueBackendIdeAutoCompletionBundleBuilder(): BundleBuilderInterface + { + return new IdeAutoCompletionBundleBuilder( + $this->createGlueBackendAutoCompletionMethodBuilderStack(), + $this->getConfig()->getGlueBackendIdeAutoCompletionOptions(), ); } /** * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\IdeAutoCompletionWriterInterface */ - public function createGlueIdeAutoCompletionWriter() + public function createGlueIdeAutoCompletionWriter(): IdeAutoCompletionWriterInterface { return $this->createIdeAutoCompletionWriter( $this->createGlueIdeAutoCompletionBundleBuilder(), - $this->getConfig()->getGlueIdeAutoCompletionOptions() + $this->getConfig()->getGlueIdeAutoCompletionOptions(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\IdeAutoCompletionWriterInterface + */ + public function createGlueBackendIdeAutoCompletionWriter(): IdeAutoCompletionWriterInterface + { + return $this->createIdeAutoCompletionWriter( + $this->createGlueBackendIdeAutoCompletionBundleBuilder(), + $this->getConfig()->getGlueBackendIdeAutoCompletionOptions(), ); } + /** + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\GeneratedFileFinderInterface + */ + public function createGeneratedFileFinder(): GeneratedFileFinderInterface + { + return new GeneratedFileFinder($this->getFinder()); + } + /** * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\IdeAutoCompletionWriterInterface */ @@ -1597,7 +1769,7 @@ public function createClientIdeAutoCompletionWriter() { return $this->createIdeAutoCompletionWriter( $this->createClientIdeAutoCompletionBundleBuilder(), - $this->getConfig()->getClientIdeAutoCompletionOptions() + $this->getConfig()->getClientIdeAutoCompletionOptions(), ); } @@ -1608,7 +1780,7 @@ protected function createClientIdeAutoCompletionBundleBuilder() { return new IdeAutoCompletionBundleBuilder( $this->getClientIdeAutoCompletionMethodBuilderStack(), - $this->getConfig()->getClientIdeAutoCompletionOptions() + $this->getConfig()->getClientIdeAutoCompletionOptions(), ); } @@ -1619,7 +1791,7 @@ public function createServiceIdeAutoCompletionWriter() { return $this->createIdeAutoCompletionWriter( $this->createServiceIdeAutoCompletionBundleBuilder(), - $this->getConfig()->getServiceIdeAutoCompletionOptions() + $this->getConfig()->getServiceIdeAutoCompletionOptions(), ); } @@ -1630,12 +1802,12 @@ protected function createServiceIdeAutoCompletionBundleBuilder() { return new IdeAutoCompletionBundleBuilder( $this->getServiceIdeAutoCompletionMethodBuilderStack(), - $this->getConfig()->getServiceIdeAutoCompletionOptions() + $this->getConfig()->getServiceIdeAutoCompletionOptions(), ); } /** - * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface[] + * @return array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> */ protected function getYvesIdeAutoCompletionMethodBuilderStack() { @@ -1646,7 +1818,7 @@ protected function getYvesIdeAutoCompletionMethodBuilderStack() } /** - * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface[] + * @return array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> */ protected function getZedIdeAutoCompletionMethodBuilderStack() { @@ -1659,9 +1831,9 @@ protected function getZedIdeAutoCompletionMethodBuilderStack() } /** - * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface[] + * @return array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> */ - protected function createGlueAutoCompletionMethodBuilderStack() + protected function createGlueAutoCompletionMethodBuilderStack(): array { return [ $this->createIdeAutoCompletionResourceMethodBuild(), @@ -1671,7 +1843,20 @@ protected function createGlueAutoCompletionMethodBuilderStack() } /** - * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface[] + * @return array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> + */ + protected function createGlueBackendAutoCompletionMethodBuilderStack(): array + { + return [ + $this->createIdeAutoCompletionResourceMethodBuild(), + $this->createIdeAutoCompletionClientMethodBuilder(), + $this->createIdeAutoCompletionServiceMethodBuilder(), + $this->createIdeAutoCompletionFacadeMethodBuilder(), + ]; + } + + /** + * @return array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> */ protected function getClientIdeAutoCompletionMethodBuilderStack() { @@ -1682,7 +1867,7 @@ protected function getClientIdeAutoCompletionMethodBuilderStack() } /** - * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface[] + * @return array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> */ protected function getServiceIdeAutoCompletionMethodBuilderStack() { @@ -1733,7 +1918,7 @@ protected function createIdeAutoCompletionResourceMethodBuild() /** * @param \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\BundleBuilderInterface $bundleBuilder - * @param array $options + * @param array $options * * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\IdeAutoCompletionWriterInterface */ @@ -1741,7 +1926,7 @@ protected function createIdeAutoCompletionWriter(BundleBuilderInterface $bundleB { return new IdeAutoCompletionWriter( $this->getIdeAutoCompletionGeneratorStack($options), - $this->createIdeAutoCompletionBundleFinder($bundleBuilder) + $this->createIdeAutoCompletionBundleFinder($bundleBuilder), ); } @@ -1753,16 +1938,16 @@ protected function createIdeAutoCompletionWriter(BundleBuilderInterface $bundleB protected function createIdeAutoCompletionBundleFinder(BundleBuilderInterface $bundleBuilder) { return new BundleFinder( - $this->getProvidedDependency(DevelopmentDependencyProvider::FINDER), + $this->getFinder(), $bundleBuilder, - $this->getConfig()->getIdeAutoCompletionSourceDirectoryGlobPatterns() + $this->getConfig()->getIdeAutoCompletionSourceDirectoryGlobPatterns(), ); } /** - * @param array $options + * @param array $options * - * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface[] + * @return array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface> */ protected function getIdeAutoCompletionGeneratorStack(array $options) { @@ -1773,7 +1958,7 @@ protected function getIdeAutoCompletionGeneratorStack(array $options) } /** - * @param array $options + * @param array $options * * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface */ @@ -1791,7 +1976,7 @@ protected function createFileWriter(): FileWriterInterface } /** - * @param array $options + * @param array $options * * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface */ @@ -1841,12 +2026,12 @@ public function createArchitectureSniffer(): ArchitectureSnifferInterface return new ArchitectureSniffer( $xml, $command, - $this->createArchitectureSnifferConfigurationBuilder() + $this->createArchitectureSnifferConfigurationBuilder(), ); } /** - * @return \Zend\Config\Reader\ReaderInterface + * @return \Laminas\Config\Reader\ReaderInterface */ protected function createXmlReader() { @@ -1854,6 +2039,8 @@ protected function createXmlReader() } /** + * @deprecated Use {@link createAllModuleFinder()} instead. + * * @return \Spryker\Zed\Development\Business\ArchitectureSniffer\AllBundleFinderInterface */ public function createArchitectureBundleFinder() @@ -1862,12 +2049,24 @@ public function createArchitectureBundleFinder() $this->createFinder(), $this->createCamelCaseToDashFilter(), $this->getConfig()->getProjectNamespaces(), - $this->getConfig()->getCoreNamespaces() + $this->getConfig()->getCoreNamespaces(), ); } /** - * @return \Zend\Filter\FilterInterface + * @return \Spryker\Zed\Development\Business\ArchitectureSniffer\AllModuleFinderInterface + */ + public function createAllModuleFinder(): AllModuleFinderInterface + { + return new AllModuleFinder( + $this->createFinder(), + $this->getConfig(), + $this->createCamelCaseToDashFilter(), + ); + } + + /** + * @return \Laminas\Filter\FilterInterface */ protected function createCamelCaseToDashFilter() { @@ -1875,6 +2074,8 @@ protected function createCamelCaseToDashFilter() } /** + * @deprecated Use `spryker/module-finder` instead. + * * @return \Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface */ public function createProjectModuleFinder(): ProjectModuleFinderInterface @@ -1883,6 +2084,8 @@ public function createProjectModuleFinder(): ProjectModuleFinderInterface } /** + * @deprecated Use `spryker/module-finder` instead. + * * @return \Spryker\Zed\Development\Business\Package\PackageFinder\PackageFinderInterface */ public function createPackageFinder(): PackageFinderInterface @@ -1904,7 +2107,7 @@ public function createYamlParser(): Parser public function createConfigurationReader(): ConfigurationReaderInterface { return new ConfigurationReader( - $this->createYamlParser() + $this->createYamlParser(), ); } @@ -1915,7 +2118,7 @@ public function createArchitectureSnifferConfigurationBuilder(): SnifferConfigur { return new ArchitectureSnifferConfigurationBuilder( $this->createConfigurationReader(), - $this->getConfig()->getArchitectureSnifferDefaultPriority() + $this->getConfig()->getArchitectureSnifferDefaultPriority(), ); } @@ -1932,7 +2135,12 @@ protected function createPhpstanConfigFileFinder(): PhpstanConfigFileFinderInter */ protected function createPhpstanConfigFileManager(): PhpstanConfigFileManagerInterface { - return new PhpstanConfigFileManager($this->getFilesystem(), $this->getConfig(), $this->getConfigLoader()); + return new PhpstanConfigFileManager( + $this->getFilesystem(), + $this->getConfig(), + $this->getConfigLoader(), + $this->createPhpstanConfigFileSaver(), + ); } /** @@ -1950,4 +2158,86 @@ protected function getConfigLoader(): Loader { return $this->getProvidedDependency(DevelopmentDependencyProvider::CONFIG_LOADER); } + + /** + * @return \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface + */ + public function getModuleFinderFacade(): DevelopmentToModuleFinderFacadeInterface + { + return $this->getProvidedDependency(DevelopmentDependencyProvider::FACADE_MODULE_FINDER); + } + + /** + * @return \Symfony\Component\Finder\Finder + */ + protected function getFinder(): Finder + { + return $this->getProvidedDependency(DevelopmentDependencyProvider::FINDER); + } + + /** + * @return \Spryker\Zed\Development\Business\Codeception\Argument\Builder\CodeceptionArgumentsBuilderInterface + */ + public function createConfigArgumentCollectionBuilder(): CodeceptionArgumentsBuilderInterface + { + return new CodeceptionArgumentsBuilder( + $this->getConfig()->getDefaultInclusiveGroups(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\Composer\ComposerNameFinderInterface + */ + public function createComposerNameFinder(): ComposerNameFinderInterface + { + return new ComposerNameFinder($this->getModuleFinderFacade()); + } + + /** + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Remover\TargetDirectoryResolver + */ + protected function createTargetDirectoryResolver(): TargetDirectoryResolver + { + return new TargetDirectoryResolver( + $this->getConfig(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileSaverInterface + */ + public function createPhpstanConfigFileSaver(): PhpstanConfigFileSaverInterface + { + return new PhpstanConfigFileSaver( + $this->getPhpstanFileAdapters(), + ); + } + + /** + * @return array + */ + public function getPhpstanFileAdapters(): array + { + return $this->getProvidedDependency(DevelopmentDependencyProvider::PHPSTAN_ADAPTERS); + } + + /** + * @return \Spryker\Zed\Development\Business\Resolver\PathResolverInterface + */ + public function createCodeStylePathResolver(): PathResolverInterface + { + return new CodeStylePathResolver( + $this->getConfig(), + $this->createNameNormalizer(), + $this->createCodeStyleSnifferConfigurationLoader(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface + */ + public function createNameNormalizer(): NameNormalizerInterface + { + return new NameNormalizer(); + } } diff --git a/src/Spryker/Zed/Development/Business/DevelopmentFacade.php b/src/Spryker/Zed/Development/Business/DevelopmentFacade.php index b3cc2bb0..105751ac 100644 --- a/src/Spryker/Zed/Development/Business/DevelopmentFacade.php +++ b/src/Spryker/Zed/Development/Business/DevelopmentFacade.php @@ -15,6 +15,7 @@ use Generated\Shared\Transfer\DependencyValidationResponseTransfer; use Generated\Shared\Transfer\ModuleFilterTransfer; use Generated\Shared\Transfer\ModuleTransfer; +use Spryker\Zed\Development\Business\IdeAutoCompletion\IdeAutoCompletionOptionConstants; use Spryker\Zed\Kernel\Business\AbstractFacade; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -25,10 +26,12 @@ class DevelopmentFacade extends AbstractFacade implements DevelopmentFacadeInterface { /** + * {@inheritDoc} + * * @api * * @param string|null $module - * @param array $options + * @param array $options * * @return int Exit code */ @@ -38,23 +41,42 @@ public function checkCodeStyle($module = null, array $options = []) } /** + * {@inheritDoc} + * * @api * * @param string|null $module - * @param array $options + * @param array $options * - * @return void + * @return int + */ + public function runTest(?string $module, array $options = []): int + { + return $this->getFactory()->createCodeTester()->runTest($module, $options); + } + + /** + * {@inheritDoc} + * + * @api + * + * @param string|null $module + * @param array $options + * + * @return int */ - public function runTest($module, array $options = []) + public function runFixtures(?string $module, array $options = []): int { - $this->getFactory()->createCodeTester()->runTest($module, $options); + return $this->getFactory()->createCodeTester()->runFixtures($module, $options); } /** + * {@inheritDoc} + * * @api * * @param string|null $module - * @param array $options + * @param array $options * * @return int Exit code */ @@ -64,11 +86,15 @@ public function runPhpMd($module, array $options = []) } /** + * {@inheritDoc} + * * @api * + * @internal + * * @param string $module * @param string $toModule - * @param array $methods + * @param array $methods * * @return void */ @@ -78,12 +104,14 @@ public function createBridge($module, $toModule, array $methods) } /** + * {@inheritDoc} + * * @api * * @deprecated Use Spryk tool instead. * * @param string $module - * @param array $options + * @param array $options * * @return void */ @@ -93,11 +121,13 @@ public function createModule($module, array $options) } /** + * {@inheritDoc} + * * @api * * @internal * - * @param \Generated\Shared\Transfer\ModuleTransfer[] $modules + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $modules * @param bool $dryRun * * @return array @@ -108,9 +138,10 @@ public function updateComposerJsonInModules(array $modules, $dryRun = false): ar } /** - * {@inheritdoc} + * {@inheritDoc} * * @api + * * @internal * * @param \Generated\Shared\Transfer\ModuleTransfer $moduleTransfer @@ -124,9 +155,10 @@ public function showOutgoingDependenciesForModule(ModuleTransfer $moduleTransfer } /** - * {@inheritdoc} + * {@inheritDoc} * * @api + * * @internal * * @param string $moduleName @@ -139,8 +171,12 @@ public function showIncomingDependenciesForModule($moduleName) } /** + * {@inheritDoc} + * * @api * + * @deprecated Use {@link getModules()} instead. + * * @return array */ public function getAllModules() @@ -149,9 +185,11 @@ public function getAllModules() } /** + * {@inheritDoc} + * * @api * - * @deprecated Use `getAllModules()` instead. + * @deprecated Use {@link getAllModules()} instead. * * @return array */ @@ -161,6 +199,8 @@ public function getAllBundles() } /** + * {@inheritDoc} + * * @api * * @param string $module @@ -173,6 +213,8 @@ public function buildDependencyTree(string $module) } /** + * {@inheritDoc} + * * @api * * @return array @@ -183,10 +225,12 @@ public function calculateStability() } /** + * {@inheritDoc} + * * @api * * @param string $moduleToView - * @param array $excludedModules + * @param array $excludedModules * @param bool $showIncomingDependencies * * @return string @@ -197,6 +241,8 @@ public function drawOutgoingDependencyTreeGraph($moduleToView, array $excludedMo } /** + * {@inheritDoc} + * * @api * * @param string|bool $moduleToView @@ -209,6 +255,8 @@ public function drawDetailedDependencyTreeGraph($moduleToView) } /** + * {@inheritDoc} + * * @api * * @param bool $showEngineModule @@ -222,6 +270,8 @@ public function drawSimpleDependencyTreeGraph($showEngineModule, $moduleToView) } /** + * {@inheritDoc} + * * @api * * @param string $moduleToView @@ -234,6 +284,8 @@ public function drawExternalDependencyTreeGraph($moduleToView) } /** + * {@inheritDoc} + * * @api * * @return array @@ -244,6 +296,8 @@ public function getAdjacencyMatrixData() } /** + * {@inheritDoc} + * * @api * * @deprecated This method is not used anymore. @@ -256,9 +310,11 @@ public function getDependencyViolations() } /** + * {@inheritDoc} + * * @api * - * @return array + * @return array */ public function getEngineModuleList() { @@ -266,6 +322,8 @@ public function getEngineModuleList() } /** + * {@inheritDoc} + * * @api * * @deprecated This method is not used anymore. @@ -278,6 +336,8 @@ public function getExternalDependencyTree() } /** + * {@inheritDoc} + * * @api * * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $dependencyCollectionTransfer @@ -290,6 +350,8 @@ public function getComposerDependencyComparison(DependencyCollectionTransfer $de } /** + * {@inheritDoc} + * * @api * * @return void @@ -300,6 +362,20 @@ public function generateYvesIdeAutoCompletion() } /** + * {@inheritDoc} + * + * @api + * + * @return void + */ + public function removeYvesIdeAutoCompletion(): void + { + $this->getFactory()->createIdeAutoCompletionDirectoryRemover()->remove(IdeAutoCompletionOptionConstants::YVES); + } + + /** + * {@inheritDoc} + * * @api * * @return void @@ -310,6 +386,20 @@ public function generateZedIdeAutoCompletion() } /** + * {@inheritDoc} + * + * @api + * + * @return void + */ + public function removeZedIdeAutoCompletion(): void + { + $this->getFactory()->createIdeAutoCompletionDirectoryRemover()->remove(IdeAutoCompletionOptionConstants::ZED); + } + + /** + * {@inheritDoc} + * * @api * * @return void @@ -320,6 +410,20 @@ public function generateClientIdeAutoCompletion() } /** + * {@inheritDoc} + * + * @api + * + * @return void + */ + public function removeClientIdeAutoCompletion(): void + { + $this->getFactory()->createIdeAutoCompletionDirectoryRemover()->remove(IdeAutoCompletionOptionConstants::CLIENT); + } + + /** + * {@inheritDoc} + * * @api * * @return void @@ -330,6 +434,20 @@ public function generateServiceIdeAutoCompletion() } /** + * {@inheritDoc} + * + * @api + * + * @return void + */ + public function removeServiceIdeAutoCompletion(): void + { + $this->getFactory()->createIdeAutoCompletionDirectoryRemover()->remove(IdeAutoCompletionOptionConstants::SERVICE); + } + + /** + * {@inheritDoc} + * * @api * * @return void @@ -340,12 +458,24 @@ public function generateGlueIdeAutoCompletion() } /** - * {@inheritdoc} + * {@inheritDoc} + * + * @api + * + * @return void + */ + public function removeGlueIdeAutoCompletion(): void + { + $this->getFactory()->createIdeAutoCompletionDirectoryRemover()->remove(IdeAutoCompletionOptionConstants::GLUE); + } + + /** + * {@inheritDoc} * * @api * * @param string $directory - * @param array $options + * @param array $options * * @return array */ @@ -355,7 +485,7 @@ public function runArchitectureSniffer($directory, array $options = []) } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * @@ -363,13 +493,15 @@ public function runArchitectureSniffer($directory, array $options = []) */ public function listAllModules() { - return $this->getFactory()->createArchitectureBundleFinder()->find(); + return $this->getFactory()->createAllModuleFinder()->find(); } /** + * {@inheritDoc} + * * @api * - * @deprecated Use `listAllModules` instead. + * @deprecated Use {@link listAllModules()} instead. * * @return array */ @@ -379,7 +511,7 @@ public function listAllBundles() } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * @@ -391,7 +523,7 @@ public function getArchitectureRules() } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * @@ -406,7 +538,7 @@ public function runPhpstan(InputInterface $input, OutputInterface $output) } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * @@ -421,7 +553,7 @@ public function runPropelAbstractValidation(OutputInterface $output, ?string $mo } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * @@ -435,7 +567,7 @@ public function validateModuleDependencies(DependencyValidationRequestTransfer $ } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * @@ -449,7 +581,7 @@ public function validateComposerJson(ComposerJsonValidationRequestTransfer $comp } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * @@ -463,56 +595,94 @@ public function getInProjectDependencyProviderUsedPlugins(?ModuleFilterTransfer } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return array + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ public function getProjectModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array { - return $this->getFactory()->createProjectModuleFinder()->getProjectModules($moduleFilterTransfer); + return $this->getFactory()->getModuleFinderFacade()->getProjectModules($moduleFilterTransfer); } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array { - return $this->getFactory()->createModuleFinder()->getModules($moduleFilterTransfer); + return $this->getFactory()->getModuleFinderFacade()->getModules($moduleFilterTransfer); } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * * @internal * - * @return \Generated\Shared\Transfer\PackageTransfer[] + * @return array<\Generated\Shared\Transfer\PackageTransfer> */ public function getPackages(): array { - return $this->getFactory()->createPackageFinder()->getPackages(); + return $this->getFactory()->getModuleFinderFacade()->getPackages(); } /** - * {@inheritdoc} + * {@inheritDoc} * * @api * - * @return \Generated\Shared\Transfer\ModuleOverviewTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleOverviewTransfer> */ public function getModuleOverview(): array { return $this->getFactory()->createModuleOverview()->getOverview(); } + + /** + * {@inheritDoc} + * + * @api + * + * @param string $moduleName + * + * @return string|null + */ + public function findComposerNameByModuleName(string $moduleName): ?string + { + return $this->getFactory()->createComposerNameFinder()->findComposerNameByModuleName($moduleName); + } + + /** + * {@inheritDoc} + * + * @api + * + * @return void + */ + public function generateGlueBackendIdeAutoCompletion(): void + { + $this->getFactory()->createGlueBackendIdeAutoCompletionWriter()->writeCompletionFiles(); + } + + /** + * {@inheritDoc} + * + * @api + * + * @return void + */ + public function removeGlueBackendIdeAutoCompletion(): void + { + $this->getFactory()->createIdeAutoCompletionDirectoryRemover()->remove(IdeAutoCompletionOptionConstants::GLUE_BACKEND); + } } diff --git a/src/Spryker/Zed/Development/Business/DevelopmentFacadeInterface.php b/src/Spryker/Zed/Development/Business/DevelopmentFacadeInterface.php index 369ae6af..7f683484 100644 --- a/src/Spryker/Zed/Development/Business/DevelopmentFacadeInterface.php +++ b/src/Spryker/Zed/Development/Business/DevelopmentFacadeInterface.php @@ -21,51 +21,88 @@ interface DevelopmentFacadeInterface { /** + * Specification: + * - Runs vendor/bin/phpcs or vendor/bin/phpcbf as wrapper for easier use. + * - If no module is given, it will run over the whole repository. + * * @api * * @param string|null $module - * @param array $options + * @param array $options * * @return int Exit code */ public function checkCodeStyle($module = null, array $options = []); /** + * Specification: + * - Runs `vendor/bin/codecept run` as wrapper for easier use. + * - If no (core) module is given, it will run on project level. + * * @api * * @param string|null $module - * @param array $options + * @param array $options * - * @return void + * @return int */ - public function runTest($module, array $options = []); + public function runTest(?string $module, array $options = []): int; /** + * Specification: + * - Runs `vendor/bin/codecept fixtures` as wrapper for easier use. + * - If no (core) module is given, it will run on project level. + * - If options contains "initialize", it will also run vendor/bin/codecept build. + * + * @api + * + * @param string|null $module + * @param array $options + * + * @return int + */ + public function runFixtures(?string $module, array $options = []): int; + + /** + * Specification: + * - Runs the vendor/bin/phpmd as wrapper for easier use. + * - If no (core) module is given, it will run on project level. + * * @api * * @param string|null $module - * @param array $options + * @param array $options * * @return int Exit code */ public function runPhpMd($module, array $options = []); /** + * Specification: + * - TODO: Add method specification. + * * @api * + * @internal + * * @param string $module * @param string $toModule - * @param array $methods + * @param array $methods * * @return void */ public function createBridge($module, $toModule, array $methods); /** + * Specification: + * - TODO: Add method specification. + * * @api * + * @deprecated Use Spryk tool instead. + * * @param string $module - * @param array $options + * @param array $options * * @return void */ @@ -87,6 +124,9 @@ public function createModule($module, array $options); public function showOutgoingDependenciesForModule(ModuleTransfer $moduleTransfer, ?string $dependencyType = null): DependencyCollectionTransfer; /** + * Specification: + * - TODO: Add method specification. + * * @api * * @internal @@ -98,18 +138,24 @@ public function showOutgoingDependenciesForModule(ModuleTransfer $moduleTransfer public function showIncomingDependenciesForModule($moduleName); /** + * Specification: + * - TODO: Add method specification. + * * @api * - * @deprecated Please use `getModules()` instead. + * @deprecated Use {@link getModules()} instead. * * @return array */ public function getAllModules(); /** + * Specification: + * - TODO: Add method specification. + * * @api * - * @deprecated Use `getAllModules()` instead. + * @deprecated Use {@link getAllModules()} instead. * * @return array */ @@ -139,10 +185,13 @@ public function buildDependencyTree(string $module); public function calculateStability(); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @param string|bool $moduleToView - * @param array $excludedModules + * @param array $excludedModules * @param bool $showIncomingDependencies * * @return string @@ -150,6 +199,9 @@ public function calculateStability(); public function drawOutgoingDependencyTreeGraph($moduleToView, array $excludedModules = [], $showIncomingDependencies = false); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @param string|bool $moduleToView @@ -159,6 +211,9 @@ public function drawOutgoingDependencyTreeGraph($moduleToView, array $excludedMo public function drawDetailedDependencyTreeGraph($moduleToView); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @param bool $showEngineModule @@ -169,6 +224,9 @@ public function drawDetailedDependencyTreeGraph($moduleToView); public function drawSimpleDependencyTreeGraph($showEngineModule, $moduleToView); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @param string $moduleToView @@ -178,6 +236,9 @@ public function drawSimpleDependencyTreeGraph($showEngineModule, $moduleToView); public function drawExternalDependencyTreeGraph($moduleToView); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return array @@ -185,6 +246,9 @@ public function drawExternalDependencyTreeGraph($moduleToView); public function getAdjacencyMatrixData(); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return array @@ -192,18 +256,24 @@ public function getAdjacencyMatrixData(); public function getDependencyViolations(); /** + * Specification: + * - TODO: Add method specification. + * * @api * - * @return array + * @return array */ public function getEngineModuleList(); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @internal * - * @param \Generated\Shared\Transfer\ModuleTransfer[] $modules + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $modules * @param bool $dryRun * * @return array @@ -211,6 +281,9 @@ public function getEngineModuleList(); public function updateComposerJsonInModules(array $modules, $dryRun = false): array; /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return array @@ -218,6 +291,9 @@ public function updateComposerJsonInModules(array $modules, $dryRun = false): ar public function getExternalDependencyTree(); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @param \Generated\Shared\Transfer\DependencyCollectionTransfer $dependencyCollectionTransfer @@ -227,6 +303,9 @@ public function getExternalDependencyTree(); public function getComposerDependencyComparison(DependencyCollectionTransfer $dependencyCollectionTransfer); /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return void @@ -234,6 +313,19 @@ public function getComposerDependencyComparison(DependencyCollectionTransfer $de public function generateYvesIdeAutoCompletion(); /** + * Specification: + * - Removes Yves IDE autocompletion files + * + * @api + * + * @return void + */ + public function removeYvesIdeAutoCompletion(): void; + + /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return void @@ -241,6 +333,19 @@ public function generateYvesIdeAutoCompletion(); public function generateZedIdeAutoCompletion(); /** + * Specification: + * - Removes Zed IDE autocompletion files + * + * @api + * + * @return void + */ + public function removeZedIdeAutoCompletion(): void; + + /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return void @@ -248,6 +353,19 @@ public function generateZedIdeAutoCompletion(); public function generateClientIdeAutoCompletion(); /** + * Specification: + * - Removes Client IDE autocompletion files + * + * @api + * + * @return void + */ + public function removeClientIdeAutoCompletion(): void; + + /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return void @@ -255,6 +373,19 @@ public function generateClientIdeAutoCompletion(); public function generateServiceIdeAutoCompletion(); /** + * Specification: + * - Removes Service IDE autocompletion files + * + * @api + * + * @return void + */ + public function removeServiceIdeAutoCompletion(): void; + + /** + * Specification: + * - TODO: Add method specification. + * * @api * * @return void @@ -262,19 +393,32 @@ public function generateServiceIdeAutoCompletion(); public function generateGlueIdeAutoCompletion(); /** - * Run the architecture sniffer against the given module and returns the violations + * Specification: + * - Removes Glue IDE autocompletion files + * + * @api + * + * @return void + */ + public function removeGlueIdeAutoCompletion(): void; + + /** + * Specification: + * - Run the architecture sniffer against the given module and returns the violations + * - In case the module contains a custom ruleset, it will be used instead of the default one. * * @api * * @param string $directory - * @param array $options + * @param array $options * * @return array */ public function runArchitectureSniffer($directory, array $options = []); /** - * Returns a list of all modules in project and core namespaces + * Specification: + * - Returns a list of all modules in project and core namespaces. * * @api * @@ -283,16 +427,20 @@ public function runArchitectureSniffer($directory, array $options = []); public function listAllModules(); /** + * Specification: + * - TODO: Add method specification. + * * @api * - * @deprecated Use `listAllModules` instead. + * @deprecated Use {@link listAllModules()} instead. * * @return array */ public function listAllBundles(); /** - * Returns all architecture rules + * Specification: + * - Returns all architecture rules * * @api * @@ -373,7 +521,7 @@ public function getInProjectDependencyProviderUsedPlugins(?ModuleFilterTransfer * * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return array + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ public function getProjectModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array; @@ -388,7 +536,7 @@ public function getProjectModules(?ModuleFilterTransfer $moduleFilterTransfer = * * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array; @@ -401,7 +549,7 @@ public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): * * @internal * - * @return \Generated\Shared\Transfer\PackageTransfer[] + * @return array<\Generated\Shared\Transfer\PackageTransfer> */ public function getPackages(): array; @@ -411,7 +559,40 @@ public function getPackages(): array; * * @api * - * @return \Generated\Shared\Transfer\ModuleOverviewTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleOverviewTransfer> */ public function getModuleOverview(): array; + + /** + * Specification: + * - Returns the composer name for a module if module is not ambiguous. + * - Returns null when the module name was found in more than one organization. + * + * @api + * + * @param string $moduleName + * + * @return string|null + */ + public function findComposerNameByModuleName(string $moduleName): ?string; + + /** + * Specification: + * - Add Glue Backend IDE autocompletion files, including autocompletion for Facades + * + * @api + * + * @return void + */ + public function generateGlueBackendIdeAutoCompletion(): void; + + /** + * Specification: + * - Removes Glue IDE autocompletion files + * + * @api + * + * @return void + */ + public function removeGlueBackendIdeAutoCompletion(): void; } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleBuilder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleBuilder.php index 4439421c..8877b3a3 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleBuilder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleBuilder.php @@ -15,7 +15,7 @@ class BundleBuilder implements BundleBuilderInterface { /** - * @var \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface[] + * @var array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> */ protected $bundleMethodBuilders; @@ -25,8 +25,8 @@ class BundleBuilder implements BundleBuilderInterface protected $options; /** - * @param \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface[] $bundleMethodBuilders - * @param array $options + * @param array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\BundleMethodBuilderInterface> $bundleMethodBuilders + * @param array $options */ public function __construct(array $bundleMethodBuilders, array $options) { @@ -63,7 +63,7 @@ protected function getNamespace() return str_replace( IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, $this->options[IdeAutoCompletionOptionConstants::APPLICATION_NAME], - $this->options[IdeAutoCompletionOptionConstants::TARGET_NAMESPACE_PATTERN] + $this->options[IdeAutoCompletionOptionConstants::TARGET_NAMESPACE_PATTERN], ); } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php index d53c4f5b..de9ee6af 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinder.php @@ -26,14 +26,14 @@ class BundleFinder implements BundleFinderInterface protected $bundleBuilder; /** - * @var array + * @var array */ protected $directoryGlobPatterns; /** * @param \Symfony\Component\Finder\Finder $finder * @param \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\BundleBuilderInterface $bundleBuilder - * @param array $directoryGlobPatterns + * @param array $directoryGlobPatterns */ public function __construct(Finder $finder, BundleBuilderInterface $bundleBuilder, array $directoryGlobPatterns) { @@ -43,7 +43,7 @@ public function __construct(Finder $finder, BundleBuilderInterface $bundleBuilde } /** - * @return \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer[] + * @return array<\Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer> */ public function find() { @@ -66,7 +66,7 @@ public function find() /** * @param string $bundleDirectoryGlobPattern * - * @return \Traversable|\Symfony\Component\Finder\SplFileInfo[] + * @return \Traversable<\Symfony\Component\Finder\SplFileInfo> */ protected function getBundleDirectories($bundleDirectoryGlobPattern) { @@ -93,7 +93,7 @@ protected function getFinder() /** * @param \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer $bundleTransfer - * @param \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer[] $bundles + * @param array<\Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer> $bundles * * @return \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer */ @@ -107,7 +107,7 @@ protected function mergeWithPossibleExistingBundle(IdeAutoCompletionBundleTransf $mergedMethodTransferCollection = $this->mergeMethods( $existingBundleTransfer->getMethods(), - $bundleTransfer->getMethods() + $bundleTransfer->getMethods(), ); $bundleTransfer->setMethods($mergedMethodTransferCollection); @@ -115,10 +115,10 @@ protected function mergeWithPossibleExistingBundle(IdeAutoCompletionBundleTransf } /** - * @param \ArrayObject|\Generated\Shared\Transfer\IdeAutoCompletionBundleMethodTransfer[] $existingMethodTransferCollection - * @param \ArrayObject|\Generated\Shared\Transfer\IdeAutoCompletionBundleMethodTransfer[] $methodTransferCollection + * @param \ArrayObject $existingMethodTransferCollection + * @param \ArrayObject $methodTransferCollection * - * @return \ArrayObject|\Generated\Shared\Transfer\IdeAutoCompletionBundleMethodTransfer[] + * @return \ArrayObject */ protected function mergeMethods( ArrayObject $existingMethodTransferCollection, diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinderInterface.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinderInterface.php index d76bdd81..44337578 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/BundleFinderInterface.php @@ -10,7 +10,7 @@ interface BundleFinderInterface { /** - * @return \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer[] + * @return array<\Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer> */ public function find(); } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/AbstractBundleMethodBuilder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/AbstractBundleMethodBuilder.php index 9f44cef9..ae5930be 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/AbstractBundleMethodBuilder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/AbstractBundleMethodBuilder.php @@ -14,6 +14,9 @@ abstract class AbstractBundleMethodBuilder implements BundleMethodBuilderInterface { + /** + * @var string + */ public const FILE_EXTENSION = 'php'; /** @@ -147,7 +150,7 @@ protected function findFileByName($fileName, $searchPath) $filePath = $searchPath . $fileName; if (file_exists($filePath)) { - return new SplFileInfo($filePath, null, null); + return new SplFileInfo($filePath, dirname($filePath), basename($filePath)); } return null; @@ -189,6 +192,6 @@ protected function getFileDirectory(SplFileInfo $file) { $classFileDirectory = str_replace($file->getFilename(), '', $file->getPath()); - return new SplFileInfo($classFileDirectory, null, null); + return new SplFileInfo($classFileDirectory, $file->getRelativePath(), $file->getFilename()); } } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilder.php index 0e9550ed..a8f37b2b 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilder.php @@ -29,7 +29,7 @@ protected function getSearchDirectory(IdeAutoCompletionBundleTransfer $bundleTra return sprintf( '%s%s/', $bundleTransfer->getDirectory(), - $bundleTransfer->getName() + $bundleTransfer->getName(), ); } } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilder.php index 6a73a84d..fee1a46f 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilder.php @@ -29,7 +29,7 @@ protected function getSearchDirectory(IdeAutoCompletionBundleTransfer $bundleTra return sprintf( '%s%s/Business/', $bundleTransfer->getDirectory(), - $bundleTransfer->getName() + $bundleTransfer->getName(), ); } } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilder.php index 70a7af83..4c60e90f 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilder.php @@ -29,7 +29,7 @@ protected function getSearchDirectory(IdeAutoCompletionBundleTransfer $bundleTra return sprintf( '%s%s/Persistence/', $bundleTransfer->getDirectory(), - $bundleTransfer->getName() + $bundleTransfer->getName(), ); } } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ResourceMethodBuilder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ResourceMethodBuilder.php index 3970f1ef..e84cb19e 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ResourceMethodBuilder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ResourceMethodBuilder.php @@ -29,7 +29,7 @@ protected function getSearchDirectory(IdeAutoCompletionBundleTransfer $bundleTra return sprintf( '%s%s/', $bundleTransfer->getDirectory(), - $bundleTransfer->getName() + $bundleTransfer->getName(), ); } } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilder.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilder.php index d52dc43f..810cecc5 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilder.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilder.php @@ -29,7 +29,7 @@ protected function getSearchDirectory(IdeAutoCompletionBundleTransfer $bundleTra return sprintf( '%s%s/', $bundleTransfer->getDirectory(), - $bundleTransfer->getName() + $bundleTransfer->getName(), ); } } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriter.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriter.php index 51b29172..8caa3df8 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriter.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriter.php @@ -12,7 +12,7 @@ class FileWriter implements FileWriterInterface /** * @param string $fileName * @param string $fileContent - * @param array $options + * @param array $options * * @return void */ @@ -26,7 +26,7 @@ public function writeFile(string $fileName, string $fileContent, array $options) } /** - * @param array $options + * @param array $options * * @return string */ @@ -34,16 +34,16 @@ protected function getTargetDirectory(array $options): string { $baseDirectory = rtrim( $options[IdeAutoCompletionOptionConstants::TARGET_BASE_DIRECTORY], - DIRECTORY_SEPARATOR + DIRECTORY_SEPARATOR, ); $applicationPathFragment = trim( str_replace( IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, $options[IdeAutoCompletionOptionConstants::APPLICATION_NAME], - $options[IdeAutoCompletionOptionConstants::TARGET_DIRECTORY_PATTERN] + $options[IdeAutoCompletionOptionConstants::TARGET_DIRECTORY_PATTERN], ), - DIRECTORY_SEPARATOR + DIRECTORY_SEPARATOR, ); return "{$baseDirectory}/{$applicationPathFragment}/"; @@ -51,7 +51,7 @@ protected function getTargetDirectory(array $options): string /** * @param string $directory - * @param array $options + * @param array $options * * @return void */ diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriterInterface.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriterInterface.php index dcdf05ce..a18193ab 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriterInterface.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/FileWriterInterface.php @@ -12,7 +12,7 @@ interface FileWriterInterface /** * @param string $fileName * @param string $fileContent - * @param array $options + * @param array $options * * @return void */ diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/AbstractGenerator.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/AbstractGenerator.php index c04825db..e7ff8b30 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/AbstractGenerator.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/AbstractGenerator.php @@ -32,7 +32,7 @@ abstract class AbstractGenerator implements GeneratorInterface /** * @param \Twig\Environment $twig * @param \Spryker\Zed\Development\Business\IdeAutoCompletion\FileWriterInterface $fileWriter - * @param array $options + * @param array $options */ public function __construct(Environment $twig, FileWriterInterface $fileWriter, array $options) { @@ -42,7 +42,7 @@ public function __construct(Environment $twig, FileWriterInterface $fileWriter, } /** - * @param \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer[] $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer> $moduleTransferCollection * * @return void */ @@ -75,7 +75,7 @@ protected function getNamespace(): string return str_replace( IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, $this->options[IdeAutoCompletionOptionConstants::APPLICATION_NAME], - $this->options[IdeAutoCompletionOptionConstants::TARGET_NAMESPACE_PATTERN] + $this->options[IdeAutoCompletionOptionConstants::TARGET_NAMESPACE_PATTERN], ); } } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/BundleMethodGenerator.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/BundleMethodGenerator.php index e20ceec6..3ee4c2ae 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/BundleMethodGenerator.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/BundleMethodGenerator.php @@ -18,7 +18,7 @@ public function getName(): string } /** - * @param \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer[] $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer> $moduleTransferCollection * * @return void */ diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/GeneratorInterface.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/GeneratorInterface.php index 1f1d639a..ed7d5d65 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/GeneratorInterface.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Generator/GeneratorInterface.php @@ -10,7 +10,7 @@ interface GeneratorInterface { /** - * @param \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer[] $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer> $moduleTransferCollection * * @return void */ diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionConstants.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionConstants.php index c25f0fe4..20a9c724 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionConstants.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionConstants.php @@ -9,6 +9,13 @@ final class IdeAutoCompletionConstants { + /** + * @var string + */ public const APPLICATION_NAME_PLACEHOLDER = '{{APPLICATION_NAME}}'; + + /** + * @var string + */ public const DIRECTORY_PERMISSION = 'DIRECTORY_PERMISSION'; } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionOptionConstants.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionOptionConstants.php index 0b46ed3e..070d3829 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionOptionConstants.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionOptionConstants.php @@ -9,8 +9,53 @@ final class IdeAutoCompletionOptionConstants { + /** + * @var string + */ public const TARGET_BASE_DIRECTORY = 'target_base_directory'; + + /** + * @var string + */ public const TARGET_DIRECTORY_PATTERN = 'target_path_pattern'; + + /** + * @var string + */ public const TARGET_NAMESPACE_PATTERN = 'target_namespace_pattern'; + + /** + * @var string + */ public const APPLICATION_NAME = 'application_name'; + + /** + * @var string + */ + public const YVES = 'Yves'; + + /** + * @var string + */ + public const ZED = 'Zed'; + + /** + * @var string + */ + public const CLIENT = 'Client'; + + /** + * @var string + */ + public const GLUE = 'Glue'; + + /** + * @var string + */ + public const GLUE_BACKEND = 'GlueBackend'; + + /** + * @var string + */ + public const SERVICE = 'Service'; } diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriter.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriter.php index efcbc52e..08b1af9d 100644 --- a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriter.php +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriter.php @@ -12,7 +12,7 @@ class IdeAutoCompletionWriter implements IdeAutoCompletionWriterInterface { /** - * @var \Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface[] + * @var array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface> */ protected $generators; @@ -22,7 +22,7 @@ class IdeAutoCompletionWriter implements IdeAutoCompletionWriterInterface protected $moduleFinder; /** - * @param \Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface[] $generators + * @param array<\Spryker\Zed\Development\Business\IdeAutoCompletion\Generator\GeneratorInterface> $generators * @param \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\BundleFinderInterface $moduleFinder */ public function __construct(array $generators, BundleFinderInterface $moduleFinder) diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/DirectoryRemover.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/DirectoryRemover.php new file mode 100644 index 00000000..fc28f1b1 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/DirectoryRemover.php @@ -0,0 +1,58 @@ +targetDirectoryResolver = $targetDirectoryResolver; + $this->fileSystem = $fileSystem; + $this->fileFinder = $fileFinder; + } + + /** + * @param string $application + * + * @return void + */ + public function remove(string $application): void + { + $targetDirectory = $this->targetDirectoryResolver->resolveTargetDirectory($application); + + if (!$this->fileSystem->exists($targetDirectory)) { + return; + } + + $this->fileSystem->remove( + $this->fileFinder->findFiles($targetDirectory), + ); + } +} diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/DirectoryRemoverInterface.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/DirectoryRemoverInterface.php new file mode 100644 index 00000000..3ac3c804 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/DirectoryRemoverInterface.php @@ -0,0 +1,18 @@ +finder = $finder; + } + + /** + * @param string $directoryPath + * + * @return \Symfony\Component\Finder\Finder + */ + public function findFiles(string $directoryPath): Finder + { + $finder = clone $this->finder; + $finder->in($directoryPath) + ->depth(0) + ->name('/.*\.php/'); + + return $finder; + } + + /** + * @param string $directoryPath + * + * @return bool + */ + public function isEmpty(string $directoryPath): bool + { + $finder = clone $this->finder; + + return $finder->in($directoryPath) + ->depth(0) + ->exclude(['.', '..']) + ->count() === 0; + } +} diff --git a/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/GeneratedFileFinderInterface.php b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/GeneratedFileFinderInterface.php new file mode 100644 index 00000000..f4da78bf --- /dev/null +++ b/src/Spryker/Zed/Development/Business/IdeAutoCompletion/Remover/GeneratedFileFinderInterface.php @@ -0,0 +1,27 @@ +config = $config; + } + + /** + * @param string $application + * + * @return string + */ + public function resolveTargetDirectory(string $application): string + { + $options = $this->getOptions($application); + + $baseDirectory = rtrim( + $options[IdeAutoCompletionOptionConstants::TARGET_BASE_DIRECTORY], + DIRECTORY_SEPARATOR, + ); + + $applicationPathFragment = trim( + str_replace( + IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, + $application, + $options[IdeAutoCompletionOptionConstants::TARGET_DIRECTORY_PATTERN], + ), + DIRECTORY_SEPARATOR, + ); + + return "{$baseDirectory}/{$applicationPathFragment}/"; + } + + /** + * @param string $application + * + * @throws \InvalidArgumentException + * + * @return array + */ + private function getOptions(string $application): array + { + switch ($application) { + case IdeAutoCompletionOptionConstants::YVES: + return $this->config->getYvesIdeAutoCompletionOptions(); + case IdeAutoCompletionOptionConstants::ZED: + return $this->config->getZedIdeAutoCompletionOptions(); + case IdeAutoCompletionOptionConstants::CLIENT: + return $this->config->getClientIdeAutoCompletionOptions(); + case IdeAutoCompletionOptionConstants::GLUE: + return $this->config->getGlueIdeAutoCompletionOptions(); + case IdeAutoCompletionOptionConstants::SERVICE: + return $this->config->getServiceIdeAutoCompletionOptions(); + default: + throw new InvalidArgumentException(sprintf('Unable to resolve IDE autocompletion directory for application `%s`', $application)); + } + } +} diff --git a/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php b/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php index 5d14e52d..c309d719 100644 --- a/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php +++ b/src/Spryker/Zed/Development/Business/Integration/DependencyProviderUsedPluginFinder.php @@ -14,7 +14,7 @@ use Generated\Shared\Transfer\ModuleTransfer; use Generated\Shared\Transfer\OrganizationTransfer; use Generated\Shared\Transfer\PluginTransfer; -use Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface; +use Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; @@ -22,9 +22,9 @@ class DependencyProviderUsedPluginFinder implements DependencyProviderUsedPluginFinderInterface { /** - * @var \Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface + * @var \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface */ - protected $projectModuleFinder; + protected $moduleFinderFacade; /** * @var \Spryker\Zed\Development\DevelopmentConfig @@ -32,12 +32,12 @@ class DependencyProviderUsedPluginFinder implements DependencyProviderUsedPlugin protected $config; /** - * @param \Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface $projectModuleFinder + * @param \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade * @param \Spryker\Zed\Development\DevelopmentConfig $config */ - public function __construct(ProjectModuleFinderInterface $projectModuleFinder, DevelopmentConfig $config) + public function __construct(DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade, DevelopmentConfig $config) { - $this->projectModuleFinder = $projectModuleFinder; + $this->moduleFinderFacade = $moduleFinderFacade; $this->config = $config; } @@ -48,13 +48,13 @@ public function __construct(ProjectModuleFinderInterface $projectModuleFinder, D */ public function getUsedPlugins(?ModuleFilterTransfer $moduleFilterTransfer = null): DependencyProviderCollectionTransfer { - $projectModules = $this->projectModuleFinder->getProjectModules($moduleFilterTransfer); + $projectModules = $this->moduleFinderFacade->getProjectModules($moduleFilterTransfer); $dependencyProviderCollectionTransfer = new DependencyProviderCollectionTransfer(); foreach ($projectModules as $moduleTransfer) { $dependencyProviderCollectionTransfer = $this->addPluginUsageInModuleApplications( $moduleTransfer, - $dependencyProviderCollectionTransfer + $dependencyProviderCollectionTransfer, ); } @@ -67,8 +67,10 @@ public function getUsedPlugins(?ModuleFilterTransfer $moduleFilterTransfer = nul * * @return \Generated\Shared\Transfer\DependencyProviderCollectionTransfer */ - protected function addPluginUsageInModuleApplications(ModuleTransfer $moduleTransfer, DependencyProviderCollectionTransfer $dependencyProviderCollectionTransfer): DependencyProviderCollectionTransfer - { + protected function addPluginUsageInModuleApplications( + ModuleTransfer $moduleTransfer, + DependencyProviderCollectionTransfer $dependencyProviderCollectionTransfer + ): DependencyProviderCollectionTransfer { foreach ($moduleTransfer->getApplications() as $applicationTransfer) { $dependencyProviderCollectionTransfer = $this->addPluginUsageInModule($moduleTransfer, $applicationTransfer, $dependencyProviderCollectionTransfer); } @@ -83,10 +85,13 @@ protected function addPluginUsageInModuleApplications(ModuleTransfer $moduleTran * * @return \Generated\Shared\Transfer\DependencyProviderCollectionTransfer */ - protected function addPluginUsageInModule(ModuleTransfer $moduleTransfer, ApplicationTransfer $applicationTransfer, DependencyProviderCollectionTransfer $dependencyProviderCollectionTransfer) - { + protected function addPluginUsageInModule( + ModuleTransfer $moduleTransfer, + ApplicationTransfer $applicationTransfer, + DependencyProviderCollectionTransfer $dependencyProviderCollectionTransfer + ) { $finder = $this->getFinderForModule( - $this->getPath($moduleTransfer, $applicationTransfer) + $this->getPath($moduleTransfer, $applicationTransfer), ); foreach ($finder as $splFileInfo) { @@ -110,14 +115,14 @@ protected function getPath(ModuleTransfer $moduleTransfer, ApplicationTransfer $ $moduleTransfer->getPath(), $moduleTransfer->getOrganization()->getName(), $applicationTransfer->getName(), - $moduleTransfer->getName() + $moduleTransfer->getName(), ); } /** * @param string $path * - * @return \Symfony\Component\Finder\SplFileInfo[]|\Symfony\Component\Finder\Finder + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ protected function getFinderForModule(string $path): Finder { @@ -132,12 +137,19 @@ protected function getFinderForModule(string $path): Finder } /** + * @phpstan-return \Closure + * * @return callable */ protected function getFilenameSortCallback(): callable { return function (SplFileInfo $splFileInfoOne, SplFileInfo $splFileInfoTwo) { - return strcmp($splFileInfoOne->getRealPath(), $splFileInfoTwo->getRealPath()); + /** @var string $firstRealPath */ + $firstRealPath = $splFileInfoOne->getRealPath(); + /** @var string $secondRealPath */ + $secondRealPath = $splFileInfoTwo->getRealPath(); + + return strcmp($firstRealPath, $secondRealPath); }; } @@ -168,8 +180,11 @@ protected function buildDependencyProviderTransfer(SplFileInfo $splFileInfo, Mod * * @return \Generated\Shared\Transfer\DependencyProviderCollectionTransfer */ - protected function addPluginUsages(DependencyProviderCollectionTransfer $dependencyProviderCollectionTransfer, DependencyProviderTransfer $dependencyProviderTransfer, SplFileInfo $splFileInfo): DependencyProviderCollectionTransfer - { + protected function addPluginUsages( + DependencyProviderCollectionTransfer $dependencyProviderCollectionTransfer, + DependencyProviderTransfer $dependencyProviderTransfer, + SplFileInfo $splFileInfo + ): DependencyProviderCollectionTransfer { preg_match_all('/use (.*?);/', $splFileInfo->getContents(), $matches, PREG_SET_ORDER); if (count($matches) === 0) { return $dependencyProviderCollectionTransfer; diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinder.php b/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinder.php index 556b688d..05904857 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinder.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinder.php @@ -65,7 +65,12 @@ public function find(ModuleTransfer $moduleTransfer): Finder protected function getModuleDirectories(ModuleTransfer $moduleTransfer): array { $directories = $this->pathBuilder->buildPaths($moduleTransfer); - $directories = array_filter($directories, 'glob'); + $directories = array_filter( + $directories, + function (string $directory) { + return glob($directory, GLOB_NOSORT | GLOB_ONLYDIR); + }, + ); return $directories; } diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinderInterface.php b/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinderInterface.php index cc3a701c..9eb68a6d 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleFileFinder/ModuleFileFinderInterface.php @@ -15,7 +15,7 @@ interface ModuleFileFinderInterface /** * @param \Generated\Shared\Transfer\ModuleTransfer $moduleTransfer * - * @return \Symfony\Component\Finder\Finder|\Symfony\Component\Finder\SplFileInfo[] + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ public function find(ModuleTransfer $moduleTransfer): Finder; diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php b/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php index a2da497d..bbc27c2a 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinder.php @@ -11,15 +11,18 @@ use Generated\Shared\Transfer\ModuleFilterTransfer; use Generated\Shared\Transfer\ModuleTransfer; use Generated\Shared\Transfer\OrganizationTransfer; +use Laminas\Filter\FilterChain; +use Laminas\Filter\StringToLower; +use Laminas\Filter\Word\CamelCaseToDash; +use Laminas\Filter\Word\DashToCamelCase; use Spryker\Zed\Development\Business\Module\ModuleMatcher\ModuleMatcherInterface; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\FilterChain; -use Zend\Filter\StringToLower; -use Zend\Filter\Word\CamelCaseToDash; -use Zend\Filter\Word\DashToCamelCase; +/** + * @deprecated Use `spryker/module-finder` instead. + */ class ModuleFinder implements ModuleFinderInterface { /** @@ -33,7 +36,7 @@ class ModuleFinder implements ModuleFinderInterface protected $moduleMatcher; /** - * @var \Generated\Shared\Transfer\ModuleTransfer[] + * @var array<\Generated\Shared\Transfer\ModuleTransfer> */ protected static $moduleTransferCollection; @@ -50,7 +53,7 @@ public function __construct(DevelopmentConfig $config, ModuleMatcherInterface $m /** * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array { @@ -73,10 +76,10 @@ public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): } /** - * @param array $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $moduleTransferCollection * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ protected function addStandaloneModulesToCollection(array $moduleTransferCollection, ?ModuleFilterTransfer $moduleFilterTransfer = null): array { @@ -98,7 +101,7 @@ protected function addStandaloneModulesToCollection(array $moduleTransferCollect } /** - * @return \Symfony\Component\Finder\SplFileInfo[]|\Symfony\Component\Finder\Finder + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ protected function getStandaloneModuleFinder(): Finder { @@ -107,13 +110,16 @@ protected function getStandaloneModuleFinder(): Finder /** * @param \Generated\Shared\Transfer\ModuleTransfer $moduleTransfer - * @param \Generated\Shared\Transfer\ModuleTransfer[] $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $moduleTransferCollection * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ - protected function addModuleToCollection(ModuleTransfer $moduleTransfer, array $moduleTransferCollection, ?ModuleFilterTransfer $moduleFilterTransfer = null): array - { + protected function addModuleToCollection( + ModuleTransfer $moduleTransfer, + array $moduleTransferCollection, + ?ModuleFilterTransfer $moduleFilterTransfer = null + ): array { if ($moduleFilterTransfer !== null && !$this->moduleMatcher->matches($moduleTransfer, $moduleFilterTransfer)) { return $moduleTransferCollection; } @@ -141,14 +147,14 @@ protected function isModule(ModuleTransfer $moduleTransfer): bool $description = $composerJsonAsArray['description']; - return preg_match('/\smodule$/', $description); + return (bool)preg_match('/\smodule$/', $description); } /** - * @param array $moduleTransferCollection + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $moduleTransferCollection * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ protected function addModulesToCollection(array $moduleTransferCollection, ?ModuleFilterTransfer $moduleFilterTransfer = null): array { @@ -165,7 +171,7 @@ protected function addModulesToCollection(array $moduleTransferCollection, ?Modu } /** - * @return \Symfony\Component\Finder\SplFileInfo[]|\Symfony\Component\Finder\Finder + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ protected function getModuleFinder(): Finder { @@ -337,6 +343,7 @@ protected function getComposerJsonAsArray(string $path): array if (!is_file($pathToComposerJson)) { return []; } + /** @var string $fileContent */ $fileContent = file_get_contents($pathToComposerJson); $composerJsonAsArray = json_decode($fileContent, true); @@ -363,7 +370,9 @@ protected function getOrganizationNameFromComposer(array $composerJsonAsArray): */ protected function getOrganizationNameFromDirectory(SplFileInfo $directoryInfo): string { - $pathFragments = explode(DIRECTORY_SEPARATOR, $directoryInfo->getRealPath()); + /** @var string $realPath */ + $realPath = $directoryInfo->getRealPath(); + $pathFragments = explode(DIRECTORY_SEPARATOR, $realPath); $vendorPosition = array_search('vendor', $pathFragments); $organizationName = $pathFragments[$vendorPosition + 1]; @@ -378,7 +387,9 @@ protected function getOrganizationNameFromDirectory(SplFileInfo $directoryInfo): */ protected function getApplicationNameFromDirectory(SplFileInfo $directoryInfo): string { - $pathFragments = explode(DIRECTORY_SEPARATOR, $directoryInfo->getRealPath()); + /** @var string $realPath */ + $realPath = $directoryInfo->getRealPath(); + $pathFragments = explode(DIRECTORY_SEPARATOR, $realPath); $vendorPosition = array_search('vendor', $pathFragments); $applicationName = $pathFragments[$vendorPosition + 2]; diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinderInterface.php b/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinderInterface.php index 98a4f8a2..74c43e04 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleFinder/ModuleFinderInterface.php @@ -9,12 +9,15 @@ use Generated\Shared\Transfer\ModuleFilterTransfer; +/** + * @deprecated Use `spryker/module-finder` instead. + */ interface ModuleFinderInterface { /** * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array; } diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php b/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php index 0dc1760d..0425b7d2 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcher.php @@ -11,6 +11,9 @@ use Generated\Shared\Transfer\ModuleTransfer; use Generated\Shared\Transfer\OrganizationTransfer; +/** + * @deprecated Use `spryker/module-finder` instead. + */ class ModuleMatcher implements ModuleMatcherInterface { /** @@ -119,6 +122,6 @@ protected function match(string $search, string $given): bool $search = mb_substr($search, 0, mb_strlen($search) - 1); } - return preg_match(sprintf('/%s/', $search), $given); + return (bool)preg_match(sprintf('/%s/', $search), $given); } } diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcherInterface.php b/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcherInterface.php index 4ef58af7..4f58dab8 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcherInterface.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleMatcher/ModuleMatcherInterface.php @@ -10,6 +10,9 @@ use Generated\Shared\Transfer\ModuleFilterTransfer; use Generated\Shared\Transfer\ModuleTransfer; +/** + * @deprecated Use `spryker/module-finder` instead. + */ interface ModuleMatcherInterface { /** diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleOverview.php b/src/Spryker/Zed/Development/Business/Module/ModuleOverview.php index 4b2e2e3a..bd9b39b6 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleOverview.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleOverview.php @@ -8,33 +8,25 @@ namespace Spryker\Zed\Development\Business\Module; use Generated\Shared\Transfer\ModuleOverviewTransfer; -use Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface; -use Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface; +use Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface; class ModuleOverview implements ModuleOverviewInterface { /** - * @var \Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface + * @var \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface */ - protected $projectModuleFinder; + protected $moduleFinderFacade; /** - * @var \Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface + * @param \Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade */ - protected $moduleFinder; - - /** - * @param \Spryker\Zed\Development\Business\Module\ProjectModuleFinder\ProjectModuleFinderInterface $projectModuleFinder - * @param \Spryker\Zed\Development\Business\Module\ModuleFinder\ModuleFinderInterface $moduleFinder - */ - public function __construct(ProjectModuleFinderInterface $projectModuleFinder, ModuleFinderInterface $moduleFinder) + public function __construct(DevelopmentToModuleFinderFacadeInterface $moduleFinderFacade) { - $this->projectModuleFinder = $projectModuleFinder; - $this->moduleFinder = $moduleFinder; + $this->moduleFinderFacade = $moduleFinderFacade; } /** - * @return \Generated\Shared\Transfer\ModuleOverviewTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleOverviewTransfer> */ public function getOverview(): array { @@ -48,19 +40,19 @@ public function getOverview(): array } /** - * @param \Generated\Shared\Transfer\ModuleOverviewTransfer[] $moduleOverviewTransferCollection + * @param array<\Generated\Shared\Transfer\ModuleOverviewTransfer> $moduleOverviewTransferCollection * - * @return \Generated\Shared\Transfer\ModuleOverviewTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleOverviewTransfer> */ protected function addProjectModules(array $moduleOverviewTransferCollection): array { - $projectModules = $this->projectModuleFinder->getProjectModules(); + $projectModules = $this->moduleFinderFacade->getProjectModules(); foreach (array_keys($projectModules) as $moduleKey) { $moduleName = $this->getModuleNameFromModuleKey($moduleKey); $moduleOverviewTransfer = $this->getModuleOverviewTransfer( $moduleOverviewTransferCollection, - $this->getModuleNameFromModuleKey($moduleKey) + $this->getModuleNameFromModuleKey($moduleKey), ); $moduleOverviewTransfer->setExistsProjectModule(true); @@ -72,19 +64,19 @@ protected function addProjectModules(array $moduleOverviewTransferCollection): a } /** - * @param \Generated\Shared\Transfer\ModuleOverviewTransfer[] $moduleOverviewTransferCollection + * @param array<\Generated\Shared\Transfer\ModuleOverviewTransfer> $moduleOverviewTransferCollection * - * @return \Generated\Shared\Transfer\ModuleOverviewTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleOverviewTransfer> */ protected function addCoreModules(array $moduleOverviewTransferCollection): array { - $coreModules = $this->moduleFinder->getModules(); + $coreModules = $this->moduleFinderFacade->getModules(); foreach (array_keys($coreModules) as $moduleKey) { $moduleName = $this->getModuleNameFromModuleKey($moduleKey); $moduleOverviewTransfer = $this->getModuleOverviewTransfer( $moduleOverviewTransferCollection, - $this->getModuleNameFromModuleKey($moduleKey) + $this->getModuleNameFromModuleKey($moduleKey), ); $moduleOverviewTransfer->setExistsCoreModule(true); @@ -108,7 +100,7 @@ protected function getModuleNameFromModuleKey(string $moduleKey): string } /** - * @param array $moduleOverviewTransferCollection + * @param array $moduleOverviewTransferCollection * @param string $moduleName * * @return \Generated\Shared\Transfer\ModuleOverviewTransfer diff --git a/src/Spryker/Zed/Development/Business/Module/ModuleOverviewInterface.php b/src/Spryker/Zed/Development/Business/Module/ModuleOverviewInterface.php index c2036f72..eb42a682 100644 --- a/src/Spryker/Zed/Development/Business/Module/ModuleOverviewInterface.php +++ b/src/Spryker/Zed/Development/Business/Module/ModuleOverviewInterface.php @@ -10,7 +10,7 @@ interface ModuleOverviewInterface { /** - * @return \Generated\Shared\Transfer\ModuleOverviewTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleOverviewTransfer> */ public function getOverview(): array; } diff --git a/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php b/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php index 1591de06..7d4bb831 100644 --- a/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php +++ b/src/Spryker/Zed/Development/Business/Module/PathBuilder/AbstractPathBuilder.php @@ -41,7 +41,7 @@ public function buildPaths(ModuleTransfer $moduleTransfer): array sprintf( '%s%s/', $this->config->getPathToInternalNamespace(static::ORGANIZATION), - $this->getModuleName($moduleTransfer) + $this->getModuleName($moduleTransfer), ), ]; } diff --git a/src/Spryker/Zed/Development/Business/Module/PathBuilder/PathBuilderComposite.php b/src/Spryker/Zed/Development/Business/Module/PathBuilder/PathBuilderComposite.php index c4da07e3..1f11a937 100644 --- a/src/Spryker/Zed/Development/Business/Module/PathBuilder/PathBuilderComposite.php +++ b/src/Spryker/Zed/Development/Business/Module/PathBuilder/PathBuilderComposite.php @@ -12,12 +12,12 @@ class PathBuilderComposite implements PathBuilderInterface { /** - * @var \Spryker\Zed\Development\Business\Module\PathBuilder\PathBuilderInterface[] + * @var array<\Spryker\Zed\Development\Business\Module\PathBuilder\PathBuilderInterface> */ protected $pathBuilders; /** - * @param \Spryker\Zed\Development\Business\Module\PathBuilder\PathBuilderInterface[] $pathBuilders + * @param array<\Spryker\Zed\Development\Business\Module\PathBuilder\PathBuilderInterface> $pathBuilders */ public function __construct(array $pathBuilders) { diff --git a/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerFeatureModulePathBuilder.php b/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerFeatureModulePathBuilder.php new file mode 100644 index 00000000..926d6fc4 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Module/PathBuilder/SprykerFeatureModulePathBuilder.php @@ -0,0 +1,16 @@ +getModuleName($moduleTransfer) + $this->getModuleName($moduleTransfer), ), ]; diff --git a/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php b/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php index 3502944b..b802d4a5 100644 --- a/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php +++ b/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinder.php @@ -16,6 +16,9 @@ use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; +/** + * @deprecated Use `spryker/module-finder` instead. + */ class ProjectModuleFinder implements ProjectModuleFinderInterface { /** @@ -75,7 +78,7 @@ public function getProjectModules(?ModuleFilterTransfer $moduleFilterTransfer = } /** - * @return array + * @return array */ protected function getProjectDirectories(): array { @@ -90,9 +93,9 @@ protected function getProjectDirectories(): array } /** - * @param array $projectOrganizationModuleDirectories + * @param array $projectOrganizationModuleDirectories * - * @return \Symfony\Component\Finder\SplFileInfo[]|\Symfony\Component\Finder\Finder + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ protected function getProjectModuleFinder(array $projectOrganizationModuleDirectories): Finder { @@ -107,12 +110,19 @@ protected function getProjectModuleFinder(array $projectOrganizationModuleDirect } /** + * @phpstan-return \Closure + * * @return callable */ protected function getFilenameSortCallback(): callable { return function (SplFileInfo $fileOne, SplFileInfo $fileTwo) { - return strcmp($fileOne->getRealpath(), $fileTwo->getRealpath()); + /** @var string $firstRealPath */ + $firstRealPath = $fileOne->getRealpath(); + /** @var string $secondRealPath */ + $secondRealPath = $fileTwo->getRealpath(); + + return strcmp($firstRealPath, $secondRealPath); }; } @@ -182,7 +192,9 @@ protected function buildApplicationTransferFromDirectoryInformation(SplFileInfo */ protected function getOrganizationNameFromDirectory(SplFileInfo $directoryInfo): string { - $pathFragments = explode(DIRECTORY_SEPARATOR, $directoryInfo->getRealPath()); + /** @var string $realPath */ + $realPath = $directoryInfo->getRealPath(); + $pathFragments = explode(DIRECTORY_SEPARATOR, $realPath); $srcPosition = array_search('src', $pathFragments); $organizationName = $pathFragments[$srcPosition + 1]; @@ -197,7 +209,9 @@ protected function getOrganizationNameFromDirectory(SplFileInfo $directoryInfo): */ protected function getApplicationNameFromDirectory(SplFileInfo $directoryInfo): string { - $pathFragments = explode(DIRECTORY_SEPARATOR, $directoryInfo->getRealPath()); + /** @var string $realPath */ + $realPath = $directoryInfo->getRealPath(); + $pathFragments = explode(DIRECTORY_SEPARATOR, $realPath); $srcPosition = array_search('src', $pathFragments); $organizationName = $pathFragments[$srcPosition + 2]; diff --git a/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinderInterface.php b/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinderInterface.php index da8ceedb..1783b418 100644 --- a/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/Module/ProjectModuleFinder/ProjectModuleFinderInterface.php @@ -9,6 +9,9 @@ use Generated\Shared\Transfer\ModuleFilterTransfer; +/** + * @deprecated Use `spryker/module-finder` instead. + */ interface ProjectModuleFinderInterface { /** diff --git a/src/Spryker/Zed/Development/Business/Normalizer/NameNormalizer.php b/src/Spryker/Zed/Development/Business/Normalizer/NameNormalizer.php new file mode 100644 index 00000000..4abcd7a4 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Normalizer/NameNormalizer.php @@ -0,0 +1,48 @@ +attach(new CamelCaseToDash()) + ->attach(new StringToLower()); + + return $filterChain->filter($name); + } + + /** + * @param string $name + * + * @return string + */ + public function camelize(string $name): string + { + /** @var string $name */ + $name = str_replace('-', '_', $name); + $filter = new UnderscoreToCamelCase(); + + /** @var string $camelCasedValue */ + $camelCasedValue = $filter->filter($name); + + return ucfirst($camelCasedValue); + } +} diff --git a/src/Spryker/Zed/Development/Business/Normalizer/NameNormalizerInterface.php b/src/Spryker/Zed/Development/Business/Normalizer/NameNormalizerInterface.php new file mode 100644 index 00000000..095df959 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Normalizer/NameNormalizerInterface.php @@ -0,0 +1,25 @@ + */ public function getPackages(): array { $packageTransferCollection = []; foreach ($this->getPackageFinder() as $directoryInfo) { - if (in_array($directoryInfo->getFilename(), $this->config->getInternalPackageDirectories())) { + if (in_array($directoryInfo->getFilename(), $this->config->getInternalPackageDirectories(), true)) { continue; } $packageTransfer = $this->getPackageTransfer($directoryInfo); @@ -54,7 +57,7 @@ public function getPackages(): array } /** - * @return \Symfony\Component\Finder\SplFileInfo[]|\Symfony\Component\Finder\Finder + * @return \Symfony\Component\Finder\Finder<\Symfony\Component\Finder\SplFileInfo> */ protected function getPackageFinder(): Finder { @@ -95,6 +98,7 @@ protected function getPackageTransfer(SplFileInfo $directoryInfo): PackageTransf protected function getComposerJsonAsArray(string $path): array { $pathToComposerJson = sprintf('%s/composer.json', $path); + /** @var string $fileContent */ $fileContent = file_get_contents($pathToComposerJson); $composerJsonAsArray = json_decode($fileContent, true); @@ -127,6 +131,6 @@ protected function isModule(PackageTransfer $packageTransfer): bool $composerJsonAsArray = $this->getComposerJsonAsArray($packageTransfer->getPath()); $description = $composerJsonAsArray['description']; - return preg_match('/\smodule$/', $description); + return (bool)preg_match('/\smodule$/', $description); } } diff --git a/src/Spryker/Zed/Development/Business/Package/PackageFinder/PackageFinderInterface.php b/src/Spryker/Zed/Development/Business/Package/PackageFinder/PackageFinderInterface.php index ab450c71..39bd0670 100644 --- a/src/Spryker/Zed/Development/Business/Package/PackageFinder/PackageFinderInterface.php +++ b/src/Spryker/Zed/Development/Business/Package/PackageFinder/PackageFinderInterface.php @@ -7,10 +7,13 @@ namespace Spryker\Zed\Development\Business\Package\PackageFinder; +/** + * @deprecated Use `spryker/module-finder` instead. + */ interface PackageFinderInterface { /** - * @return \Generated\Shared\Transfer\PackageTransfer[] + * @return array<\Generated\Shared\Transfer\PackageTransfer> */ public function getPackages(): array; } diff --git a/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php b/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php index 8a222e96..5d8f2067 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php +++ b/src/Spryker/Zed/Development/Business/PhpMd/PhpMdRunner.php @@ -8,35 +8,72 @@ namespace Spryker\Zed\Development\Business\PhpMd; use ErrorException; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Process\Process; -use Zend\Filter\Word\UnderscoreToCamelCase; class PhpMdRunner { + /** + * @var int + */ public const CODE_SUCCESS = 0; + /** + * @var string + */ + protected const CONFIG_LOCAL = 'phpmd.xml'; + + /** + * @var string + */ public const BUNDLE_ALL = 'all'; + /** + * @var string + */ public const OPTION_DRY_RUN = 'dry-run'; + + /** + * @var string + */ public const OPTION_FORMAT = 'format'; + /** + * @var string + */ + protected const OPTION_IGNORE = 'ignore'; + + /** + * @var string + */ + protected const CUSTOM_RULESET = 'phpmd-ruleset.xml'; + /** * @var \Spryker\Zed\Development\DevelopmentConfig */ protected $config; + /** + * @var \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface $nameNormalizer + */ + protected NameNormalizerInterface $nameNormalizer; + /** * @param \Spryker\Zed\Development\DevelopmentConfig $config + * @param \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface $nameNormalizer */ - public function __construct(DevelopmentConfig $config) - { + public function __construct( + DevelopmentConfig $config, + NameNormalizerInterface $nameNormalizer + ) { $this->config = $config; + $this->nameNormalizer = $nameNormalizer; } /** * @param string|null $bundle - * @param array $options + * @param array $options * * @throws \ErrorException * @@ -48,31 +85,30 @@ public function run($bundle, array $options = []) if (!is_dir($path)) { $message = 'This path does not exist'; - if (!empty($bundle)) { + if ($bundle) { $message = 'This bundle does not exist'; } throw new ErrorException($message); } - $defaults = [ - 'ignore' => $bundle ? '' : 'vendor/', - ]; - $options += $defaults; + $options += $this->getDefaultIgnoredPath($bundle); return $this->runPhpMdCommand($path, $options); } /** - * @param string $value + * @param string|null $bundle * - * @return string + * @return array */ - protected function convertToCamelCase(string $value): string + protected function getDefaultIgnoredPath(?string $bundle = null): array { - $filter = new UnderscoreToCamelCase(); + $dontIgnoreVendor = $bundle !== null || $this->config->isStandaloneMode(); - return ucfirst($filter->filter($value)); + return [ + static::OPTION_IGNORE => $dontIgnoreVendor ? null : 'vendor/', + ]; } /** @@ -87,7 +123,7 @@ protected function resolvePath($bundle) return $this->config->getPathToCore(); } - $bundle = $this->convertToCamelCase($bundle); + $bundle = $this->nameNormalizer->camelize($bundle); return $this->getPathToBundle($bundle); } @@ -119,33 +155,69 @@ protected function resolveCorePaths(string $module): string [$namespace, $module] = explode('.', $module, 2); $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); + if ($namespace !== null && $pathToInternalNamespace === null) { + return $this->resolveCommonModulePath($module, $namespace); + } + if ($pathToInternalNamespace !== null && is_dir($pathToInternalNamespace . $module)) { return $pathToInternalNamespace . $module . DIRECTORY_SEPARATOR; } - $namespace = $this->convertToCamelCase($namespace); - $module = $this->convertToCamelCase($module); - $path = $this->config->getPathToRoot() . 'vendor' . DIRECTORY_SEPARATOR . $namespace . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR; + $namespace = $this->nameNormalizer->camelize($namespace); + $module = $this->nameNormalizer->camelize($module); + + return $this->getFullPathFromRoot($namespace, $module); + } + + /** + * @param string $module + * @param string $namespace + * + * @return string + */ + protected function resolveCommonModulePath(string $module, string $namespace): string + { + $moduleVendor = $this->nameNormalizer->dasherize($namespace); + $module = $this->nameNormalizer->dasherize($module); + + return $this->getFullPathFromRoot($moduleVendor, $module); + } - return $path; + /** + * @param string $moduleVendor + * @param string $module + * + * @return string + */ + protected function getFullPathFromRoot(string $moduleVendor, string $module): string + { + return sprintf( + '%s/vendor/%s/%s/', + $this->config->getPathToRoot(), + $moduleVendor, + $module, + ); } /** * @param string $path - * @param array $options + * @param array $options * * @return int Exit code */ protected function runPhpMdCommand($path, array $options) { - $pathToFiles = rtrim($path, DIRECTORY_SEPARATOR); + $pathToFiles = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + if (is_dir($pathToFiles . 'src')) { + $pathToFiles .= 'src' . DIRECTORY_SEPARATOR; + } $format = 'text'; if ($options[static::OPTION_FORMAT]) { $format = $options[static::OPTION_FORMAT]; } - $config = $this->config->getArchitectureStandard(); + $config = $this->resolveRulesetPath($path); if ($options['ignore']) { $config .= ' --exclude ' . $options['ignore']; @@ -158,11 +230,48 @@ protected function runPhpMdCommand($path, array $options) return static::CODE_SUCCESS; } - $process = new Process($command, $this->config->getPathToRoot(), null, null, 4800); + $process = new Process(explode(' ', $command), $this->config->getPathToRoot()); + $process->setTimeout($this->config->getProcessTimeout()); $process->run(function ($type, $buffer) { echo $buffer; }); return $process->getExitCode(); } + + /** + * @param string $directory + * + * @return string + */ + protected function resolveRulesetPath(string $directory): string + { + $rulesetFilepath = $directory . static::CUSTOM_RULESET; + + if (file_exists($rulesetFilepath) === true) { + return $rulesetFilepath; + } + + return $this->getArchitectureStandard($rulesetFilepath); + } + + /** + * @param string $path + * + * @return string + */ + protected function getArchitectureStandard(string $path): string + { + $standardConfig = $this->config->getArchitectureStandard(); + if (!$this->config->isStandaloneMode()) { + return $standardConfig; + } + + $configPath = $path . static::CONFIG_LOCAL; + if (file_exists($configPath)) { + return $configPath; + } + + return $standardConfig; + } } diff --git a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Controversial/CamelCaseMethodName.php b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Controversial/CamelCaseMethodName.php index 2ef7cd2c..6e8f8854 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Controversial/CamelCaseMethodName.php +++ b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Controversial/CamelCaseMethodName.php @@ -44,7 +44,7 @@ class CamelCaseMethodName extends AbstractRule implements MethodAware '_beforeStep', '_afterStep', '_before', - '_before', + '_after', '_depends', '_inject', ]; @@ -60,13 +60,13 @@ class CamelCaseMethodName extends AbstractRule implements MethodAware public function apply(AbstractNode $node) { $methodName = $node->getName(); - if (!in_array($methodName, $this->ignoredMethods)) { + if (!in_array($methodName, $this->ignoredMethods, true)) { if (!$this->isValid($methodName)) { $this->addViolation( $node, [ $methodName, - ] + ], ); } } @@ -75,18 +75,18 @@ public function apply(AbstractNode $node) /** * @param string $methodName * - * @return int + * @return bool */ private function isValid($methodName) { if ($this->getBooleanProperty('allow-underscore-test') && strpos($methodName, 'test') === 0) { - return preg_match('/^test[a-zA-Z0-9]*([_][a-z][a-zA-Z0-9]*)?$/', $methodName); + return (bool)preg_match('/^test[a-zA-Z0-9]*([_][a-z][a-zA-Z0-9]*)?$/', $methodName); } if ($this->getBooleanProperty('allow-underscore')) { - return preg_match('/^[_]?[a-z][a-zA-Z0-9]*$/', $methodName); + return (bool)preg_match('/^[_]?[a-z][a-zA-Z0-9]*$/', $methodName); } - return preg_match('/^[a-z][a-zA-Z0-9]*$/', $methodName); + return (bool)preg_match('/^[a-z][a-zA-Z0-9]*$/', $methodName); } } diff --git a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjects.php b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjects.php index 1de2c94d..82badda4 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjects.php +++ b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjects.php @@ -13,7 +13,14 @@ class CouplingBetweenObjects extends AbstractRule implements ClassAware { + /** + * @var string + */ public const COUPLING_BETWEEN_OBJECTS = 'cbo'; + + /** + * @var string + */ public const THRESHOLD = 'minimum'; /** diff --git a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildren.php b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildren.php index 5bebb543..dd58dfa7 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildren.php +++ b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildren.php @@ -13,7 +13,14 @@ class NumberOfChildren extends AbstractRule implements ClassAware { + /** + * @var string + */ public const NUMBER_OF_CHILDREN = 'nocc'; + + /** + * @var string + */ public const THRESHOLD = 'minimum'; /** @@ -41,12 +48,12 @@ public function apply(AbstractNode $node) /** * @param \PHPMD\AbstractNode $node * - * @return int + * @return bool */ private function isIgnorable(AbstractNode $node) { $fullyQualifiedClassName = $node->getFullQualifiedName(); - return preg_match('/Zed\\\\Importer\\\\Business\\\\(Importer|Installer)\\\\Abstract(Importer|Installer)/', $fullyQualifiedClassName); + return (bool)preg_match('/Zed\\\\Importer\\\\Business\\\\(Importer|Installer)\\\\Abstract(Importer|Installer)/', $fullyQualifiedClassName); } } diff --git a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethods.php b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethods.php index 18acf3d1..a8001882 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethods.php +++ b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethods.php @@ -14,7 +14,14 @@ class TooManyMethods extends AbstractRule implements ClassAware { + /** + * @var string + */ public const MAX_METHODS = 'maxmethods'; + + /** + * @var string + */ public const METHODS_IGNORE_PATTERN = 'ignorepattern'; /** @@ -22,7 +29,7 @@ class TooManyMethods extends AbstractRule implements ClassAware * * @var string */ - private $ignoreRegexp; + protected $ignoreRegexp; /** * This method checks the number of methods with in a given class and checks diff --git a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethods.php b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethods.php index 71c7d3c5..7104ef59 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethods.php +++ b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethods.php @@ -14,7 +14,14 @@ class TooManyPublicMethods extends AbstractRule implements ClassAware { + /** + * @var string + */ public const NUMBER_OF_PUBLIC_METHODS = 'npm'; + + /** + * @var string + */ public const THRESHOLD = 'maxmethods'; /** @@ -22,7 +29,7 @@ class TooManyPublicMethods extends AbstractRule implements ClassAware * * @var string */ - private $ignoreRegexp; + protected $ignoreRegexp; /** * This method checks the number of public methods with in a given class and checks @@ -82,6 +89,6 @@ private function countMethods(AbstractTypeNode $node) */ private function isIgnorable(AbstractNode $node) { - return (preg_match('/(Client|Yves|Zed)\\\\(.*?)\\\\(.*?)Facade/', $node->getFullQualifiedName()) || preg_match('/(Factory)/', $node->getName())); + return (bool)preg_match('/(Client|Yves|Zed)\\\\(.*?)\\\\(.*?)Facade/', $node->getFullQualifiedName()) || preg_match('/(Factory)/', $node->getName()); } } diff --git a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php index 5c154f32..9ea6108b 100644 --- a/src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php +++ b/src/Spryker/Zed/Development/Business/PhpMd/Rules/Naming/ShortVariable.php @@ -62,7 +62,7 @@ private function isInExceptionList(AbstractNode $node) { $exceptions = $this->getExceptionsList(); - if (in_array(substr($node->getImage(), 1), $exceptions)) { + if (in_array(substr($node->getImage(), 1), $exceptions, true)) { return true; } @@ -87,9 +87,9 @@ private function isCestFile(AbstractNode $node) /** * Gets array of exceptions from property * - * @return string[] + * @return array */ - private function getExceptionsList() + protected function getExceptionsList() { try { $exceptions = $this->getStringProperty('exceptions'); @@ -109,7 +109,7 @@ private function getExceptionsList() * * @return bool */ - private function isNameAllowedInContext(AbstractNode $node) + protected function isNameAllowedInContext(AbstractNode $node) { return $this->isChildOf($node, 'CatchStatement') || $this->isChildOf($node, 'ForInit') @@ -126,8 +126,9 @@ private function isNameAllowedInContext(AbstractNode $node) * * @return bool */ - private function isChildOf(AbstractNode $node, $type) + protected function isChildOf(AbstractNode $node, $type) { + /** @var \PHPMD\Node\ASTNode|null $parent */ $parent = $node->getParent(); while (is_object($parent)) { if ($parent->isInstanceOf($type)) { diff --git a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileFinder.php b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileFinder.php index 8bc5c818..a2474503 100644 --- a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileFinder.php +++ b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileFinder.php @@ -55,7 +55,10 @@ protected function getConfigFile(): ?SplFileInfo return null; } - return iterator_to_array($this->finder, false)[0]; + $finderAsArray = iterator_to_array($this->finder, false); + + /** @phpstan-var \SplFileInfo */ + return reset($finderAsArray); } /** diff --git a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManager.php b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManager.php index e7786fe1..1882f6c3 100644 --- a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManager.php +++ b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManager.php @@ -16,32 +16,43 @@ class PhpstanConfigFileManager implements PhpstanConfigFileManagerInterface /** * @var \Symfony\Component\Filesystem\Filesystem */ - protected $filesystem; + protected Filesystem $filesystem; /** * @var \Spryker\Zed\Development\DevelopmentConfig */ - protected $config; + protected DevelopmentConfig $config; /** * @var \Nette\DI\Config\Loader */ - protected $configLoader; + protected Loader $configLoader; + + /** + * @var \Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileSaverInterface + */ + protected PhpstanConfigFileSaverInterface $phpstanConfigFileSaver; /** * @param \Symfony\Component\Filesystem\Filesystem $filesystem * @param \Spryker\Zed\Development\DevelopmentConfig $config * @param \Nette\DI\Config\Loader $configLoader + * @param \Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileSaverInterface $phpstanConfigFileSaver */ - public function __construct(Filesystem $filesystem, DevelopmentConfig $config, Loader $configLoader) - { + public function __construct( + Filesystem $filesystem, + DevelopmentConfig $config, + Loader $configLoader, + PhpstanConfigFileSaverInterface $phpstanConfigFileSaver + ) { $this->filesystem = $filesystem; $this->config = $config; $this->configLoader = $configLoader; + $this->phpstanConfigFileSaver = $phpstanConfigFileSaver; } /** - * @param \SplFileInfo[] $configFiles + * @param array<\SplFileInfo> $configFiles * @param string $newConfigFileName * * @return string @@ -72,7 +83,7 @@ public function deleteConfigFile(string $configFilePath): void } /** - * @param \SplFileInfo[] $configFiles + * @param array<\SplFileInfo> $configFiles * * @return array */ @@ -113,7 +124,10 @@ protected function saveConfig(string $newConfigFileName, array $mergedConfig): s } $newConfigFilePath = $directory . $newConfigFileName; - $this->configLoader->save($mergedConfig, $newConfigFilePath . $this->config->getPhpstanConfigFilename()); + $this->phpstanConfigFileSaver->save( + $newConfigFilePath . $this->config->getPhpstanConfigFilename(), + $mergedConfig, + ); return $newConfigFilePath; } diff --git a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManagerInterface.php b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManagerInterface.php index 574bcbc3..1aaa74f6 100644 --- a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManagerInterface.php +++ b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileManagerInterface.php @@ -10,7 +10,7 @@ interface PhpstanConfigFileManagerInterface { /** - * @param \SplFileInfo[] $configFiles + * @param array<\SplFileInfo> $configFiles * @param string $newConfigFileName * * @return string diff --git a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileSaver.php b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileSaver.php new file mode 100644 index 00000000..fedef21f --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileSaver.php @@ -0,0 +1,77 @@ + + */ + protected array $fileAdapters; + + /** + * @param array $fileAdapters + */ + public function __construct(array $fileAdapters = []) + { + $this->fileAdapters = $fileAdapters; + } + + /** + * @param string $configFilePath + * @param array $data + * + * @throws \RuntimeException + * + * @return void + */ + public function save(string $configFilePath, array $data): void + { + if (file_put_contents($configFilePath, $this->getAdapter($configFilePath)->dump($data)) === false) { + throw new RuntimeException(sprintf(static::ERROR_CANNOT_WRITE_FILE, $configFilePath)); + } + } + + /** + * @param string $filePath + * + * @throws \InvalidArgumentException + * + * @return \Nette\DI\Config\Adapter + */ + protected function getAdapter(string $filePath): Adapter + { + $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); + if (!isset($this->fileAdapters[$extension])) { + throw new InvalidArgumentException(sprintf(static::ERROR_UNKNOWN_FILE_EXTENSION, $filePath)); + } + + if ($this->fileAdapters[$extension] instanceof Adapter) { + return $this->fileAdapters[$extension]; + } + + /** @var \Nette\DI\Config\Adapter $adapter */ + $adapter = new $this->fileAdapters[$extension](); + + return $adapter; + } +} diff --git a/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileSaverInterface.php b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileSaverInterface.php new file mode 100644 index 00000000..2f6c2132 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Phpstan/Config/PhpstanConfigFileSaverInterface.php @@ -0,0 +1,19 @@ + $data + * + * @return void + */ + public function save(string $configFilePath, array $data): void; +} diff --git a/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php b/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php index 951ff1f3..2cc67365 100644 --- a/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php +++ b/src/Spryker/Zed/Development/Business/Phpstan/PhpstanRunner.php @@ -7,8 +7,13 @@ namespace Spryker\Zed\Development\Business\Phpstan; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use RecursiveRegexIterator; +use RegexIterator; use RuntimeException; use SplFileInfo; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface; use Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileFinderInterface; use Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileManagerInterface; use Spryker\Zed\Development\Business\Traits\PathTrait; @@ -16,27 +21,76 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; -use Symfony\Component\Process\Process; -use Zend\Filter\FilterChain; -use Zend\Filter\StringToLower; -use Zend\Filter\Word\CamelCaseToDash; class PhpstanRunner implements PhpstanRunnerInterface { use PathTrait; - public const NAMESPACE_SPRYKER_SHOP = 'SprykerShop'; + /** + * @var string + */ public const NAMESPACE_SPRYKER = 'Spryker'; + /** + * @var string + */ public const DEFAULT_LEVEL = 'defaultLevel'; - public const MEMORY_LIMIT = '512M'; + + /** + * @var string + */ + public const MEMORY_LIMIT = '-1'; + + /** + * @var int + */ public const CODE_SUCCESS = 0; - public const CODE_ERROR = 0; + /** + * @var string + */ public const OPTION_DRY_RUN = 'dry-run'; + + /** + * @var string + */ public const OPTION_VERBOSE = 'verbose'; + + /** + * @var string + */ public const OPTION_MODULE = 'module'; + /** + * @var string + */ + public const OPTION_LEVEL = 'level'; + + /** + * @var string + */ + public const OPTION_OFFSET = 'offset'; + + /** + * @var string + */ + public const OPTION_IS_MERGABLE_CONFIG = 'is-mergable-config'; + + /** + * @var int + */ + protected const SUCCESS_EXIT_CODE = 0; + + /** + * @var int + */ + protected const ERROR_EXIT_CODE = 1; + + /** + * @var string + */ + protected const PHPSTAN_MEMORY_LIMIT = '4000M'; + /** * @var \Spryker\Zed\Development\DevelopmentConfig */ @@ -52,6 +106,11 @@ class PhpstanRunner implements PhpstanRunnerInterface */ protected $phpstanConfigFileManager; + /** + * @var \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface $nameNormalizer + */ + protected NameNormalizerInterface $nameNormalizer; + /** * @var int */ @@ -61,45 +120,35 @@ class PhpstanRunner implements PhpstanRunnerInterface * @param \Spryker\Zed\Development\DevelopmentConfig $config * @param \Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileFinderInterface $phpstanConfigFileFinder * @param \Spryker\Zed\Development\Business\Phpstan\Config\PhpstanConfigFileManagerInterface $phpstanConfigFileManager + * @param \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface $nameNormalizer */ public function __construct( DevelopmentConfig $config, PhpstanConfigFileFinderInterface $phpstanConfigFileFinder, - PhpstanConfigFileManagerInterface $phpstanConfigFileManager + PhpstanConfigFileManagerInterface $phpstanConfigFileManager, + NameNormalizerInterface $nameNormalizer ) { $this->config = $config; $this->phpstanConfigFileFinder = $phpstanConfigFileFinder; $this->phpstanConfigFileManager = $phpstanConfigFileManager; + $this->nameNormalizer = $nameNormalizer; } /** * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * - * @throws \RuntimeException - * * @return int Exit code */ public function run(InputInterface $input, OutputInterface $output) { + /** @var string|null $module */ $module = $input->getOption(static::OPTION_MODULE); - $message = 'Run PHPStan in PROJECT level'; - if ($module) { - $message = 'Run PHPStan in module ' . $module; - } - + $message = $this->buildMessage($module); $output->writeln($message); - if ($module) { - $paths = $this->getPaths($module); - } else { - $paths[$this->config->getPathToRoot()] = $this->config->getPathToRoot(); - } - if (empty($paths)) { - throw new RuntimeException('No path found for module ' . $module); - } - + $paths = $this->getPathsToAnalyze($module, $input); $resultCode = 0; $count = 0; $total = count($paths); @@ -108,13 +157,21 @@ public function run(InputInterface $input, OutputInterface $output) asort($paths); foreach ($paths as $path => $configFilePath) { - $resultCode |= $this->runCommand($path, $configFilePath, $input, $output); $count++; + if ($this->skip($count, $input)) { + continue; + } + + $time = time(); + $resultCode |= $this->runCommand($path, $configFilePath, $input, $output); + $passedTime = time() - $time; + if ($input->getOption(static::OPTION_VERBOSE)) { - $output->writeln(sprintf('Finished %s/%s.', $count, $total)); + $output->writeln(sprintf('Finished %s/%s (%s).', $count, $total, $passedTime . 's')); } } - if ($this->errorCount) { + + if ($this->getErrorCount()) { $output->writeln('Total errors found: ' . $this->errorCount . ''); } @@ -129,66 +186,161 @@ public function run(InputInterface $input, OutputInterface $output) * * @return int Exit code */ - protected function runCommand($path, $configFilePath, InputInterface $input, OutputInterface $output) - { - $command = 'php -d memory_limit=%s vendor/bin/phpstan analyze --no-progress -c %s %s -l %s'; - - $defaultLevel = $this->getDefaultLevel($path, $configFilePath); - $level = $input->getOption('level'); - if (preg_match('/^([+])(\d)$/', $level, $matches)) { - $level = $defaultLevel + (int)$matches[2]; - } else { - $level = (int)$level ?: $defaultLevel; - } + protected function runCommand( + string $path, + string $configFilePath, + InputInterface $input, + OutputInterface $output + ): int { + $command = 'php -d memory_limit=%s vendor/bin/phpstan analyze --memory-limit=%s --no-progress -c %s %s -l %s'; + $level = $this->getLevel($input, $path, $configFilePath); if (is_dir($path . 'src')) { $path .= 'src' . DIRECTORY_SEPARATOR; } + if (!$this->needsRun($path)) { + if ($output->isVerbose()) { + $output->writeln(sprintf('Skipping %s (no PHP files found)', $path)); + } + + return static::CODE_SUCCESS; + } + $configFilePath .= $this->config->getPhpstanConfigFilename(); - $command = sprintf($command, static::MEMORY_LIMIT, $configFilePath, $path, $level); + $command = sprintf( + $command, + static::MEMORY_LIMIT, + static::PHPSTAN_MEMORY_LIMIT, + $configFilePath, + $path, + $level, + ); if ($input->getOption(static::OPTION_DRY_RUN)) { $output->writeln($command); + return static::CODE_SUCCESS; } - $output->writeln(sprintf('Checking %s (level %s)', $path, $level)); - - $process = $this->getProcess($command); - $process->run(function ($type, $buffer) use ($output) { - $this->addErrors($buffer); + if ($output->isVerbose()) { + $output->writeln(sprintf('Checking %s (level %s)', $path, $level)); + } - $output->write($buffer); - }); + $commandResult = $this->executeCommand($command, $output, $path); if ($this->phpstanConfigFileManager->isMergedConfigFile($configFilePath)) { $this->phpstanConfigFileManager->deleteConfigFile($configFilePath); } - return $process->getExitCode(); + return $commandResult; } /** * @param string $command + * @param \Symfony\Component\Console\Output\OutputInterface $output + * @param string $path + * + * @return int + */ + protected function executeCommand( + string $command, + OutputInterface $output, + string $path + ): int { + gc_collect_cycles(); + gc_mem_caches(); + + $execResult = exec($command, $execOutput); + $outputBuffer = implode(PHP_EOL, $execOutput); + + if ($execResult !== false) { + $this->addErrors($outputBuffer); + preg_match('#\[ERROR\] Found (\d+) error#i', $outputBuffer, $matches); + + if (!$matches) { + return static::SUCCESS_EXIT_CODE; + } + } + + $output->write($outputBuffer); + + if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) { + $module = str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $path); + $output->writeln(sprintf('Errors in module %s', $module)); + } + + return static::ERROR_EXIT_CODE; + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param string $path + * @param string $configFilePath * - * @return \Symfony\Component\Process\Process + * @return int */ - protected function getProcess($command) + protected function getLevel(InputInterface $input, string $path, string $configFilePath): int { - return new Process($command, null, null, null, 0); + $defaultLevel = $this->getDefaultLevel($path, $configFilePath); + /** @var string|null $level */ + $level = $input->getOption(static::OPTION_LEVEL); + + if ($level === null) { + return $defaultLevel; + } + + if (preg_match('/^([+])(\d)$/', $level, $matches)) { + return $defaultLevel + (int)$matches[2]; + } + + return (int)$level ?: $defaultLevel; + } + + /** + * @param string|bool|null $module + * @param \Symfony\Component\Console\Input\InputInterface $input + * + * @throws \RuntimeException + * + * @return array + */ + protected function getPathsToAnalyze($module, InputInterface $input): array + { + if (is_string($module) && $module) { + $paths = $this->getPaths($module, $input); + + if (!$paths) { + throw new RuntimeException('No path found for module ' . $module); + } + + return $paths; + } + + return [ + $this->config->getPathToRoot() => $this->config->getPathToRoot(), + ]; + } + + /** + * @return int + */ + protected function getErrorCount(): int + { + return $this->errorCount; } /** * @param string $module + * @param \Symfony\Component\Console\Input\InputInterface $input * * @return array */ - protected function getPaths($module) + protected function getPaths($module, InputInterface $input) { if (strpos($module, '.') !== false) { - $paths = $this->resolveCorePaths($module); + $paths = $this->resolveCorePaths($module, $input); } else { $paths = $this->resolveProjectPaths($module); } @@ -196,6 +348,80 @@ protected function getPaths($module) return $paths; } + /** + * @param string $module + * @param \Symfony\Component\Console\Input\InputInterface $input + * + * @throws \RuntimeException + * + * @return array + */ + protected function resolveCorePaths($module, InputInterface $input) + { + $paths = []; + [$namespace, $module] = explode('.', $module, 2); + + $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); + if ($namespace !== null && $pathToInternalNamespace === null) { + return $this->resolveCommonModulePath([], $module, $namespace, $input); + } + + if ($module === 'all') { + if ($pathToInternalNamespace === null) { + throw new RuntimeException('Namespace invalid: ' . $namespace); + } + + return $this->resolveCoreModules($paths, $pathToInternalNamespace, $namespace, $input); + } + + if ($pathToInternalNamespace && is_dir($pathToInternalNamespace . $module)) { + return $this->addPath($paths, $pathToInternalNamespace . $module . DIRECTORY_SEPARATOR, $namespace, $input); + } + + return $this->resolveCommonModulePath($paths, $module, $namespace, $input); + } + + /** + * @param array $paths + * @param string $pathToInternalNamespace + * @param string $namespace + * @param \Symfony\Component\Console\Input\InputInterface $input + * + * @return array + */ + protected function resolveCoreModules(array $paths, string $pathToInternalNamespace, string $namespace, InputInterface $input): array + { + $modules = $this->getCoreModules($pathToInternalNamespace); + foreach ($modules as $module) { + $path = $pathToInternalNamespace . $module . DIRECTORY_SEPARATOR; + $paths = $this->addPath($paths, $path, $namespace, $input); + } + + return $paths; + } + + /** + * @param array $paths + * @param string|null $module + * @param string|null $namespace + * @param \Symfony\Component\Console\Input\InputInterface $input + * + * @return array + */ + protected function resolveCommonModulePath(array $paths, ?string $module, ?string $namespace, InputInterface $input): array + { + $moduleVendor = $this->nameNormalizer->dasherize($namespace); + $module = $this->nameNormalizer->dasherize($module); + $path = sprintf( + '%s/vendor/%s/%s/', + $this->config->getPathToRoot(), + $moduleVendor, + $module, + ); + + return $this->addPath($paths, $path, $namespace, $input); + } + /** * @param string $module * @param string|null $pathSuffix @@ -205,7 +431,7 @@ protected function getPaths($module) protected function resolveProjectPaths($module, $pathSuffix = null) { $projectNamespaces = $this->config->getProjectNamespaces(); - $namespaces = array_merge(DevelopmentConfig::APPLICATION_NAMESPACES, $projectNamespaces); + $namespaces = array_merge($this->config->getApplicationNamespaces(), $projectNamespaces); $pathToRoot = $this->config->getPathToRoot(); $paths = []; @@ -214,6 +440,7 @@ protected function resolveProjectPaths($module, $pathSuffix = null) foreach (DevelopmentConfig::APPLICATIONS as $layer) { $layerPath = $path . $layer . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR; + if ($pathSuffix) { $layerPath .= $pathSuffix; } @@ -222,7 +449,7 @@ protected function resolveProjectPaths($module, $pathSuffix = null) continue; } - $paths[$layerPath] = null; + $paths[$layerPath] = $pathToRoot; } } @@ -230,15 +457,16 @@ protected function resolveProjectPaths($module, $pathSuffix = null) } /** - * @param array $paths + * @param array $paths * @param string $moduleDirectoryPath * @param string|null $namespace + * @param \Symfony\Component\Console\Input\InputInterface $input * - * @return array + * @return array */ - protected function addPath(array $paths, string $moduleDirectoryPath, $namespace = null): array + protected function addPath(array $paths, string $moduleDirectoryPath, $namespace, InputInterface $input): array { - $paths[$moduleDirectoryPath] = $this->getConfigFilePathByModuleDirectory($moduleDirectoryPath, $namespace); + $paths[$moduleDirectoryPath] = $this->getConfigFilePathByModuleDirectory($moduleDirectoryPath, $namespace, $input); return $paths; } @@ -246,10 +474,11 @@ protected function addPath(array $paths, string $moduleDirectoryPath, $namespace /** * @param string $moduleDirectoryPath * @param string|null $namespace + * @param \Symfony\Component\Console\Input\InputInterface $input * * @return string */ - protected function getConfigFilePathByModuleDirectory(string $moduleDirectoryPath, $namespace = null): string + protected function getConfigFilePathByModuleDirectory(string $moduleDirectoryPath, $namespace, InputInterface $input): string { $moduleConfigFile = $this->phpstanConfigFileFinder ->searchIn($moduleDirectoryPath); @@ -259,10 +488,12 @@ protected function getConfigFilePathByModuleDirectory(string $moduleDirectoryPat $vendorConfigFile = $this->phpstanConfigFileFinder ->searchIn($vendorDirectoryPath); - if ($moduleConfigFile && $vendorConfigFile) { + $isMergable = $input->getOption(static::OPTION_IS_MERGABLE_CONFIG); + + if ($moduleConfigFile && $vendorConfigFile && $isMergable === true) { return $this->phpstanConfigFileManager->merge( [$moduleConfigFile, $vendorConfigFile], - $this->getConfigFilenameForMerge($moduleConfigFile) + $this->getConfigFilenameForMerge($moduleConfigFile), ); } @@ -290,9 +521,9 @@ protected function getConfigFilenameForMerge(SplFileInfo $moduleConfigFile): ?st array_slice( explode('/', $moduleConfigFile->getPath()), -3, - 3 - ) - ) + 3, + ), + ), ); return $filenameFromPath . '_'; @@ -314,61 +545,6 @@ protected function getVendorPathByNamespace(string $namespace): ?string return dirname($pathToModules) . DIRECTORY_SEPARATOR; } - /** - * @param string $module - * - * @throws \RuntimeException - * - * @return array - */ - protected function resolveCorePaths($module) - { - $paths = []; - [$namespace, $module] = explode('.', $module, 2); - - if ($module === 'all') { - $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); - if ($pathToInternalNamespace === null) { - throw new RuntimeException('Namespace invalid: ' . $namespace); - } - - $modules = $this->getCoreModules($pathToInternalNamespace); - foreach ($modules as $module) { - $path = $pathToInternalNamespace . $module . DIRECTORY_SEPARATOR; - $paths = $this->addPath($paths, $path, $namespace); - } - - return $paths; - } - - $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); - if ($pathToInternalNamespace && is_dir($pathToInternalNamespace . $module)) { - return $this->addPath($paths, $pathToInternalNamespace . $module . DIRECTORY_SEPARATOR, $namespace); - } - - $vendor = $this->dasherize($namespace); - $module = $this->dasherize($module); - $path = $this->config->getPathToRoot() . 'vendor' . DIRECTORY_SEPARATOR . $vendor . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR; - $paths = $this->addPath($paths, $path, $namespace); - - return $paths; - } - - /** - * @param string $name - * - * @return string - */ - protected function dasherize($name) - { - $filterChain = new FilterChain(); - $filterChain - ->attach(new CamelCaseToDash()) - ->attach(new StringToLower()); - - return $filterChain->filter($name); - } - /** * @param string $path * @@ -376,11 +552,12 @@ protected function dasherize($name) */ protected function getCoreModules($path) { - /** @var \Symfony\Component\Finder\SplFileInfo[] $directories */ + /** @var array<\Symfony\Component\Finder\SplFileInfo> $directories */ $directories = (new Finder()) ->directories() ->in($path) - ->depth('== 0'); + ->depth('== 0') + ->sortByName(); $modules = []; foreach ($directories as $dir) { @@ -394,6 +571,8 @@ protected function getCoreModules($path) * @param string $path * @param string $fallbackPath * + * @throws \RuntimeException + * * @return int */ protected function getDefaultLevel($path, $fallbackPath) @@ -407,14 +586,28 @@ protected function getDefaultLevel($path, $fallbackPath) $configFile = $directory . 'phpstan.json'; } + $neonLevel = $this->neonConfigLevel($path); if (!file_exists($configFile)) { - return $configLevel; + return $neonLevel ?: $configLevel; } + /** @var string $content */ $content = file_get_contents($configFile); $json = json_decode($content, true); + if (!isset($json[static::DEFAULT_LEVEL])) { + return $neonLevel ?: $configLevel; + } + + $definedMinimumLevel = $json[static::DEFAULT_LEVEL]; + if (!$neonLevel && !$definedMinimumLevel) { + return $configLevel; + } - return $json[static::DEFAULT_LEVEL]; + if ($neonLevel && $definedMinimumLevel && $neonLevel !== $definedMinimumLevel) { + throw new RuntimeException('Can\'t resolve level from both neon and json file, as they differ.'); + } + + return $neonLevel ?: $definedMinimumLevel; } /** @@ -430,4 +623,94 @@ protected function addErrors(string $buffer): void } $this->errorCount += (int)$matches[1]; } + + /** + * Determines 1-based skipping as per `offset[,limit]` config. + * + * @param int $count + * @param \Symfony\Component\Console\Input\InputInterface $input + * + * @return bool + */ + protected function skip(int $count, InputInterface $input): bool + { + $limit = null; + /** @var string|null $offset */ + $offset = $input->getOption(static::OPTION_OFFSET); + if ($offset && strpos($offset, ',') !== false) { + [$offset, $limit] = explode(',', $offset); + } + $limit = (int)$limit; + $offset = (int)$offset; + if (!$limit && !$offset) { + return false; + } + + if ($offset && $count <= $offset) { + return true; + } + if ($limit && $count > ($limit + $offset)) { + return true; + } + + return false; + } + + /** + * @param string $path + * + * @return int|null + */ + protected function neonConfigLevel(string $path): ?int + { + $file = $path . 'phpstan.neon'; + if (!file_exists($file)) { + return null; + } + + /** @var string $content */ + $content = file_get_contents($file); + preg_match('/\blevel:\s*(\d)\b/', $content, $matches); + if (!$matches) { + return null; + } + + return (int)$matches[1] ?: null; + } + + /** + * @param string $path + * + * @return bool + */ + protected function needsRun(string $path): bool + { + $directoryIterator = new RecursiveDirectoryIterator($path); + $recursiveIterator = new RecursiveIteratorIterator($directoryIterator); + $regexIterator = new RegexIterator($recursiveIterator, '#\.php$#', RecursiveRegexIterator::GET_MATCH); + foreach ($regexIterator as $file) { + return true; + } + + return false; + } + + /** + * @param string|null $module + * + * @return string + */ + protected function buildMessage(?string $module = null): string + { + $message = 'Run PHPStan in '; + if ($this->config->isStandaloneMode()) { + return $message . 'Standalone Mode'; + } + + if ($module !== null) { + return $message . 'module ' . $module; + } + + return $message . 'PROJECT level'; + } } diff --git a/src/Spryker/Zed/Development/Business/Propel/PropelAbstractClassValidator.php b/src/Spryker/Zed/Development/Business/Propel/PropelAbstractClassValidator.php index 24e1c0af..64ad890c 100644 --- a/src/Spryker/Zed/Development/Business/Propel/PropelAbstractClassValidator.php +++ b/src/Spryker/Zed/Development/Business/Propel/PropelAbstractClassValidator.php @@ -8,12 +8,12 @@ namespace Spryker\Zed\Development\Business\Propel; use Exception; +use Laminas\Filter\FilterChain; +use Laminas\Filter\Word\UnderscoreToCamelCase; use SimpleXMLElement; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; -use Zend\Filter\FilterChain; -use Zend\Filter\Word\UnderscoreToCamelCase; class PropelAbstractClassValidator implements PropelAbstractClassValidatorInterface { @@ -57,7 +57,10 @@ protected function validateModules(OutputInterface $output): bool protected function getModuleNames(): array { $finder = new Finder(); - $finder->directories()->in(APPLICATION_VENDOR_DIR . '/spryker/spryker/Bundles/')->depth('< 1'); + $finder->directories()->in([ + APPLICATION_VENDOR_DIR . '/spryker/spryker/Bundles/', + APPLICATION_VENDOR_DIR . '/spryker/spryker/Features/', + ])->depth('< 1'); $modules = []; @@ -83,16 +86,26 @@ protected function validateModule(OutputInterface $output, string $module): bool } $moduleSchemaFileFinder = $this->getModuleSchemaFileFinder($module); - $isModuleValid = true; - foreach ($moduleSchemaFileFinder as $schemaFile) { - $isValid = $this->abstractClassesForTablesExist($output, $module, $schemaFile); - if (!$isValid) { - $isModuleValid = false; + if (is_dir($schemaFile->getPathname())) { + $moduleNestedSchemaFileFinder = new Finder(); + $moduleNestedSchemaFileFinder->in($schemaFile->getPathname()); + + foreach ($moduleNestedSchemaFileFinder as $nestedSchemaFile) { + if (!$this->abstractClassesForTablesExist($output, $module, $nestedSchemaFile)) { + return false; + } + } + + continue; + } + + if (!$this->abstractClassesForTablesExist($output, $module, $schemaFile)) { + return false; } } - return $isModuleValid; + return true; } /** @@ -127,7 +140,10 @@ protected function getModuleSchemaFileFinder(string $module) */ protected function getPathToModuleSchemas(string $module): string { - return sprintf('%1$s/spryker/spryker/Bundles/%2$s/src/Spryker/Zed/%2$s/Persistence/Propel/Schema/', APPLICATION_VENDOR_DIR, $module); + $bundlePath = sprintf('%1$s/spryker/spryker/Bundles/%2$s/src/Spryker/Zed/%2$s/Persistence/Propel/Schema/', APPLICATION_VENDOR_DIR, $module); + $featurePath = sprintf('%1$s/spryker/spryker/Features/%2$s/src/SprykerFeature/Zed/%2$s/Persistence/Propel/Schema/', APPLICATION_VENDOR_DIR, $module); + + return is_dir($featurePath) ? $featurePath : $bundlePath; } /** @@ -147,8 +163,9 @@ protected function abstractClassesForTablesExist(OutputInterface $output, string throw new Exception('Could not load xml file'); } - $simpleXmlTableElements = $simpleXmlElement->xpath('//table'); - if ($simpleXmlTableElements === false) { + $simpleXmlTableElements = $this->getSimpleXmlTableElements($simpleXmlElement); + + if (!$simpleXmlTableElements) { throw new Exception('No table found in '); } @@ -165,7 +182,21 @@ protected function abstractClassesForTablesExist(OutputInterface $output, string } /** - * @param \SimpleXMLElement[] $simpleXmlTableElements + * @param \SimpleXMLElement $simpleXmlElement + * + * @return bool + */ + protected function hasNamespaceInSchema(SimpleXMLElement $simpleXmlElement): bool + { + if (in_array('spryker:schema-01', $simpleXmlElement->getNamespaces(), true)) { + return true; + } + + return false; + } + + /** + * @param array<\SimpleXMLElement> $simpleXmlTableElements * @param string $module * @param \Symfony\Component\Console\Output\OutputInterface $output * @@ -180,17 +211,19 @@ protected function abstractClassesForTableExists(array $simpleXmlTableElements, $tableName = $this->getTableNameFromSimpleXmlTableElement($simpleXmlTableElement); $abstractEntityClass = sprintf('Spryker\\Zed\\%s\\Persistence\\Propel\\Abstract%s', $module, $phpName); - if (!class_exists($abstractEntityClass)) { + $abstractFeatureEntityClass = sprintf('SprykerFeature\\Zed\\%s\\Persistence\\Propel\\Abstract%s', $module, $phpName); + if (!class_exists($abstractEntityClass) && !class_exists($abstractFeatureEntityClass)) { $isValid = false; - $output->writeln(sprintf('%s does not exists, please create one.', $abstractEntityClass)); - $output->writeln(sprintf('vendor/bin/console spryk:run AddZedPersistencePropelAbstractEntity --module=\'%1$s\' --targetModule=\'%1$s\' --tableName=\'%2$s\' -n', $module, $tableName)); + $output->writeln(sprintf('Neither %s nor %s does not exists, please create one.', $abstractEntityClass, $abstractFeatureEntityClass)); + $output->writeln(sprintf('vendor/bin/spryk-run AddZedPersistencePropelAbstractEntity --module=\'%1$s\' --targetModule=\'%1$s\' --tableName=\'%2$s\' -n', $module, $tableName)); } $abstractQueryClass = sprintf('Spryker\\Zed\\%s\\Persistence\\Propel\\Abstract%sQuery', $module, $phpName); - if (!class_exists($abstractQueryClass)) { + $abstractFeatureQueryClass = sprintf('SprykerFeature\\Zed\\%s\\Persistence\\Propel\\Abstract%sQuery', $module, $phpName); + if (!class_exists($abstractQueryClass) && !class_exists($abstractFeatureQueryClass)) { $isValid = false; - $output->writeln(sprintf('%s does not exists, please create one.', $abstractQueryClass)); - $output->writeln(sprintf('vendor/bin/console spryk:run AddZedPersistencePropelAbstractQuery --module=\'%1$s\' --targetModule=\'%1$s\' --tableName=\'%2$s\' -n', $module, $tableName)); + $output->writeln(sprintf('Neither %s nor %s does not exists, please create one.', $abstractQueryClass, $abstractFeatureQueryClass)); + $output->writeln(sprintf('vendor/bin/spryk-run AddZedPersistencePropelAbstractQuery --module=\'%1$s\' --targetModule=\'%1$s\' --tableName=\'%2$s\' -n', $module, $tableName)); } } @@ -249,4 +282,21 @@ protected function getModuleFromSchemaNamespace(SimpleXMLElement $simpleXmlEleme return $schemaModule; } + + /** + * @param \SimpleXMLElement $simpleXmlElement + * + * @return array<\SimpleXMLElement> + */ + protected function getSimpleXmlTableElements(SimpleXMLElement $simpleXmlElement) + { + if ($this->hasNamespaceInSchema($simpleXmlElement)) { + $simpleXmlElement->registerXPathNamespace('s', 'spryker:schema-01'); + + /** @phpstan-var array<\SimpleXMLElement> */ + return $simpleXmlElement->xpath('//s:table'); + } + + return $simpleXmlElement->xpath('//table'); + } } diff --git a/src/Spryker/Zed/Development/Business/Resolver/CodeStylePathResolver.php b/src/Spryker/Zed/Development/Business/Resolver/CodeStylePathResolver.php new file mode 100644 index 00000000..da2f4a8a --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Resolver/CodeStylePathResolver.php @@ -0,0 +1,313 @@ +config = $config; + $this->nameNormalizer = $nameNormalizer; + $this->codeStyleSnifferConfigurationLoader = $codeStyleSnifferConfigurationLoader; + } + + /** + * @param string|null $module + * @param string|null $namespace + * @param string|null $path + * @param array $options + * + * @return array + */ + public function resolvePaths(?string $module, ?string $namespace, ?string $path, array $options): array + { + $path = $path !== null ? trim($path, DIRECTORY_SEPARATOR) : null; + + if ($namespace !== null && $this->config->getPathToInternalNamespace($namespace) === null) { + return $this->resolveCommonModulePath($module, $namespace, $path, $options); + } + + if ($namespace) { + return $this->resolveCorePath($module, $namespace, $path, $options); + } + + if (!$module) { + return $this->addPath([], $this->config->getPathToRoot() . $path, $options); + } + + return $this->resolveProjectPath($module, $path, $options); + } + + /** + * @param string|null $module + * @param string|null $namespace + * @param string|null $path + * @param array $options + * + * @return array + */ + protected function resolveCommonModulePath(?string $module, ?string $namespace, ?string $path, array $options): array + { + $moduleVendor = $this->nameNormalizer->dasherize($namespace); + $module = $this->nameNormalizer->dasherize($module); + + $path = sprintf( + '%s/%s/%s/', + APPLICATION_VENDOR_DIR, + $moduleVendor, + $module, + ); + + return $this->addPath([], $path, $options); + } + + /** + * @param string $module + * @param string $namespace + * @param string|null $path + * @param array $options + * + * @return array + */ + protected function resolveCorePath(string $module, string $namespace, ?string $path, array $options): array + { + if ($module === 'all') { + return $this->getPathsToAllCoreModules($namespace, $path, $options); + } + + return $this->getPathToCoreModule($module, $namespace, $path, $options); + } + + /** + * @param string $module + * @param string|null $pathSuffix + * @param array $options + * + * @return array + */ + protected function resolveProjectPath(string $module, ?string $pathSuffix, array $options): array + { + $namespaces = array_merge($this->config->getApplicationNamespaces(), $this->config->getProjectNamespaces()); + $pathToRoot = $this->config->getPathToRoot(); + + $paths = []; + foreach ($namespaces as $namespace) { + $path = $pathToRoot . 'src' . DIRECTORY_SEPARATOR . $namespace . DIRECTORY_SEPARATOR; + + foreach ($this->config->getApplicationLayers() as $layer) { + $layerPath = $path . $layer . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR; + if ($pathSuffix) { + $layerPath .= $pathSuffix; + } + + if (!is_dir($layerPath)) { + continue; + } + + $paths[] = $layerPath; + } + } + + return $this->addPath([], implode(' ', $paths), $options); + } + + /** + * @param string $namespace + * @param string|null $pathSuffix + * @param array $options + * + * @throws \RuntimeException + * + * @return array + */ + protected function getPathsToAllCoreModules(string $namespace, ?string $pathSuffix, array $options): array + { + if ($pathSuffix) { + throw new RuntimeException(static::ERROR_SUFFIX_ISNT_POSSIBLE); + } + + $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); + + if (!$pathToInternalNamespace) { + throw new RuntimeException(sprintf(static::ERROR_NAMESPACE_INVALID, $namespace)); + } + + $paths = []; + $modules = $this->getCoreModules($pathToInternalNamespace); + foreach ($modules as $module) { + $path = $pathToInternalNamespace . $module . DIRECTORY_SEPARATOR; + $paths = $this->addPath($paths, $path, $options, $namespace); + } + + return $paths; + } + + /** + * @param string $module + * @param string $namespace + * @param string|null $pathSuffix + * @param array $options + * + * @throws \Spryker\Zed\Development\Business\Exception\CodeStyleSniffer\PathDoesNotExistException + * + * @return array + */ + protected function getPathToCoreModule(string $module, string $namespace, ?string $pathSuffix, array $options) + { + $path = $this->getCorePath($module, $namespace, $pathSuffix); + + if ($this->isPathValid($path)) { + return $this->addPath([], $path, $options, $namespace); + } + + $message = sprintf( + static::ERROR_NO_VALID_PATH, + $module, + $path, + ); + + throw new PathDoesNotExistException($message); + } + + /** + * @param string $module + * @param string $namespace + * @param string|null $pathSuffix + * + * @return string + */ + protected function getCorePath($module, $namespace, $pathSuffix = null): string + { + $pathToInternalNamespace = $this->config->getPathToInternalNamespace($namespace); + if ($pathToInternalNamespace && is_dir($pathToInternalNamespace . $module)) { + return $this->buildPath($pathToInternalNamespace . $module . DIRECTORY_SEPARATOR, $pathSuffix); + } + + if ($namespace === $this->config->getSprykerFeatureNamespace() && $pathToInternalNamespace && is_dir($pathToInternalNamespace)) { + return $this->buildPath($pathToInternalNamespace . DIRECTORY_SEPARATOR, $pathSuffix); + } + + $moduleVendor = $this->nameNormalizer->dasherize($namespace); + $module = $this->nameNormalizer->dasherize($module); + $path = sprintf( + '%s/vendor/%s/%s/', + $this->config->getPathToRoot(), + $moduleVendor, + $module, + ); + + return $this->buildPath($path, $pathSuffix); + } + + /** + * @param string $path + * @param string|null $suffix + * + * @return string + */ + protected function buildPath(string $path, ?string $suffix = null): string + { + if (!$suffix) { + return $path; + } + + return $path . $suffix; + } + + /** + * @param string $path + * + * @return bool + */ + protected function isPathValid(string $path): bool + { + return (is_file($path) || is_dir($path)); + } + + /** + * @param string $path + * + * @return array + */ + protected function getCoreModules(string $path): array + { + /** @var array<\Symfony\Component\Finder\SplFileInfo> $directories */ + $directories = (new Finder()) + ->directories() + ->in($path) + ->depth('== 0') + ->sortByName(); + + $modules = []; + foreach ($directories as $dir) { + $modules[] = $dir->getFilename(); + } + + return $modules; + } + + /** + * @param array $paths + * @param string $moduleDirectoryPath + * @param array $options + * @param string|null $namespace + * + * @return array + */ + protected function addPath(array $paths, string $moduleDirectoryPath, array $options, ?string $namespace = null): array + { + $paths[$moduleDirectoryPath] = clone $this->codeStyleSnifferConfigurationLoader->load($options, $moduleDirectoryPath, $namespace); + + return $paths; + } +} diff --git a/src/Spryker/Zed/Development/Business/Resolver/PathResolverInterface.php b/src/Spryker/Zed/Development/Business/Resolver/PathResolverInterface.php new file mode 100644 index 00000000..088961c5 --- /dev/null +++ b/src/Spryker/Zed/Development/Business/Resolver/PathResolverInterface.php @@ -0,0 +1,21 @@ + $options + * + * @throws \RuntimeException * * @return array */ @@ -49,11 +67,11 @@ public function getConfiguration(string $absoluteModulePath, array $options = [] $priority = $this->getPriority( $moduleConfig, - $options + $options, ); if ($priority === static::CONFIG_PRIORITY_SKIP_VALUE) { - return []; + throw new RuntimeException('Priority should be more than 0'); } $options[static::CONFIG_PRIORITY_NAME] = $priority; @@ -63,8 +81,8 @@ public function getConfiguration(string $absoluteModulePath, array $options = [] } /** - * @param array $moduleConfig - * @param array $options + * @param array $moduleConfig + * @param array $options * * @throws \Spryker\Zed\Development\Business\Exception\ArchitectureSniffer\InvalidTypeException * @@ -88,7 +106,7 @@ protected function getPriority(array $moduleConfig, array $options = []): int } /** - * @param array $moduleConfig + * @param array $moduleConfig * * @return int */ @@ -108,7 +126,7 @@ protected function getConfigPriority(array $moduleConfig): int } /** - * @param array $moduleConfig + * @param array $moduleConfig * * @return bool */ @@ -118,7 +136,7 @@ protected function architectureSnifferConfigExists(array $moduleConfig): bool } /** - * @param array $moduleConfig + * @param array $moduleConfig * * @return array */ @@ -128,7 +146,7 @@ protected function getArchitectureSnifferConfig(array $moduleConfig): array } /** - * @param array $architectureSnifferConfig + * @param array $architectureSnifferConfig * * @return bool */ @@ -138,7 +156,7 @@ protected function architectureSnifferConfigPriorityExists(array $architectureSn } /** - * @param array $architectureSnifferConfig + * @param array $architectureSnifferConfig * * @return int */ @@ -148,9 +166,9 @@ protected function getArchitectureSnifferConfigPriority(array $architectureSniff } /** - * @param array $moduleConfig + * @param array $moduleConfig * - * @return string[] + * @return array */ protected function getIgnoreErrors(array $moduleConfig): array { diff --git a/src/Spryker/Zed/Development/Business/SnifferConfiguration/Builder/SnifferConfigurationBuilderInterface.php b/src/Spryker/Zed/Development/Business/SnifferConfiguration/Builder/SnifferConfigurationBuilderInterface.php index 881b7885..4931fa57 100644 --- a/src/Spryker/Zed/Development/Business/SnifferConfiguration/Builder/SnifferConfigurationBuilderInterface.php +++ b/src/Spryker/Zed/Development/Business/SnifferConfiguration/Builder/SnifferConfigurationBuilderInterface.php @@ -11,7 +11,7 @@ interface SnifferConfigurationBuilderInterface { /** * @param string $absoluteModulePath - * @param array $options + * @param array $options * * @return array */ diff --git a/src/Spryker/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReader.php b/src/Spryker/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReader.php index ec126624..8b930de5 100644 --- a/src/Spryker/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReader.php +++ b/src/Spryker/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReader.php @@ -11,6 +11,9 @@ class ConfigurationReader implements ConfigurationReaderInterface { + /** + * @var string + */ protected const CONFIG_FILE_NAME = 'tooling.yml'; /** diff --git a/src/Spryker/Zed/Development/Business/Stability/StabilityCalculator.php b/src/Spryker/Zed/Development/Business/Stability/StabilityCalculator.php index 11b43663..c0bc64b9 100644 --- a/src/Spryker/Zed/Development/Business/Stability/StabilityCalculator.php +++ b/src/Spryker/Zed/Development/Business/Stability/StabilityCalculator.php @@ -44,7 +44,9 @@ public function __construct() */ public function calculateStability() { - $bundlesDependencies = json_decode(file_get_contents(APPLICATION_ROOT_DIR . '/data/dependencyTree.json'), true); + /** @var string $dependencyTreeContent */ + $dependencyTreeContent = file_get_contents(APPLICATION_ROOT_DIR . '/data/dependencyTree.json'); + $bundlesDependencies = json_decode($dependencyTreeContent, true); $this->bundlesDependencies = $this->filter($bundlesDependencies); @@ -116,6 +118,9 @@ protected function calculateBundlesStability() { foreach ($this->bundles as &$bundle) { $stability = count($bundle['out']) / (count($bundle['in']) + count($bundle['out'])); + $bundle['stabilityNotFormatted'] = $stability; + + /** @deprecated Exists for Backward Compatibility reasons only. Use `stabilityNotFormatted` instead. */ $bundle['stability'] = number_format($stability, 3); } } @@ -136,13 +141,16 @@ protected function calculateIndirectBundlesStability() $indirectIncomingDependencies = $indirectIncomingDependencies->getArrayCopy(); $callback = function ($bundle) use ($incomingBundles) { - return !in_array($bundle, $incomingBundles); + return !in_array($bundle, $incomingBundles, true); }; $indirectIncomingDependencies = array_filter($indirectIncomingDependencies, $callback); $this->bundles[$bundle]['indirectIn'] = $indirectIncomingDependencies; $divisor = (count($this->bundles[$bundle]['indirectIn']) + count($this->bundles[$bundle]['indirectOut'])); $indirectStability = ($divisor > 0) ? count($this->bundles[$bundle]['indirectOut']) / $divisor : 0; + $this->bundles[$bundle]['indirectStabilityNotFormatted'] = $indirectStability; + + /** @deprecated Exists for Backward Compatibility reasons only. Use `indirectStabilityNotFormatted` instead. */ $this->bundles[$bundle]['indirectStability'] = number_format($indirectStability, 3); } } @@ -154,13 +162,16 @@ protected function calculateSprykerStability() { foreach ($this->bundles as $bundle => $info) { $sprykerStability = (count($info['indirectIn']) * count($info['indirectOut'])) * (1 - abs(0.5 - $info['indirectStability'])); + $this->bundles[$bundle]['sprykerStabilityNotFormatted'] = $sprykerStability; + + /** @deprecated Exists for Backward Compatibility reasons only. Use `sprykerStabilityNotFormatted` instead. */ $this->bundles[$bundle]['sprykerStability'] = number_format($sprykerStability, 3); } } /** * @param string $bundleName - * @param \ArrayObject $indirectOutgoingDependencies + * @param \ArrayObject $indirectOutgoingDependencies * * @return void */ @@ -169,17 +180,17 @@ protected function buildIndirectOutgoingDependencies($bundleName, ArrayObject $i $dependencies = $this->bundles[$bundleName]['out']; foreach ($dependencies as $dependentBundle) { - if (array_key_exists($dependentBundle, $indirectOutgoingDependencies)) { + if ($indirectOutgoingDependencies->offsetExists($dependentBundle)) { continue; } - $indirectOutgoingDependencies[$dependentBundle] = $dependentBundle; + $indirectOutgoingDependencies->offsetSet($dependentBundle, $dependentBundle); $this->buildIndirectOutgoingDependencies($dependentBundle, $indirectOutgoingDependencies); } } /** * @param string $bundleName - * @param \ArrayObject $indirectIncomingDependencies + * @param \ArrayObject $indirectIncomingDependencies * * @return void */ @@ -188,10 +199,10 @@ protected function buildIndirectIncomingDependencies($bundleName, ArrayObject $i $dependencies = $this->bundles[$bundleName]['in']; foreach ($dependencies as $dependentBundle) { - if (array_key_exists($dependentBundle, $indirectIncomingDependencies)) { + if ($indirectIncomingDependencies->offsetExists($dependentBundle)) { continue; } - $indirectIncomingDependencies[$dependentBundle] = $dependentBundle; + $indirectIncomingDependencies->offsetSet($dependentBundle, $dependentBundle); $this->buildIndirectIncomingDependencies($dependentBundle, $indirectIncomingDependencies); } } diff --git a/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php b/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php index 09367bbe..ccd0c4bd 100644 --- a/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/AbstractCoreModuleAwareConsole.php @@ -19,21 +19,24 @@ /** * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() - * @method \Spryker\Zed\Development\Business\DevelopmentBusinessFactory getFactory() + * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class AbstractCoreModuleAwareConsole extends Console { + /** + * @var string + */ protected const ARGUMENT_MODULE = 'module'; /** - * @var \Generated\Shared\Transfer\ModuleTransfer[] + * @var array<\Generated\Shared\Transfer\ModuleTransfer> */ protected $moduleTransferCollection = []; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -54,12 +57,12 @@ protected function configure() - Organization.Application*.Module - Organization.*Application.Module -Asterisk can also be used more than once in all parts. Currently, it\'s not possible to use it in the middle of one of the parts e.g. Spryker.Foo*Bar is invalid. +Asterisk can also be used more than once in all parts. Currently, it\'s not possible to use it in the middle of one of the parts e.g. Spryker.Foo*Bar is invalid. '); } /** - * @param array $modulesToValidate + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $modulesToValidate * * @return bool */ @@ -85,7 +88,7 @@ protected function canRun(array $modulesToValidate): bool * @param \Generated\Shared\Transfer\ModuleTransfer $moduleTransfer * @param string|null $dependencyType * - * @return \ArrayObject|\Generated\Shared\Transfer\ModuleDependencyTransfer[] + * @return \ArrayObject */ protected function getModuleDependencies(ModuleTransfer $moduleTransfer, ?string $dependencyType = null): ArrayObject { @@ -99,7 +102,7 @@ protected function getModuleDependencies(ModuleTransfer $moduleTransfer, ?string } /** - * @param \Generated\Shared\Transfer\ModuleDependencyTransfer[]|\ArrayObject $moduleDependencyTransferCollection + * @param \ArrayObject $moduleDependencyTransferCollection * @param string|null $dependencyType * * @return int @@ -121,7 +124,7 @@ protected function getDependencyViolationCount(ArrayObject $moduleDependencyTran /** * @param \Symfony\Component\Console\Input\InputInterface $input * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ protected function getModulesToExecute(InputInterface $input): array { @@ -138,12 +141,13 @@ protected function getModulesToExecute(InputInterface $input): array */ protected function buildModuleFilterTransfer(): ?ModuleFilterTransfer { - if (!$this->input->getArgument(static::ARGUMENT_MODULE)) { + /** @var string|null $moduleArgument */ + $moduleArgument = $this->input->getArgument(static::ARGUMENT_MODULE); + if (!$moduleArgument) { return null; } $moduleFilterTransfer = new ModuleFilterTransfer(); - $moduleArgument = $this->input->getArgument(static::ARGUMENT_MODULE); if (strpos($moduleArgument, '.') === false) { $moduleTransfer = new ModuleTransfer(); @@ -267,7 +271,7 @@ protected function isNamespacedModuleName(string $module): bool } /** - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ protected function getModuleTransferCollection(): array { @@ -279,7 +283,7 @@ protected function getModuleTransferCollection(): array } /** - * @param array $modulesToValidate + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $modulesToValidate * * @return bool */ @@ -293,13 +297,14 @@ protected function isSingleModuleValidation(array $modulesToValidate): bool } /** - * @param array $modulesToValidate + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $modulesToValidate * * @return bool */ protected function isModuleNameValid(array $modulesToValidate): bool { $moduleTransferCollection = $this->getModuleTransferCollection(); + /** @var \Generated\Shared\Transfer\ModuleTransfer $currentModuleTransfer */ $currentModuleTransfer = current($modulesToValidate); if (!isset($moduleTransferCollection[$this->buildModuleKey($currentModuleTransfer)])) { diff --git a/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php b/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php index 9066c29d..2bd2c3a5 100644 --- a/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/CodeArchitectureSnifferConsole.php @@ -10,15 +10,13 @@ use Generated\Shared\Transfer\ModuleFilterTransfer; use Generated\Shared\Transfer\ModuleTransfer; use Generated\Shared\Transfer\OrganizationTransfer; +use Spryker\Zed\Development\Business\ArchitectureSniffer\ArchitectureSniffer; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface; use Spryker\Zed\Kernel\Communication\Console\Console; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Zend\Filter\FilterChain; -use Zend\Filter\StringToLower; -use Zend\Filter\Word\CamelCaseToDash; -use Zend\Filter\Word\UnderscoreToCamelCase; /** * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() @@ -26,23 +24,60 @@ */ class CodeArchitectureSnifferConsole extends Console { + /** + * @var string + */ protected const COMMAND_NAME = 'code:sniff:architecture'; + + /** + * @var string + */ protected const OPTION_MODULE = 'module'; + + /** + * @var string + */ protected const OPTION_STRICT = 'strict'; + + /** + * @var string + */ protected const OPTION_PRIORITY = 'priority'; + + /** + * @var string + */ protected const OPTION_DRY_RUN = 'dry-run'; + + /** + * @var string + */ protected const ARGUMENT_SUB_PATH = 'path'; + + /** + * @var string + */ protected const OPTION_VERBOSE = 'verbose'; - protected const APPLICATION_LAYERS = ['Zed', 'Client', 'Yves', 'Service', 'Shared']; - protected const NAMESPACE_SPRYKER_SHOP = 'SprykerShop'; - protected const NAMESPACE_SPRYKER = 'Spryker'; + /** + * @var string + */ protected const SOURCE_FOLDER_NAME = 'src'; + /** + * @var string + */ + protected const RUN_IN_STANDALONE_MODE = 'Run Architecture Sniffer in Standalone Mode'; + + /** + * @var \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface|null $nameNormalizer + */ + protected ?NameNormalizerInterface $nameNormalizer = null; + /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -55,6 +90,7 @@ protected function configure() $this->addOption(static::OPTION_PRIORITY, 'p', InputOption::VALUE_OPTIONAL, 'Priority [1 (highest), 2 (medium), 3 (experimental)], defaults to 2.'); $this->addOption(static::OPTION_STRICT, 's', InputOption::VALUE_NONE, 'Also report those nodes with a @SuppressWarnings annotation'); $this->addOption(static::OPTION_DRY_RUN, 'd', InputOption::VALUE_NONE, 'Dry-Run the command, display it only'); + $this->addOption(ArchitectureSniffer::OPTION_UPDATE, 'u', InputOption::VALUE_NONE, 'Update baseline'); $this->addArgument(static::ARGUMENT_SUB_PATH, InputArgument::OPTIONAL, 'Optional path or sub path element'); } @@ -67,21 +103,13 @@ protected function configure() */ public function execute(InputInterface $input, OutputInterface $output) { + /** @var string $module */ $module = $this->input->getOption(static::OPTION_MODULE); - $isCore = strpos($module, '.') !== false; - $message = sprintf('Run Architecture Sniffer for %s', $isCore ? 'CORE' : 'PROJECT'); - - if ($module) { - $module = $this->normalizeModuleName($module); - $message .= ' in ' . $module . ' module'; - } - + /** @var string|null $path */ $path = $this->input->getArgument(static::ARGUMENT_SUB_PATH); + $isCore = strpos((string)$module, '.') !== false; - if ($path) { - $message .= ' (' . $path . ')'; - } - + $message = $this->buildMessage($module, $path, $isCore); $this->info($message); if ($isCore) { @@ -110,41 +138,44 @@ protected function runForCore(OutputInterface $output, $moduleArgument, $subPath { $moduleTransferCollection = $this->getModulesToExecute($moduleArgument); + if (!$moduleTransferCollection) { + $customPath = $this->getCommonPath($moduleArgument, $subPath); + + if (file_exists($customPath)) { + return $this->runCustomPath($output, $customPath); + } + } + + if (!$moduleTransferCollection) { + $output->writeln(sprintf('No module(s) found: `%s`.', $moduleArgument)); + + return false; + } + $count = 0; foreach ($moduleTransferCollection as $moduleTransfer) { $path = $this->getCorePath($moduleTransfer, $subPath); if (!is_dir($path)) { - $output->writeln(sprintf('Path not found: %s', $path)); + $output->writeln(sprintf('Path not found: `%s`', $path)); return false; } $violations = $this->getFacade()->runArchitectureSniffer($path, $this->input->getOptions()); $output->writeln($path, $violations ? OutputInterface::VERBOSITY_QUIET : OutputInterface::VERBOSITY_VERBOSE); - $countCurrent = $this->displayViolations($output, $violations); - $this->displayViolationsCountMessage($output, $countCurrent); + $countCurrent = $this->displayViolationsWithBaseline($output, $violations); $count += $countCurrent; } return $count === 0; } - /** - * @param string $namespace - * - * @return bool - */ - protected function getNamespaceIsSpryker(string $namespace): bool - { - return $namespace === static::NAMESPACE_SPRYKER || $namespace === static::NAMESPACE_SPRYKER_SHOP; - } - /** * @param string $moduleArgument * - * @return \Generated\Shared\Transfer\ModuleTransfer[] + * @return array<\Generated\Shared\Transfer\ModuleTransfer> */ protected function getModulesToExecute(string $moduleArgument): array { @@ -237,13 +268,14 @@ protected function runForProject(OutputInterface $output, $module, $subPath) $projectNamespaces = $this->getFactory()->getConfig()->getProjectNamespaces(); $result = 0; + $violations = null; foreach ($projectNamespaces as $projectNamespace) { $output->writeln($projectNamespace, OutputInterface::VERBOSITY_VERBOSE); $path = $pathToRoot . 'src' . DIRECTORY_SEPARATOR . $projectNamespace . DIRECTORY_SEPARATOR; $paths = []; if ($module) { - foreach (static::APPLICATION_LAYERS as $layer) { + foreach ($this->getFactory()->getConfig()->getApplicationLayers() as $layer) { $paths[] = $path . $layer . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR; } } else { @@ -256,17 +288,18 @@ protected function runForProject(OutputInterface $output, $module, $subPath) } if (!is_dir($path)) { $output->writeln('Path not found, skipping: ' . $path, OutputInterface::VERBOSITY_VERY_VERBOSE); + continue; } $output->writeln('Checking path: ' . $path, OutputInterface::VERBOSITY_VERBOSE); $violations = $this->getFacade()->runArchitectureSniffer($path, $this->input->getOptions()); - $count = $this->displayViolations($output, $violations); + $count = $this->displayViolationsWithBaseline($output, $violations); $result += $count; } } - if (!isset($violations)) { + if ($violations === null) { $output->writeln('No paths found for checking'); return false; @@ -288,14 +321,14 @@ protected function runCustomPath(OutputInterface $output, $customPath) $output->writeln($customPath, OutputInterface::VERBOSITY_VERBOSE); $violations = $this->getFacade()->runArchitectureSniffer($customPath, $this->input->getOptions()); - $count = $this->displayViolations($output, $violations); - - $this->displayViolationsCountMessage($output, $count); + $count = $this->displayViolationsWithBaseline($output, $violations); return $count === 0; } /** + * @deprecated Use {@link \Spryker\Zed\Development\Communication\Console\CodeArchitectureSnifferConsole::displayViolationsWithBaseline()} instead.} + * * @param \Symfony\Component\Console\Output\OutputInterface $output * @param array $violations * @@ -316,47 +349,54 @@ protected function displayViolations(OutputInterface $output, array $violations) } /** - * @param string $module + * @param \Symfony\Component\Console\Output\OutputInterface $output + * @param array $violations * - * @return string + * @return int */ - protected function normalizeModuleName($module) + protected function displayViolationsWithBaseline(OutputInterface $output, array $violations): int { - $filter = new UnderscoreToCamelCase(); - $normalized = $filter->filter(str_replace('-', '_', $module)); - $normalized = ucfirst($normalized); + if (!$violations) { + return 0; + } - return $normalized; - } + foreach ($violations as $type => $violationsArray) { + $count = 0; - /** - * @param string $name - * - * @return string - */ - protected function dasherize($name) - { - $filterChain = new FilterChain(); - $filterChain - ->attach(new CamelCaseToDash()) - ->attach(new StringToLower()); + foreach ($violationsArray as $violation) { + if ($type === ArchitectureSniffer::NAME_VISIBLE_VIOLATIONS) { + $output->writeln(' - ' . trim($violation[ArchitectureSniffer::VIOLATION_FIELD_NAME_DESCRIPTION]) . ' ', OutputInterface::VERBOSITY_VERBOSE); + } else { + $output->writeln(' - ' . trim($violation[ArchitectureSniffer::VIOLATION_FIELD_NAME_DESCRIPTION]), OutputInterface::VERBOSITY_VERBOSE); + } - return $filterChain->filter($name); + $ruleset = $violation[ArchitectureSniffer::VIOLATION_FIELD_NAME_RULESET]; + $rule = $violation[ArchitectureSniffer::VIOLATION_FIELD_NAME_RULE]; + $filename = pathinfo($violation['fileName'], PATHINFO_FILENAME); + $output->writeln(' ' . $ruleset . ' > ' . $rule . ' > ' . $filename, OutputInterface::VERBOSITY_VERBOSE); + $count++; + } + + $this->displayViolationsCountMessage($output, $count, ($type === ArchitectureSniffer::NAME_IGNORED_VIOLATIONS)); + } + + return count($violations[ArchitectureSniffer::NAME_VISIBLE_VIOLATIONS]); } /** * @param \Symfony\Component\Console\Output\OutputInterface $output * @param int $count + * @param bool $isIgnored * * @return void */ - protected function displayViolationsCountMessage(OutputInterface $output, int $count): void + protected function displayViolationsCountMessage(OutputInterface $output, int $count, $isIgnored = false): void { if (!$this->isVerboseModeEnabled() && $count === 0) { return; } - $output->writeln($count . ' violations found'); + $output->writeln($count . ($isIgnored ? ' ' . ArchitectureSniffer::NAME_IGNORED_VIOLATIONS : '') . ' violations found'); } /** @@ -364,7 +404,7 @@ protected function displayViolationsCountMessage(OutputInterface $output, int $c */ protected function isVerboseModeEnabled(): bool { - return $this->input->getOption(static::OPTION_VERBOSE); + return (bool)$this->input->getOption(static::OPTION_VERBOSE); } /** @@ -384,4 +424,62 @@ protected function getCustomPath(?string $module, ?string $path): string return $this->buildPath($customPath); } + + /** + * @param string|null $module + * @param string|null $path + * + * @return string + */ + protected function getCommonPath(?string $module, ?string $path): string + { + [$namespace, $module] = explode('.', $module); + + if (!$this->nameNormalizer) { + $this->nameNormalizer = $this->getFactory()->createNameNormalizer(); + } + + $moduleVendor = $this->nameNormalizer->dasherize($namespace); + $module = $this->nameNormalizer->dasherize($module); + + return sprintf( + '%s/vendor/%s/%s/%s', + $this->getFactory()->getConfig()->getPathToRoot(), + $moduleVendor, + $module, + $path, + ); + } + + /** + * @param string|null $module + * @param string|null $path + * @param bool $isCore + * + * @return string + */ + protected function buildMessage(?string $module = null, ?string $path = null, bool $isCore = true): string + { + if ($this->getFactory()->getConfig()->isStandaloneMode()) { + return static::RUN_IN_STANDALONE_MODE; + } + + $message = sprintf('Run Architecture Sniffer for %s', $isCore ? 'CORE' : 'PROJECT'); + + if ($module !== null) { + if (!$this->nameNormalizer) { + $this->nameNormalizer = $this->getFactory()->createNameNormalizer(); + } + + $module = $this->nameNormalizer->camelize($module); + + $message = sprintf('%s in %s module', $message, $module); + } + + if ($path) { + $message = sprintf('%s (%s)', $message, $path); + } + + return $message; + } } diff --git a/src/Spryker/Zed/Development/Communication/Console/CodeFixturesConsole.php b/src/Spryker/Zed/Development/Communication/Console/CodeFixturesConsole.php new file mode 100644 index 00000000..dac58988 --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/CodeFixturesConsole.php @@ -0,0 +1,97 @@ +setName(static::COMMAND_NAME) + ->setHelp('' . static::COMMAND_NAME . ' -h') + ->setDescription('Build fixtures for codeception tests'); + + $this->addOption(static::OPTION_MODULE, 'm', InputOption::VALUE_OPTIONAL, 'Name of core module to build fixtures for (or "all")'); + $this->addOption(static::OPTION_GROUP, 'g', InputOption::VALUE_OPTIONAL, 'Groups of fixtures to be build (multiple values allowed, comma separated)'); + $this->addOption(static::OPTION_TYPE_EXCLUDE, 'x', InputOption::VALUE_OPTIONAL, 'Types of fixtures to be skipped (e.g. Slow; multiple values allowed, comma separated)'); + $this->addOption(static::OPTION_INITIALIZE, 'i', InputOption::VALUE_NONE, 'Initialize actors by (re)generating required classes'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + /** @var string|null $module */ + $module = $this->input->getOption(static::OPTION_MODULE); + $this->displayRunInfo($module); + + $initialize = $this->input->getOption(static::OPTION_INITIALIZE); + if (!$initialize) { + $this->warning('Make sure you ran `codecept build` already.'); + } + + return $this->getFacade()->runFixtures($module, $this->input->getOptions()); + } + + /** + * @param string|null $module + * + * @return void + */ + protected function displayRunInfo(?string $module): void + { + $message = 'Build fixtures for codeception tests for project level'; + if ($module) { + $message = 'Build fixtures for codeception tests for module(s) ' . $module; + } + $this->info($message); + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/CodePhpMessDetectorConsole.php b/src/Spryker/Zed/Development/Communication/Console/CodePhpMessDetectorConsole.php index b2e66cd0..76a5f4dd 100644 --- a/src/Spryker/Zed/Development/Communication/Console/CodePhpMessDetectorConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/CodePhpMessDetectorConsole.php @@ -18,16 +18,35 @@ */ class CodePhpMessDetectorConsole extends Console { + /** + * @var string + */ public const COMMAND_NAME = 'code:phpmd'; + + /** + * @var string + */ public const OPTION_MODULE = 'module'; + + /** + * @var string + */ public const OPTION_MODULE_ALL = 'all'; + + /** + * @var string + */ public const OPTION_DRY_RUN = 'dry-run'; + + /** + * @var string + */ public const OPTION_FORMAT = 'format'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -49,17 +68,35 @@ protected function configure() */ public function execute(InputInterface $input, OutputInterface $output) { + /** @var string|null $module */ $module = $this->input->getOption(static::OPTION_MODULE); - $message = 'Run PHPMD in PROJECT level'; - if ($module) { - $message = 'Run PHPMD in all CORE modules'; - if ($module !== static::OPTION_MODULE_ALL) { - $message = 'Run PHPMD in ' . $module . ' CORE module'; - } - } + $message = $this->buildMessage($module); $this->info($message); return $this->getFacade()->runPhpMd($module, $this->input->getOptions()); } + + /** + * @param string|null $module + * + * @return string + */ + protected function buildMessage(?string $module = null): string + { + $message = 'Run PHPMD in'; + if ($this->getFactory()->getConfig()->isStandaloneMode()) { + return sprintf('%s Standalone Mode', $message); + } + + if ($module === null) { + return sprintf('%s PROJECT level', $message); + } + + if ($module !== static::OPTION_MODULE_ALL) { + return sprintf('%s %s CORE module', $message, $module); + } + + return sprintf('%s all CORE modules', $message); + } } diff --git a/src/Spryker/Zed/Development/Communication/Console/CodePhpstanConsole.php b/src/Spryker/Zed/Development/Communication/Console/CodePhpstanConsole.php index e612f99a..6b6afbc5 100644 --- a/src/Spryker/Zed/Development/Communication/Console/CodePhpstanConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/CodePhpstanConsole.php @@ -7,6 +7,7 @@ namespace Spryker\Zed\Development\Communication\Console; +use Spryker\Zed\Development\Business\Phpstan\PhpstanRunner; use Spryker\Zed\Kernel\Communication\Console\Console; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -18,28 +19,64 @@ */ class CodePhpstanConsole extends Console { + /** + * @var string + */ protected const COMMAND_NAME = 'code:phpstan'; - protected const OPTION_MODULE = 'module'; - protected const OPTION_DRY_RUN = 'dry-run'; - protected const OPTION_LEVEL = 'level'; + + /** + * @var string + */ + protected const OPTION_MODULE = PhpstanRunner::OPTION_MODULE; + + /** + * @var string + */ + protected const OPTION_DRY_RUN = PhpstanRunner::OPTION_DRY_RUN; + + /** + * @var string + */ + protected const OPTION_LEVEL = PhpstanRunner::OPTION_LEVEL; + + /** + * @var string + */ + protected const OPTION_OFFSET = PhpstanRunner::OPTION_OFFSET; + + /** + * @var string + */ + protected const OPTION_IS_MERGABLE_CONFIG = PhpstanRunner::OPTION_IS_MERGABLE_CONFIG; + + /** + * @deprecated Not Used + * + * @var string + */ protected const OPTION_FORMAT = 'format'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this ->setName(static::COMMAND_NAME) ->setHelp('' . static::COMMAND_NAME . ' -h') - ->setDescription('Run Phpstan for project or core'); + ->setDescription('Run PHPStan static analyzer for project or core'); $this->addOption(static::OPTION_MODULE, 'm', InputOption::VALUE_OPTIONAL, 'Name of module to run PHPStan for. You can use dot syntax for namespaced ones, e.g. `SprykerEco.FooBar`. `Spryker.all`/`SprykerShop.all` is reserved for CORE internal usage.'); $this->addOption(static::OPTION_FORMAT, 'f', InputOption::VALUE_OPTIONAL, 'Output format [text, xml, json, md]'); $this->addOption(static::OPTION_DRY_RUN, 'd', InputOption::VALUE_NONE, 'Dry-run the command, display it only'); $this->addOption(static::OPTION_LEVEL, 'l', InputOption::VALUE_OPTIONAL, 'Level of rule options - the higher the stricter'); + $this->addOption(static::OPTION_IS_MERGABLE_CONFIG, 'c', InputOption::VALUE_OPTIONAL, 'Defines whether the module config is mergable with the default one or not. If not set to false, the command will merge the module config with the default one.', true); + + $description = 'Offset to use for path splitting. Mainly for core, where it is needed for runtime reasons.'; + $description .= PHP_EOL . 'Syntax: {offset}[,{limit}]'; + $this->addOption(static::OPTION_OFFSET, 'o', InputOption::VALUE_OPTIONAL, $description); } /** diff --git a/src/Spryker/Zed/Development/Communication/Console/CodeStyleSnifferConsole.php b/src/Spryker/Zed/Development/Communication/Console/CodeStyleSnifferConsole.php index 03f0de6b..2ed6be6a 100644 --- a/src/Spryker/Zed/Development/Communication/Console/CodeStyleSnifferConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/CodeStyleSnifferConsole.php @@ -7,12 +7,12 @@ namespace Spryker\Zed\Development\Communication\Console; +use Laminas\Filter\Word\UnderscoreToCamelCase; use Spryker\Zed\Kernel\Communication\Console\Console; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Zend\Filter\Word\UnderscoreToCamelCase; /** * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() @@ -20,20 +20,55 @@ */ class CodeStyleSnifferConsole extends Console { + /** + * @var string + */ public const COMMAND_NAME = 'code:sniff:style'; + + /** + * @var string + */ public const OPTION_MODULE = 'module'; + + /** + * @var string + */ public const OPTION_SNIFFS = 'sniffs'; + + /** + * @var string + */ public const OPTION_DRY_RUN = 'dry-run'; + + /** + * @var string + */ public const OPTION_FIX = 'fix'; + + /** + * @var string + */ public const OPTION_EXPLAIN = 'explain'; + + /** + * @var string + */ public const ARGUMENT_SUB_PATH = 'path'; + /** + * @var string + */ protected const OPTION_LEVEL = 'level'; + /** + * @var string + */ + protected const RUN_IN_STANDALONE_MODE = 'Run Code Style Sniffer in Standalone Mode'; + /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -58,7 +93,9 @@ protected function configure() */ public function execute(InputInterface $input, OutputInterface $output) { + /** @var string|null $module */ $module = $this->input->getOption(static::OPTION_MODULE); + /** @var string|null $path */ $path = $this->input->getArgument(static::ARGUMENT_SUB_PATH); $this->info($this->buildMessage($module, $path)); @@ -76,16 +113,20 @@ public function execute(InputInterface $input, OutputInterface $output) */ protected function buildMessage($module, $path) { + if ($this->getFactory()->getConfig()->isStandaloneMode()) { + return static::RUN_IN_STANDALONE_MODE; + } + $isCore = strpos($module, '.') !== false; $message = sprintf('Run Code Style Sniffer for %s', $isCore ? 'CORE' : 'PROJECT'); if ($module) { $module = $this->normalizeModuleName($module); - $message .= ' in ' . $module . ' module'; + $message = sprintf('%s in %s module', $message, $module); } if ($path) { - $message .= ' (' . $path . ')'; + $message = sprintf('%s (%s)', $message, $path); } return $message; @@ -99,6 +140,7 @@ protected function buildMessage($module, $path) protected function normalizeModuleName($module) { $filter = new UnderscoreToCamelCase(); + /** @var string $normalized */ $normalized = $filter->filter(str_replace('-', '_', $module)); $normalized = ucfirst($normalized); diff --git a/src/Spryker/Zed/Development/Communication/Console/CodeTestConsole.php b/src/Spryker/Zed/Development/Communication/Console/CodeTestConsole.php index c7e3bf98..9c412f12 100644 --- a/src/Spryker/Zed/Development/Communication/Console/CodeTestConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/CodeTestConsole.php @@ -18,17 +18,40 @@ */ class CodeTestConsole extends Console { + /** + * @var string + */ public const COMMAND_NAME = 'code:test'; + + /** + * @var string + */ public const OPTION_MODULE = 'module'; - public const OPTION_MODULE_ALL = 'all'; + + /** + * @var string + */ public const OPTION_INITIALIZE = 'initialize'; + + /** + * @var string + */ public const OPTION_GROUP = 'group'; + + /** + * @var string + */ public const OPTION_TYPE_EXCLUDE = 'exclude'; + /** + * @var string + */ + public const OPTION_DRY_RUN = 'dry-run'; + /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -37,33 +60,62 @@ protected function configure() ->setHelp('' . static::COMMAND_NAME . ' -h') ->setDescription('Run codecept tests for project or core'); - $this->addOption(static::OPTION_MODULE, 'm', InputOption::VALUE_OPTIONAL, 'Name of core module to run tests for (or "all")'); + $this->addOption(static::OPTION_MODULE, 'm', InputOption::VALUE_OPTIONAL, 'Name of core module to run tests for (or "Spryker*.all")'); $this->addOption(static::OPTION_GROUP, 'g', InputOption::VALUE_OPTIONAL, 'Groups of tests to be executed (multiple values allowed, comma separated)'); $this->addOption(static::OPTION_TYPE_EXCLUDE, 'x', InputOption::VALUE_OPTIONAL, 'Types of tests to be skipped (e.g. Presentation; multiple values allowed, comma separated)'); $this->addOption(static::OPTION_INITIALIZE, 'i', InputOption::VALUE_NONE, 'Initialize test suite by (re)generating required test classes'); + $this->addOption(static::OPTION_DRY_RUN, 'd', InputOption::VALUE_NONE, 'Dry-run the command, only output the commands that would be run'); } /** * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * - * @return int|null + * @return int */ - public function execute(InputInterface $input, OutputInterface $output) + public function execute(InputInterface $input, OutputInterface $output): int { + /** @var string|null $module */ $module = $this->input->getOption(static::OPTION_MODULE); + $this->displayRunInfo($input, $module); + if (!$this->input->getOption(static::OPTION_INITIALIZE) && !$input->getOption(static::OPTION_DRY_RUN)) { + $this->warning('Make sure you ran `codecept build` already.'); + } + + return $this->getFacade()->runTest( + $module, + $this->extendOptions($input), + ); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * + * @return array + */ + protected function extendOptions(InputInterface $input): array + { + $options = $input->getOptions(); + + return $options; + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param string|null $module + * + * @return void + */ + protected function displayRunInfo(InputInterface $input, ?string $module): void + { $message = 'Run codecept tests for project level'; if ($module) { - $message = 'Run codecept tests for ' . $module . ' module'; + $message = 'Run codecept tests for module(s): ' . $module; } - $this->info($message); - - $initialize = $this->input->getOption(static::OPTION_INITIALIZE); - if (!$initialize) { - $this->warning('Make sure you ran `codecept build` already.'); + if ($input->getOption(static::OPTION_DRY_RUN)) { + $message .= ' [dry run]'; } - - $this->getFacade()->runTest($module, $this->input->getOptions()); + $this->info($message); } } diff --git a/src/Spryker/Zed/Development/Communication/Console/ComposerJsonUpdaterConsole.php b/src/Spryker/Zed/Development/Communication/Console/ComposerJsonUpdaterConsole.php index 5430c45c..7992cd46 100644 --- a/src/Spryker/Zed/Development/Communication/Console/ComposerJsonUpdaterConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/ComposerJsonUpdaterConsole.php @@ -12,19 +12,32 @@ use Symfony\Component\Console\Output\OutputInterface; /** + * @internal + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class ComposerJsonUpdaterConsole extends AbstractCoreModuleAwareConsole { + /** + * @var string + */ public const COMMAND_NAME = 'dev:composer:update-json-files'; + + /** + * @var string + */ public const OPTION_DRY_RUN = 'dry-run'; + + /** + * @var string + */ public const VERBOSE = 'verbose'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -49,16 +62,19 @@ public function execute(InputInterface $input, OutputInterface $output) $modules = $this->getModulesToExecute($input); if (!$modules) { + /** @var string|null $module */ + $module = $this->input->getArgument(static::ARGUMENT_MODULE); $this->error( sprintf( 'Argument `%s` is not a valid module.', - $this->input->getArgument(static::ARGUMENT_MODULE) - ) + $module, + ), ); return static::CODE_ERROR; } + /** @var bool $isDryRun */ $isDryRun = $this->input->getOption(static::OPTION_DRY_RUN); $processedModules = $this->getFacade()->updateComposerJsonInModules($modules, $isDryRun); $modifiedModules = []; @@ -86,14 +102,14 @@ public function execute(InputInterface $input, OutputInterface $output) $commands = []; foreach ($modifiedModules as $modifiedModule) { - $commands[] = 'console ' . static::COMMAND_NAME . ' ' . $modifiedModule; + $commands[] = 'vendor/bin/console ' . static::COMMAND_NAME . ' ' . $modifiedModule; } $this->info( sprintf( 'Please run %s locally without dry-run:', - count($commands) > 1 ? 'these commands' : 'this command' - ) + count($commands) > 1 ? 'these commands' : 'this command', + ), ); $this->output->writeln(implode("\n", $commands)); } diff --git a/src/Spryker/Zed/Development/Communication/Console/ComposerJsonValidatorConsole.php b/src/Spryker/Zed/Development/Communication/Console/ComposerJsonValidatorConsole.php index 7a2a5108..7fa2d669 100644 --- a/src/Spryker/Zed/Development/Communication/Console/ComposerJsonValidatorConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/ComposerJsonValidatorConsole.php @@ -14,10 +14,16 @@ use Symfony\Component\Console\Output\OutputInterface; /** + * @internal + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() + * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class ComposerJsonValidatorConsole extends AbstractCoreModuleAwareConsole { + /** + * @var string + */ protected const COMMAND_NAME = 'dev:composer:validate-json-files'; /** @@ -28,7 +34,7 @@ class ComposerJsonValidatorConsole extends AbstractCoreModuleAwareConsole /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -65,7 +71,7 @@ public function execute(InputInterface $input, OutputInterface $output): int } /** - * @param array $modulesToValidate + * @param array $modulesToValidate * * @return void */ diff --git a/src/Spryker/Zed/Development/Communication/Console/DependencyTreeBuilderConsole.php b/src/Spryker/Zed/Development/Communication/Console/DependencyTreeBuilderConsole.php index 7d8ac4c9..34cfde63 100644 --- a/src/Spryker/Zed/Development/Communication/Console/DependencyTreeBuilderConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/DependencyTreeBuilderConsole.php @@ -13,21 +13,37 @@ use Symfony\Component\Console\Output\OutputInterface; /** + * @internal + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class DependencyTreeBuilderConsole extends Console { + /** + * @var string + */ public const COMMAND_NAME = 'dev:dependency:build-tree'; + /** + * @var string + */ public const OPTION_APPLICATION = 'application'; + + /** + * @var string + */ public const OPTION_MODULE = 'module'; + + /** + * @var string + */ public const OPTION_LAYER = 'layer'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -52,11 +68,14 @@ public function execute(InputInterface $input, OutputInterface $output) $module = '*'; if ($this->input->getOption(static::OPTION_MODULE)) { + /** @var string $module */ $module = $this->input->getOption(static::OPTION_MODULE); } $this->info('Build dependency tree.'); $this->getFacade()->buildDependencyTree($module); + + return static::CODE_SUCCESS; } } diff --git a/src/Spryker/Zed/Development/Communication/Console/DependencyTreeDependencyViolationConsole.php b/src/Spryker/Zed/Development/Communication/Console/DependencyTreeDependencyViolationConsole.php index caa661e2..02a9465d 100644 --- a/src/Spryker/Zed/Development/Communication/Console/DependencyTreeDependencyViolationConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/DependencyTreeDependencyViolationConsole.php @@ -8,9 +8,10 @@ namespace Spryker\Zed\Development\Communication\Console; /** - * @deprecated Use `Spryker\Zed\Development\Communication\Console\DependencyViolationFinderConsole` instead. + * @deprecated Use {@link \Spryker\Zed\Development\Communication\Console\DependencyViolationFinderConsole} instead. * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() + * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class DependencyTreeDependencyViolationConsole extends DependencyViolationFinderConsole { diff --git a/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php b/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php index 0582c052..8aa4e370 100644 --- a/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFinderConsole.php @@ -17,15 +17,36 @@ use Symfony\Component\Console\Output\OutputInterface; /** + * @internal + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() - * @method \Spryker\Zed\Development\Business\DevelopmentBusinessFactory getFactory() + * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class DependencyViolationFinderConsole extends AbstractCoreModuleAwareConsole { + /** + * @var string + */ public const COMMAND_NAME = 'dev:dependency:find'; + + /** + * @var string + */ public const OPTION_DEPENDENCY_TYPE = 'dependency-type'; + + /** + * @var string + */ public const OPTION_DEPENDENCY_TYPE_SHORT = 'd'; + + /** + * @var string + */ public const OPTION_STOP_ON_VIOLATION = 'stop-on-violation'; + + /** + * @var string + */ public const OPTION_STOP_ON_VIOLATION_SHORT = 's'; /** @@ -36,7 +57,7 @@ class DependencyViolationFinderConsole extends AbstractCoreModuleAwareConsole /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -53,9 +74,9 @@ protected function configure() * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * - * @return int|null + * @return int */ - public function execute(InputInterface $input, OutputInterface $output) + public function execute(InputInterface $input, OutputInterface $output): int { $modulesToValidate = $this->getModulesToExecute($input); @@ -109,7 +130,7 @@ protected function validateModule(ModuleTransfer $moduleTransfer, OutputInterfac } /** - * @param \Generated\Shared\Transfer\ModuleDependencyTransfer[]|\ArrayObject $moduleDependencyTransferCollection + * @param \ArrayObject $moduleDependencyTransferCollection * @param \Symfony\Component\Console\Output\OutputInterface $output * @param string|null $dependencyType * @@ -134,14 +155,18 @@ protected function describeDependencies(ArrayObject $moduleDependencyTransferCol /** * @param string $moduleToValidate - * @param \Generated\Shared\Transfer\ModuleDependencyTransfer[]|\ArrayObject $moduleDependencyTransferCollection + * @param \ArrayObject $moduleDependencyTransferCollection * @param \Symfony\Component\Console\Output\OutputInterface $output * @param string|null $dependencyType * * @return void */ - protected function printDependencyViolationErrors(string $moduleToValidate, ArrayObject $moduleDependencyTransferCollection, OutputInterface $output, ?string $dependencyType = null): void - { + protected function printDependencyViolationErrors( + string $moduleToValidate, + ArrayObject $moduleDependencyTransferCollection, + OutputInterface $output, + ?string $dependencyType = null + ): void { $tableRows = []; foreach ($moduleDependencyTransferCollection as $moduleDependencyTransfer) { if ($dependencyType !== null && !in_array($dependencyType, $moduleDependencyTransfer->getDependencyTypes())) { @@ -149,7 +174,8 @@ protected function printDependencyViolationErrors(string $moduleToValidate, Arra } foreach ($moduleDependencyTransfer->getValidationMessages() as $validationMessageTransfer) { - $tableRows[] = [$moduleDependencyTransfer->getModule(), $validationMessageTransfer->getMessage()]; + $composerName = $moduleDependencyTransfer->getComposerName(); + $tableRows[] = [$composerName, $validationMessageTransfer->getMessage()]; } } @@ -178,8 +204,11 @@ protected function renderTable(OutputInterface $output, array $headers, array $r */ protected function buildTableRow(ModuleDependencyTransfer $moduleDependencyTransfer): array { + $color = $moduleDependencyTransfer->getIsValid() ? 'yellow' : 'red'; + $composerName = $moduleDependencyTransfer->getComposerName(); + return [ - 'Dependency Module' => sprintf('%s', $moduleDependencyTransfer->getModule()), + 'Composer name' => sprintf('%s', $color, $composerName), 'is valid' => $this->getColoredYesOrNo($moduleDependencyTransfer->getIsValid()), 'src dependency' => $this->getYesOrNo($moduleDependencyTransfer->getIsSrcDependency()), 'test dependency' => $this->getYesOrNo($moduleDependencyTransfer->getIsTestDependency()), @@ -213,7 +242,7 @@ protected function getColoredYesOrNo(bool $bool): string } /** - * @param array $modulesToValidate + * @param array<\Generated\Shared\Transfer\ModuleTransfer> $modulesToValidate * @param string|null $dependencyType * * @return void @@ -228,7 +257,7 @@ protected function startValidation(array $modulesToValidate, ?string $dependency 'Checking %d %s for %sdependency issues.', count($modulesToValidate), (count($modulesToValidate) === 1) ? 'Module ' . $this->buildModuleKey(current($modulesToValidate)) . '' : 'Modules', - $typeMessage + $typeMessage, ); if ($this->output->isVerbose()) { $this->info($message); diff --git a/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php b/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php index 964de536..c1b432b6 100644 --- a/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/DependencyViolationFixConsole.php @@ -10,43 +10,45 @@ use Generated\Shared\Transfer\ModuleDependencyTransfer; use Generated\Shared\Transfer\ModuleTransfer; use Generated\Shared\Transfer\ValidationMessageTransfer; +use Spryker\Zed\Development\Business\Composer\Util\ComposerJson; use Spryker\Zed\Development\Business\Dependency\Validator\ValidationRules\ValidationRuleInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** + * @internal + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() - * @method \Spryker\Zed\Development\Business\DevelopmentBusinessFactory getFactory() + * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class DependencyViolationFixConsole extends AbstractCoreModuleAwareConsole { + /** + * @var string + */ protected const COMMAND_NAME = 'dev:dependency:fix'; - protected const OPTION_DRY_RUN = 'dry-run'; - protected const OPTION_DRY_RUN_SHORT = 'd'; - - protected const REPLACE_4_WITH_2_SPACES = '/^( +?)\\1(?=[^ ])/m'; /** - * @var array|null + * @var string */ - protected $moduleTransferCollectionGroupedByModuleName; + protected const OPTION_DRY_RUN = 'dry-run'; /** - * @var array|null + * @var string */ - protected $packageTransferCollectionGroupedByPackageName; + protected const OPTION_DRY_RUN_SHORT = 'd'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this ->setName(static::COMMAND_NAME) - ->addOption(static::OPTION_DRY_RUN, 'd', InputOption::VALUE_NONE, 'Dry-run the command, changed composer.json will not be saved.') + ->addOption(static::OPTION_DRY_RUN, static::OPTION_DRY_RUN_SHORT, InputOption::VALUE_NONE, 'Dry-run the command, changed composer.json will not be saved.') ->setDescription('Fix dependency violations in composer.json.'); } @@ -70,6 +72,8 @@ public function execute(InputInterface $input, OutputInterface $output) } $this->executeModuleTransfer($moduleTransfer); } + + return static::CODE_SUCCESS; } /** @@ -101,15 +105,16 @@ protected function fixModuleDependencies(ModuleTransfer $moduleTransfer): void $composerJsonArray = $this->getComposerJsonAsArray($moduleTransfer); foreach ($this->getModuleDependencies($moduleTransfer) as $moduleDependencyTransfer) { - $composerNameToFix = $this->getComposerNameToFix($moduleDependencyTransfer); + $missingComposerName = $this->getMissingComposerName($moduleDependencyTransfer); - if ($composerNameToFix === null) { - $this->output->writeln(sprintf('Could not get a composer name for "%s"', $moduleDependencyTransfer->getModule())); + if ($missingComposerName === null) { + $this->output->writeln(sprintf('Could not get a composer name for "%s"', $moduleDependencyTransfer->getModuleName())); $this->output->writeln(sprintf('Please check the module %s.%s manually.', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName())); + continue; } - $composerJsonArray = $this->fixDependencyViolations($moduleDependencyTransfer, $composerJsonArray, $composerNameToFix); + $composerJsonArray = $this->fixDependencyViolations($moduleDependencyTransfer, $composerJsonArray, $missingComposerName); } $this->output->writeln(sprintf('Fixed dependencies in %s.%s', $moduleTransfer->getOrganization()->getName(), $moduleTransfer->getName())); @@ -122,119 +127,19 @@ protected function fixModuleDependencies(ModuleTransfer $moduleTransfer): void * * @return string|null */ - protected function getComposerNameToFix(ModuleDependencyTransfer $moduleDependencyTransfer): ?string + protected function getMissingComposerName(ModuleDependencyTransfer $moduleDependencyTransfer): ?string { - $moduleName = $moduleDependencyTransfer->getModule(); - - $composerName = $this->getComposerNameFromModuleCollection($moduleName); - if ($composerName !== null) { - return $composerName; - } - - $composerName = $this->getComposerNameFromPackageCollection($moduleName); - if ($composerName !== null) { - return $composerName; + if ($moduleDependencyTransfer->getComposerName() !== null) { + return $moduleDependencyTransfer->getComposerName(); } - return null; - } - - /** - * @param string $moduleName - * - * @return string|null - */ - protected function getComposerNameFromModuleCollection(string $moduleName): ?string - { - if ($this->isNamespacedModuleName($moduleName)) { - $moduleTransfer = $this->getModuleTransferCollection()[$moduleName]; - - return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed()); - } - - $moduleTransferCollection = $this->getModuleTransferCollectionGroupedByModuleName(); - - if (!isset($moduleTransferCollection[$moduleName])) { - return null; - } - - if (count($moduleTransferCollection[$moduleName]) > 1) { - $this->output->writeln(sprintf('Found more than one moduleTransfer for the module name "%s"', $moduleName)); - - return null; - } - - $moduleTransfer = $this->getCurrentModuleTransfer($moduleTransferCollection[$moduleName]); - - return sprintf('%s/%s', $moduleTransfer->getOrganization()->getNameDashed(), $moduleTransfer->getNameDashed()); - } - - /** - * @param string $moduleName - * - * @return string|null - */ - protected function getComposerNameFromPackageCollection(string $moduleName): ?string - { - $packageTransferCollection = $this->getPackageTransferCollectionGroupedByPackageName(); - - if (isset($packageTransferCollection[$moduleName])) { - $packageTransfer = $packageTransferCollection[$moduleName]; - - return $packageTransfer->getComposerName(); + if ($moduleDependencyTransfer->getModuleName() !== null) { + return $this->getFacade()->findComposerNameByModuleName($moduleDependencyTransfer->getModuleName()); } return null; } - /** - * @param array $moduleTransferCollection - * - * @return \Generated\Shared\Transfer\ModuleTransfer - */ - protected function getCurrentModuleTransfer(array $moduleTransferCollection): ModuleTransfer - { - return current($moduleTransferCollection); - } - - /** - * @return array - */ - protected function getModuleTransferCollectionGroupedByModuleName(): array - { - if ($this->moduleTransferCollectionGroupedByModuleName !== null) { - return $this->moduleTransferCollectionGroupedByModuleName; - } - - $moduleTransferCollection = $this->getModuleTransferCollection(); - $this->moduleTransferCollectionGroupedByModuleName = []; - - foreach ($moduleTransferCollection as $moduleTransfer) { - $this->moduleTransferCollectionGroupedByModuleName[$moduleTransfer->getName()][] = $moduleTransfer; - } - - return $this->moduleTransferCollectionGroupedByModuleName; - } - - /** - * @return \Generated\Shared\Transfer\PackageTransfer[] - */ - protected function getPackageTransferCollectionGroupedByPackageName(): array - { - if ($this->packageTransferCollectionGroupedByPackageName !== null) { - return $this->packageTransferCollectionGroupedByPackageName; - } - - $packageTransferCollection = $this->getFacade()->getPackages(); - $this->packageTransferCollectionGroupedByPackageName = []; - - foreach ($packageTransferCollection as $packageTransfer) { - $this->packageTransferCollectionGroupedByPackageName[$packageTransfer->getPackageName()] = $packageTransfer; - } - - return $this->packageTransferCollectionGroupedByPackageName; - } - /** * @param \Generated\Shared\Transfer\ModuleTransfer $moduleTransfer * @@ -243,8 +148,7 @@ protected function getPackageTransferCollectionGroupedByPackageName(): array protected function getComposerJsonAsArray(ModuleTransfer $moduleTransfer): array { $composerJsonFile = $moduleTransfer->getPath() . '/composer.json'; - $composerJsonContent = file_get_contents($composerJsonFile); - $composerJsonArray = json_decode($composerJsonContent, true); + $composerJsonArray = ComposerJson::fromFile($composerJsonFile); return $composerJsonArray; } @@ -265,10 +169,7 @@ protected function saveComposerJsonArray(ModuleTransfer $moduleTransfer, array $ $composerJsonArray = $this->orderEntriesInComposerJsonArray($composerJsonArray); $composerJsonArray = $this->removeEmptyEntriesInComposerJsonArray($composerJsonArray); - $modifiedComposerJson = json_encode($composerJsonArray, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); - $modifiedComposerJson = preg_replace(static::REPLACE_4_WITH_2_SPACES, '$1', $modifiedComposerJson) . PHP_EOL; - - file_put_contents($composerJsonFile, $modifiedComposerJson); + ComposerJson::toFile($composerJsonFile, $composerJsonArray); } /** @@ -296,8 +197,11 @@ protected function fixDependencyViolations(ModuleDependencyTransfer $moduleDepen * * @return array */ - protected function fixDependencyViolationsInRequire(ValidationMessageTransfer $validationMessageTransfer, array $composerJsonArray, string $composerName): array - { + protected function fixDependencyViolationsInRequire( + ValidationMessageTransfer $validationMessageTransfer, + array $composerJsonArray, + string $composerName + ): array { if ($validationMessageTransfer->getFixType() === ValidationRuleInterface::ADD_REQUIRE) { $composerJsonArray['require'][$composerName] = '*'; $this->writeIfVerbose(sprintf('%s added to require', $composerName)); @@ -317,8 +221,11 @@ protected function fixDependencyViolationsInRequire(ValidationMessageTransfer $v * * @return array */ - protected function fixDependencyViolationsInRequireDev(ValidationMessageTransfer $validationMessageTransfer, array $composerJsonArray, string $composerName): array - { + protected function fixDependencyViolationsInRequireDev( + ValidationMessageTransfer $validationMessageTransfer, + array $composerJsonArray, + string $composerName + ): array { if ($validationMessageTransfer->getFixType() === ValidationRuleInterface::ADD_REQUIRE_DEV) { $composerJsonArray['require-dev'][$composerName] = '*'; $this->writeIfVerbose(sprintf('%s added to require-dev', $composerName)); @@ -338,8 +245,11 @@ protected function fixDependencyViolationsInRequireDev(ValidationMessageTransfer * * @return array */ - protected function fixDependencyViolationsInSuggest(ValidationMessageTransfer $validationMessageTransfer, array $composerJsonArray, string $composerName): array - { + protected function fixDependencyViolationsInSuggest( + ValidationMessageTransfer $validationMessageTransfer, + array $composerJsonArray, + string $composerName + ): array { if ($validationMessageTransfer->getFixType() === ValidationRuleInterface::ADD_SUGGEST) { $composerJsonArray['suggest'][$composerName] = 'ADD SUGGEST DESCRIPTION'; $this->writeIfVerbose(sprintf('%s added to suggests', $composerName)); diff --git a/src/Spryker/Zed/Development/Communication/Console/GenerateClientIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/GenerateClientIdeAutoCompletionConsole.php index f0391f56..0183c80d 100644 --- a/src/Spryker/Zed/Development/Communication/Console/GenerateClientIdeAutoCompletionConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/GenerateClientIdeAutoCompletionConsole.php @@ -17,17 +17,26 @@ */ class GenerateClientIdeAutoCompletionConsole extends Console { - public const COMMAND_NAME = 'dev:ide:generate-client-auto-completion'; + /** + * @var string + */ + protected const OLD_COMMAND_NAME = 'dev:ide:generate-client-auto-completion'; + + /** + * @var string + */ + public const COMMAND_NAME = 'dev:ide-auto-completion:client:generate'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this->setName(static::COMMAND_NAME); $this->setDescription('Generate IDE auto completion files for Client.'); + $this->setAliases([static::OLD_COMMAND_NAME]); } /** @@ -41,5 +50,7 @@ public function execute(InputInterface $input, OutputInterface $output) $this->getFacade()->generateClientIdeAutoCompletion(); $this->info('Generated Client IDE auto-completion files'); + + return static::CODE_SUCCESS; } } diff --git a/src/Spryker/Zed/Development/Communication/Console/GenerateGlueBackendIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/GenerateGlueBackendIdeAutoCompletionConsole.php new file mode 100644 index 00000000..f4e5e89e --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/GenerateGlueBackendIdeAutoCompletionConsole.php @@ -0,0 +1,50 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Generate IDE auto completion files for Glue Backend modules.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $this->getFacade()->generateGlueBackendIdeAutoCompletion(); + + $this->info('Generated Glue Backend IDE auto-completion files'); + + return static::CODE_SUCCESS; + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/GenerateGlueIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/GenerateGlueIdeAutoCompletionConsole.php index 2cf5c0d1..024a15f2 100644 --- a/src/Spryker/Zed/Development/Communication/Console/GenerateGlueIdeAutoCompletionConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/GenerateGlueIdeAutoCompletionConsole.php @@ -17,17 +17,26 @@ */ class GenerateGlueIdeAutoCompletionConsole extends Console { - public const COMMAND_NAME = 'dev:ide:generate-glue-auto-completion'; + /** + * @var string + */ + protected const OLD_COMMAND_NAME = 'dev:ide:generate-glue-auto-completion'; + + /** + * @var string + */ + public const COMMAND_NAME = 'dev:ide-auto-completion:glue:generate'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this->setName(static::COMMAND_NAME); $this->setDescription('Generate IDE auto completion files for Glue.'); + $this->setAliases([static::OLD_COMMAND_NAME]); } /** @@ -41,5 +50,7 @@ public function execute(InputInterface $input, OutputInterface $output) $this->getFacade()->generateGlueIdeAutoCompletion(); $this->info('Generated Glue IDE auto-completion files'); + + return static::CODE_SUCCESS; } } diff --git a/src/Spryker/Zed/Development/Communication/Console/GenerateIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/GenerateIdeAutoCompletionConsole.php index 895bbd67..996aff6f 100644 --- a/src/Spryker/Zed/Development/Communication/Console/GenerateIdeAutoCompletionConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/GenerateIdeAutoCompletionConsole.php @@ -17,17 +17,26 @@ */ class GenerateIdeAutoCompletionConsole extends Console { - public const COMMAND_NAME = 'dev:ide:generate-auto-completion'; + /** + * @var string + */ + protected const OLD_COMMAND_NAME = 'dev:ide:generate-auto-completion'; + + /** + * @var string + */ + public const COMMAND_NAME = 'dev:ide-auto-completion:generate'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this->setName(static::COMMAND_NAME); $this->setDescription('Generate IDE auto completion files.'); + $this->setAliases([static::OLD_COMMAND_NAME]); } /** @@ -44,11 +53,13 @@ public function execute(InputInterface $input, OutputInterface $output) GenerateClientIdeAutoCompletionConsole::COMMAND_NAME, GenerateServiceIdeAutoCompletionConsole::COMMAND_NAME, GenerateGlueIdeAutoCompletionConsole::COMMAND_NAME, + GenerateGlueBackendIdeAutoCompletionConsole::COMMAND_NAME, ]; foreach ($dependingCommands as $commandName) { if (!$this->getApplication()->has($commandName)) { $this->showCommandNotFoundMessage($commandName); + continue; } $this->runDependingCommand($commandName); @@ -69,7 +80,7 @@ public function execute(InputInterface $input, OutputInterface $output) protected function showCommandNotFoundMessage(string $commandName): void { $message = "Can not find $commandName in your project." . PHP_EOL; - $message .= "You can fix this by adding the missing command to your project ConsoleDependencyProvider."; + $message .= 'You can fix this by adding the missing command to your project ConsoleDependencyProvider.'; $this->output->writeln("$message"); } } diff --git a/src/Spryker/Zed/Development/Communication/Console/GenerateServiceIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/GenerateServiceIdeAutoCompletionConsole.php index 83cb3958..32c7b8ad 100644 --- a/src/Spryker/Zed/Development/Communication/Console/GenerateServiceIdeAutoCompletionConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/GenerateServiceIdeAutoCompletionConsole.php @@ -17,17 +17,26 @@ */ class GenerateServiceIdeAutoCompletionConsole extends Console { - public const COMMAND_NAME = 'dev:ide:generate-service-auto-completion'; + /** + * @var string + */ + protected const OLD_COMMAND_NAME = 'dev:ide:generate-service-auto-completion'; + + /** + * @var string + */ + public const COMMAND_NAME = 'dev:ide-auto-completion:service:generate'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this->setName(static::COMMAND_NAME); $this->setDescription('Generate IDE auto completion files for Service.'); + $this->setAliases([static::OLD_COMMAND_NAME]); } /** @@ -41,5 +50,7 @@ public function execute(InputInterface $input, OutputInterface $output) $this->getFacade()->generateServiceIdeAutoCompletion(); $this->info('Generated Service IDE auto-completion files'); + + return static::CODE_SUCCESS; } } diff --git a/src/Spryker/Zed/Development/Communication/Console/GenerateYvesIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/GenerateYvesIdeAutoCompletionConsole.php index 5f6a3192..b5aceb1a 100644 --- a/src/Spryker/Zed/Development/Communication/Console/GenerateYvesIdeAutoCompletionConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/GenerateYvesIdeAutoCompletionConsole.php @@ -17,17 +17,26 @@ */ class GenerateYvesIdeAutoCompletionConsole extends Console { - public const COMMAND_NAME = 'dev:ide:generate-yves-auto-completion'; + /** + * @var string + */ + protected const OLD_COMMAND_NAME = 'dev:ide:generate-yves-auto-completion'; + + /** + * @var string + */ + public const COMMAND_NAME = 'dev:ide-auto-completion:yves:generate'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this->setName(static::COMMAND_NAME); $this->setDescription('Generate IDE auto completion files for Yves.'); + $this->setAliases([static::OLD_COMMAND_NAME]); } /** @@ -41,5 +50,7 @@ public function execute(InputInterface $input, OutputInterface $output) $this->getFacade()->generateYvesIdeAutoCompletion(); $this->info('Generated Yves IDE auto-completion files'); + + return static::CODE_SUCCESS; } } diff --git a/src/Spryker/Zed/Development/Communication/Console/GenerateZedIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/GenerateZedIdeAutoCompletionConsole.php index fc78b0d5..146abe93 100644 --- a/src/Spryker/Zed/Development/Communication/Console/GenerateZedIdeAutoCompletionConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/GenerateZedIdeAutoCompletionConsole.php @@ -17,17 +17,26 @@ */ class GenerateZedIdeAutoCompletionConsole extends Console { - public const COMMAND_NAME = 'dev:ide:generate-zed-auto-completion'; + /** + * @var string + */ + protected const OLD_COMMAND_NAME = 'dev:ide:generate-zed-auto-completion'; + + /** + * @var string + */ + public const COMMAND_NAME = 'dev:ide-auto-completion:zed:generate'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); $this->setName(static::COMMAND_NAME); $this->setDescription('Generate IDE auto completion files for Zed.'); + $this->setAliases([static::OLD_COMMAND_NAME]); } /** @@ -41,5 +50,7 @@ public function execute(InputInterface $input, OutputInterface $output) $this->getFacade()->generateZedIdeAutoCompletion(); $this->info('Generated Zed IDE auto-completion files'); + + return static::CODE_SUCCESS; } } diff --git a/src/Spryker/Zed/Development/Communication/Console/ModuleBridgeCreateConsole.php b/src/Spryker/Zed/Development/Communication/Console/ModuleBridgeCreateConsole.php index f52a6f14..b4616720 100644 --- a/src/Spryker/Zed/Development/Communication/Console/ModuleBridgeCreateConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/ModuleBridgeCreateConsole.php @@ -14,24 +14,47 @@ use Symfony\Component\Console\Output\OutputInterface; /** + * @deprecated Will be removed, use Spryks instead. + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class ModuleBridgeCreateConsole extends Console { + /** + * @var string + */ public const COMMAND_NAME = 'dev:bridge:create'; + /** + * @var string + */ public const OPTION_BRIDGE_TYPE = 'bridge type'; + + /** + * @var string + */ public const OPTION_MODULE = 'from module'; + + /** + * @var string + */ public const OPTION_TO_MODULE = 'to module'; + /** + * @var string + */ public const OPTION_METHODS = 'methods'; + + /** + * @var string + */ public const OPTION_METHODS_SHORT = 'm'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -53,9 +76,13 @@ protected function configure() */ public function execute(InputInterface $input, OutputInterface $output) { + /** @var string $module */ $module = $this->input->getArgument(static::OPTION_MODULE); + /** @var string $toModule */ $toModule = $this->input->getArgument(static::OPTION_TO_MODULE); - $methods = explode(',', $this->input->getOption(static::OPTION_METHODS)); + /** @var string $methods */ + $methods = $this->input->getOption(static::OPTION_METHODS); + $methods = explode(',', $methods); $message = 'Create bridge in ' . $module; diff --git a/src/Spryker/Zed/Development/Communication/Console/ModuleCreateConsole.php b/src/Spryker/Zed/Development/Communication/Console/ModuleCreateConsole.php index 55be3667..6dcdbcba 100644 --- a/src/Spryker/Zed/Development/Communication/Console/ModuleCreateConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/ModuleCreateConsole.php @@ -14,20 +14,37 @@ use Symfony\Component\Console\Output\OutputInterface; /** + * @deprecated Will be removed, use Spryks instead. + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class ModuleCreateConsole extends Console { + /** + * @var string + */ public const COMMAND_NAME = 'dev:module:create'; + + /** + * @var string + */ public const ARGUMENT_MODULE = 'module'; + + /** + * @var string + */ public const ARGUMENT_FILE = 'file'; + + /** + * @var string + */ public const OPTION_FORCE = 'force'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -48,6 +65,7 @@ protected function configure() */ public function execute(InputInterface $input, OutputInterface $output) { + /** @var string $module */ $module = $this->input->getArgument(static::ARGUMENT_MODULE); if ($module !== 'all') { @@ -63,6 +81,6 @@ public function execute(InputInterface $input, OutputInterface $output) $this->getFacade()->createModule($module, $options); - return null; + return static::CODE_SUCCESS; } } diff --git a/src/Spryker/Zed/Development/Communication/Console/PluginUsageFinderConsole.php b/src/Spryker/Zed/Development/Communication/Console/PluginUsageFinderConsole.php index 1633a336..6e42f574 100644 --- a/src/Spryker/Zed/Development/Communication/Console/PluginUsageFinderConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/PluginUsageFinderConsole.php @@ -20,17 +20,24 @@ /** * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() - * @method \Spryker\Zed\Development\Business\DevelopmentBusinessFactory getFactory() + * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class PluginUsageFinderConsole extends Console { + /** + * @var string + */ protected const COMMAND_NAME = 'dev:plugin-usage:dump'; + + /** + * @var string + */ protected const ARGUMENT_MODULE = 'module'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -49,7 +56,7 @@ protected function configure() public function execute(InputInterface $input, OutputInterface $output) { $dependencyProviderCollectionTransfer = $this->getFacade()->getInProjectDependencyProviderUsedPlugins( - $this->buildModuleFilterTransfer() + $this->buildModuleFilterTransfer(), ); $this->printDependencyProviderPluginUsageList($dependencyProviderCollectionTransfer); @@ -89,6 +96,7 @@ protected function buildModuleFilterTransfer(): ?ModuleFilterTransfer } $moduleFilterTransfer = new ModuleFilterTransfer(); + /** @var string $moduleArgument */ $moduleArgument = $this->input->getArgument(static::ARGUMENT_MODULE); if (strpos($moduleArgument, '.') === false) { diff --git a/src/Spryker/Zed/Development/Communication/Console/PropelAbstractValidateConsole.php b/src/Spryker/Zed/Development/Communication/Console/PropelAbstractValidateConsole.php index 396cc3f0..941a847d 100644 --- a/src/Spryker/Zed/Development/Communication/Console/PropelAbstractValidateConsole.php +++ b/src/Spryker/Zed/Development/Communication/Console/PropelAbstractValidateConsole.php @@ -13,19 +13,32 @@ use Symfony\Component\Console\Output\OutputInterface; /** + * @internal Core Development internal only. + * * @method \Spryker\Zed\Development\Business\DevelopmentFacadeInterface getFacade() * @method \Spryker\Zed\Development\Communication\DevelopmentCommunicationFactory getFactory() */ class PropelAbstractValidateConsole extends Console { + /** + * @var string + */ protected const COMMAND_NAME = 'code:propel:validate-abstract'; + + /** + * @var string + */ protected const OPTION_MODULE = 'module'; + + /** + * @var string + */ protected const OPTION_STRICT = 'strict'; /** * @return void */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -45,6 +58,7 @@ protected function configure() */ public function execute(InputInterface $input, OutputInterface $output) { + /** @var string|null $module */ $module = $this->input->getOption(static::OPTION_MODULE); $message = $this->buildMessage($module); diff --git a/src/Spryker/Zed/Development/Communication/Console/RemoveClientIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/RemoveClientIdeAutoCompletionConsole.php new file mode 100644 index 00000000..d70a14c8 --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/RemoveClientIdeAutoCompletionConsole.php @@ -0,0 +1,50 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Removes IDE auto completion files for Client.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $this->getFacade()->removeClientIdeAutoCompletion(); + + $this->info('Removed Client IDE auto-completion files'); + + return static::CODE_SUCCESS; + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/RemoveGlueBackendIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/RemoveGlueBackendIdeAutoCompletionConsole.php new file mode 100644 index 00000000..51487b5f --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/RemoveGlueBackendIdeAutoCompletionConsole.php @@ -0,0 +1,50 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Removes IDE auto completion files for Glue Backend.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $this->getFacade()->removeGlueIdeAutoCompletion(); + + $this->info('Removed Glue Backend IDE auto-completion files'); + + return static::CODE_SUCCESS; + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/RemoveGlueIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/RemoveGlueIdeAutoCompletionConsole.php new file mode 100644 index 00000000..80f03cc0 --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/RemoveGlueIdeAutoCompletionConsole.php @@ -0,0 +1,50 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Removes IDE auto completion files for Glue.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $this->getFacade()->removeGlueIdeAutoCompletion(); + + $this->info('Removed Glue IDE auto-completion files'); + + return static::CODE_SUCCESS; + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/RemoveIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/RemoveIdeAutoCompletionConsole.php new file mode 100644 index 00000000..02b66548 --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/RemoveIdeAutoCompletionConsole.php @@ -0,0 +1,79 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Removes IDE auto completion files.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $dependingCommands = [ + RemoveYvesIdeAutoCompletionConsole::COMMAND_NAME, + RemoveZedIdeAutoCompletionConsole::COMMAND_NAME, + RemoveClientIdeAutoCompletionConsole::COMMAND_NAME, + RemoveServiceIdeAutoCompletionConsole::COMMAND_NAME, + RemoveGlueIdeAutoCompletionConsole::COMMAND_NAME, + RemoveGlueBackendIdeAutoCompletionConsole::COMMAND_NAME, + ]; + + foreach ($dependingCommands as $commandName) { + if (!$this->getApplication()->has($commandName)) { + $this->showCommandNotFoundMessage($commandName); + + continue; + } + $this->runDependingCommand($commandName); + + if ($this->hasError()) { + return $this->getLastExitCode(); + } + } + + return $this->getLastExitCode(); + } + + /** + * @param string $commandName + * + * @return void + */ + protected function showCommandNotFoundMessage(string $commandName): void + { + $this->output->writeln(sprintf('Can not find %s in your project.', $commandName)); + $this->output->writeln('You can fix this by adding the missing command to your project ConsoleDependencyProvider.'); + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/RemoveServiceIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/RemoveServiceIdeAutoCompletionConsole.php new file mode 100644 index 00000000..e1b653a3 --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/RemoveServiceIdeAutoCompletionConsole.php @@ -0,0 +1,50 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Removes IDE auto completion files for Service.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $this->getFacade()->removeServiceIdeAutoCompletion(); + + $this->info('Removed Service IDE auto-completion files'); + + return static::CODE_SUCCESS; + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/RemoveYvesIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/RemoveYvesIdeAutoCompletionConsole.php new file mode 100644 index 00000000..dab68c14 --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/RemoveYvesIdeAutoCompletionConsole.php @@ -0,0 +1,50 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Removes IDE auto completion files for Yves.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $this->getFacade()->removeYvesIdeAutoCompletion(); + + $this->info('Removed Yves IDE auto-completion files'); + + return static::CODE_SUCCESS; + } +} diff --git a/src/Spryker/Zed/Development/Communication/Console/RemoveZedIdeAutoCompletionConsole.php b/src/Spryker/Zed/Development/Communication/Console/RemoveZedIdeAutoCompletionConsole.php new file mode 100644 index 00000000..66680df3 --- /dev/null +++ b/src/Spryker/Zed/Development/Communication/Console/RemoveZedIdeAutoCompletionConsole.php @@ -0,0 +1,50 @@ +setName(static::COMMAND_NAME); + $this->setDescription('Removes IDE auto completion files for Zed.'); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return int + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $this->getFacade()->removeZedIdeAutoCompletion(); + + $this->info('Removed Zed IDE auto-completion files'); + + return static::CODE_SUCCESS; + } +} diff --git a/src/Spryker/Zed/Development/Communication/Controller/ArchitectureController.php b/src/Spryker/Zed/Development/Communication/Controller/ArchitectureController.php index 2ceddb50..c66b17d6 100644 --- a/src/Spryker/Zed/Development/Communication/Controller/ArchitectureController.php +++ b/src/Spryker/Zed/Development/Communication/Controller/ArchitectureController.php @@ -64,7 +64,7 @@ public function checkBundleAction(Request $request) $bundle = $request->query->get('bundle'); $namespace = $request->query->get('namespace'); $application = $request->query->get('application'); - $directory = $request->query->get('directory'); + $directory = (string)$request->query->get('directory'); $fileViolations = $this->getFacade()->runArchitectureSniffer($directory); diff --git a/src/Spryker/Zed/Development/Communication/Controller/DependencyController.php b/src/Spryker/Zed/Development/Communication/Controller/DependencyController.php index 124f9abd..804b43cb 100644 --- a/src/Spryker/Zed/Development/Communication/Controller/DependencyController.php +++ b/src/Spryker/Zed/Development/Communication/Controller/DependencyController.php @@ -19,8 +19,19 @@ */ class DependencyController extends AbstractController { + /** + * @var string + */ public const APPLICATION_ZED = 'Zed'; + + /** + * @var string + */ public const QUERY_KEY_BUILD_TREE = 'build-tree'; + + /** + * @var string + */ public const QUERY_KEY_MODULE = 'bundle'; /** @@ -28,10 +39,8 @@ class DependencyController extends AbstractController */ public function indexAction() { - $bundles = $this->getFacade()->getAllModules(); - return $this->viewResponse([ - 'bundles' => $bundles, + 'modules' => $this->getFacade()->getModules(), ]); } @@ -68,7 +77,7 @@ public function outgoingAction(Request $request) */ public function outgoingGraphAction(Request $request) { - $moduleName = $request->query->getAlnum(self::QUERY_KEY_MODULE); + $moduleName = $request->query->getAlnum(static::QUERY_KEY_MODULE); $organizationTransfer = new OrganizationTransfer(); $organizationTransfer->setName('Spryker'); @@ -82,7 +91,7 @@ public function outgoingGraphAction(Request $request) $form = $this->getFactory() ->createBundlesForm( $dataProvider->getData(), - $dataProvider->getOptions() + $dataProvider->getOptions(), ) ->handleRequest($request); diff --git a/src/Spryker/Zed/Development/Communication/Controller/DependencyProviderPluginUsageController.php b/src/Spryker/Zed/Development/Communication/Controller/DependencyProviderPluginUsageController.php index 60c6606f..e661bb0e 100644 --- a/src/Spryker/Zed/Development/Communication/Controller/DependencyProviderPluginUsageController.php +++ b/src/Spryker/Zed/Development/Communication/Controller/DependencyProviderPluginUsageController.php @@ -73,6 +73,7 @@ public function downloadCsvAction(): StreamedResponse $dependencyProviderPluginUsages = $this->getFacade()->getInProjectDependencyProviderUsedPlugins(); $streamCsv = function () use ($dependencyProviderPluginUsages) { + /** @var resource $resource */ $resource = fopen('php://output', 'w'); $header = ['organization', 'module', 'dependency_provider_class_name', 'plugin_organization', 'plugin_application', 'plugin_module', 'plugin_class_name']; fputcsv($resource, $header); diff --git a/src/Spryker/Zed/Development/Communication/DevelopmentCommunicationFactory.php b/src/Spryker/Zed/Development/Communication/DevelopmentCommunicationFactory.php index d5a18101..f93ea6b4 100644 --- a/src/Spryker/Zed/Development/Communication/DevelopmentCommunicationFactory.php +++ b/src/Spryker/Zed/Development/Communication/DevelopmentCommunicationFactory.php @@ -8,6 +8,8 @@ namespace Spryker\Zed\Development\Communication; use Generated\Shared\Transfer\ModuleTransfer; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizer; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface; use Spryker\Zed\Development\Communication\Form\BundlesFormType; use Spryker\Zed\Development\Communication\Form\DataProvider\BundleFormDataProvider; use Spryker\Zed\Kernel\Communication\AbstractCommunicationFactory; @@ -20,8 +22,8 @@ class DevelopmentCommunicationFactory extends AbstractCommunicationFactory { /** - * @param array $data - * @param array $options + * @param array $data + * @param array $options * * @return \Symfony\Component\Form\FormInterface */ @@ -40,9 +42,17 @@ public function createBundleFormDataProvider(Request $request, ModuleTransfer $m { $bundleFormDataProvider = new BundleFormDataProvider( $request, - $this->getFacade()->showOutgoingDependenciesForModule($moduleTransfer) + $this->getFacade()->showOutgoingDependenciesForModule($moduleTransfer), ); return $bundleFormDataProvider; } + + /** + * @return \Spryker\Zed\Development\Business\Normalizer\NameNormalizerInterface + */ + public function createNameNormalizer(): NameNormalizerInterface + { + return new NameNormalizer(); + } } diff --git a/src/Spryker/Zed/Development/Communication/Form/BundlesFormType.php b/src/Spryker/Zed/Development/Communication/Form/BundlesFormType.php index dc4021eb..fc4d7794 100644 --- a/src/Spryker/Zed/Development/Communication/Form/BundlesFormType.php +++ b/src/Spryker/Zed/Development/Communication/Form/BundlesFormType.php @@ -20,9 +20,24 @@ */ class BundlesFormType extends AbstractType { + /** + * @var string + */ public const FORM_TYPE_NAME = 'bundlesFormType'; + + /** + * @var string + */ public const BUNDLE_NAME_CHOICES = 'bundleNames'; + + /** + * @var string + */ public const EXCLUDED_BUNDLES = 'excludedBundles'; + + /** + * @var string + */ public const SHOW_INCOMING = 'showIncoming'; /** @@ -30,24 +45,23 @@ class BundlesFormType extends AbstractType * * @return void */ - public function configureOptions(OptionsResolver $resolver) + public function configureOptions(OptionsResolver $resolver): void { $resolver->setRequired(static::BUNDLE_NAME_CHOICES); } /** * @param \Symfony\Component\Form\FormBuilderInterface $builder - * @param array $options + * @param array $options * * @return void */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->add(static::EXCLUDED_BUNDLES, ChoiceType::class, [ 'expanded' => true, 'multiple' => true, 'choices' => array_flip($options[static::BUNDLE_NAME_CHOICES]), - 'choices_as_values' => true, ]); $builder->add(static::SHOW_INCOMING, CheckboxType::class, [ @@ -64,7 +78,7 @@ public function getBlockPrefix() } /** - * @deprecated Use `getBlockPrefix()` instead. + * @deprecated Use {@link getBlockPrefix()} instead. * * @return string */ diff --git a/src/Spryker/Zed/Development/Communication/Form/DataProvider/BundleFormDataProvider.php b/src/Spryker/Zed/Development/Communication/Form/DataProvider/BundleFormDataProvider.php index 6ae9e5f4..c25e2fc9 100644 --- a/src/Spryker/Zed/Development/Communication/Form/DataProvider/BundleFormDataProvider.php +++ b/src/Spryker/Zed/Development/Communication/Form/DataProvider/BundleFormDataProvider.php @@ -40,6 +40,7 @@ public function getData() { $excludedBundles = []; if ($this->request->request->has(BundlesFormType::FORM_TYPE_NAME)) { + /** @var array $formData */ $formData = $this->request->request->get(BundlesFormType::FORM_TYPE_NAME); if (isset($formData[BundlesFormType::EXCLUDED_BUNDLES])) { $excludedBundles = $formData[BundlesFormType::EXCLUDED_BUNDLES]; @@ -50,7 +51,7 @@ public function getData() } /** - * @return array + * @return array */ public function getOptions() { diff --git a/src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeBridge.php b/src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeBridge.php new file mode 100644 index 00000000..3752a690 --- /dev/null +++ b/src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeBridge.php @@ -0,0 +1,54 @@ +moduleFinderFacade = $moduleFinderFacade; + } + + /** + * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer + * + * @return array<\Generated\Shared\Transfer\ModuleTransfer> + */ + public function getProjectModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array + { + return $this->moduleFinderFacade->getProjectModules($moduleFilterTransfer); + } + + /** + * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer + * + * @return array<\Generated\Shared\Transfer\ModuleTransfer> + */ + public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array + { + return $this->moduleFinderFacade->getModules($moduleFilterTransfer); + } + + /** + * @return array<\Generated\Shared\Transfer\PackageTransfer> + */ + public function getPackages(): array + { + return $this->moduleFinderFacade->getPackages(); + } +} diff --git a/src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeInterface.php b/src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeInterface.php new file mode 100644 index 00000000..c2fde666 --- /dev/null +++ b/src/Spryker/Zed/Development/Dependency/Facade/DevelopmentToModuleFinderFacadeInterface.php @@ -0,0 +1,32 @@ + + */ + public function getProjectModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array; + + /** + * @param \Generated\Shared\Transfer\ModuleFilterTransfer|null $moduleFilterTransfer + * + * @return array<\Generated\Shared\Transfer\ModuleTransfer> + */ + public function getModules(?ModuleFilterTransfer $moduleFilterTransfer = null): array; + + /** + * @return array<\Generated\Shared\Transfer\PackageTransfer> + */ + public function getPackages(): array; +} diff --git a/src/Spryker/Zed/Development/DevelopmentConfig.php b/src/Spryker/Zed/Development/DevelopmentConfig.php index d6da3f4b..ce93b02d 100644 --- a/src/Spryker/Zed/Development/DevelopmentConfig.php +++ b/src/Spryker/Zed/Development/DevelopmentConfig.php @@ -15,19 +15,66 @@ class DevelopmentConfig extends AbstractBundleConfig { + /** + * @var string + */ public const BUNDLE_PLACEHOLDER = '[BUNDLE]'; + + /** + * @var string + */ protected const PHPSTAN_CONFIG_FILENAME = 'phpstan.neon'; + /** + * @var string + */ protected const NAMESPACE_SPRYKER = 'Spryker'; + + /** + * @var string + */ protected const NAMESPACE_SPRYKER_SHOP = 'SprykerShop'; + + /** + * @var string + */ protected const NAMESPACE_SPRYKER_ECO = 'SprykerEco'; + + /** + * @var string + */ protected const NAMESPACE_SPRYKER_SDK = 'SprykerSdk'; + + /** + * @var string + */ + protected const NAMESPACE_SPRYKER_MIDDLEWARE = 'SprykerMiddleware'; + + /** + * @var string + */ protected const NAMESPACE_SPRYKER_MERCHANT_PORTAL = 'SprykerMerchantPortal'; + /** + * @var string + */ + protected const GROUP_SPRYKER_TEST = 'SprykerTest'; + + /** + * @var string + */ + protected const NAMESPACE_SPRYKER_FEATURE = 'SprykerFeature'; + + /** + * @var array + */ public const APPLICATION_NAMESPACES = [ 'Orm', ]; + /** + * @var array + */ public const APPLICATIONS = [ 'Client', 'Service', @@ -37,23 +84,54 @@ class DevelopmentConfig extends AbstractBundleConfig 'Glue', ]; + /** + * @var array + */ + protected const APPLICATION_LAYERS = [ + 'Zed', + 'Client', + 'Yves', + 'Glue', + 'Service', + 'Shared', + ]; + + /** + * @var array + */ protected const INTERNAL_NAMESPACES_LIST = [ self::NAMESPACE_SPRYKER, + self::NAMESPACE_SPRYKER_FEATURE, self::NAMESPACE_SPRYKER_SHOP, self::NAMESPACE_SPRYKER_MERCHANT_PORTAL, ]; + /** + * @var array + */ protected const INTERNAL_NAMESPACES_TO_PATH_MAPPING = [ self::NAMESPACE_SPRYKER => APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'vendor/spryker/', + self::NAMESPACE_SPRYKER_FEATURE => APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'vendor/spryker-feature/', self::NAMESPACE_SPRYKER_SHOP => APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'vendor/spryker-shop/', self::NAMESPACE_SPRYKER_ECO => APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'vendor/spryker-eco/', self::NAMESPACE_SPRYKER_SDK => APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'vendor/spryker-sdk/', + self::NAMESPACE_SPRYKER_MIDDLEWARE => APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'vendor/spryker-middleware/', self::NAMESPACE_SPRYKER_MERCHANT_PORTAL => APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . 'vendor/spryker-merchant-portal/', ]; + /** + * @var array + */ protected const INTERNAL_PACKAGE_DIRECTORIES = ['spryker', 'spryker-shop', 'spryker-merchant-portal']; /** + * @var int + */ + protected const TIMEOUT_DEFAULT = 9000; + + /** + * @api + * * @return int */ public function getPermissionMode(): int @@ -62,15 +140,19 @@ public function getPermissionMode(): int } /** - * @return string[] + * @api + * + * @return array */ public function getInternalNamespaces(): array { - return ['Spryker', 'SprykerEco', 'SprykerSdk', 'SprykerShop', 'Orm']; + return ['Spryker', 'SprykerFeature', 'SprykerEco', 'SprykerSdk', 'SprykerShop', 'Orm']; } /** - * @return string[] + * @api + * + * @return array */ public function getTwigPathPatterns(): array { @@ -78,12 +160,16 @@ public function getTwigPathPatterns(): array $this->getPathToCore() . '%1$s/src/Spryker/Zed/%1$s/Presentation/', $this->getPathToCore() . '%1$s/src/Spryker/Yves/%1$s/Theme/', $this->getPathToShop() . '%1$s/src/SprykerShop/Yves/%1$s/Theme/', + $this->getPathToCore() . '%1$s/src/SprykerFeature/Zed/%1$s/Presentation/', + $this->getPathToCore() . '%1$s/src/SprykerFeature/Yves/%1$s/Theme/', ]; } /** * Gets path to application root directory. * + * @api + * * @return string */ public function getPathToRoot() @@ -94,7 +180,9 @@ public function getPathToRoot() /** * Gets Application layers. * - * @return array + * @api + * + * @return array */ public function getApplications() { @@ -104,7 +192,9 @@ public function getApplications() /** * Gets Application namespaces. * - * @return array + * @api + * + * @return array */ public function getApplicationNamespaces() { @@ -112,7 +202,22 @@ public function getApplicationNamespaces() } /** - * @deprecated Use \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerModulePathBuilder::buildPath() instead. + * Specification: + * - Gets Application layers. + * + * @api + * + * @return array + */ + public function getApplicationLayers(): array + { + return static::APPLICATION_LAYERS; + } + + /** + * @api + * + * @deprecated Use {@link \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerModulePathBuilder::buildPaths()} instead. * * Gets path to Spryker core modules. * @@ -130,7 +235,9 @@ public function getPathToCore() } /** - * @deprecated Use \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerSdkPathBuilder::buildPath() instead. + * @api + * + * @deprecated Use {@link \Spryker\Zed\Development\Business\DependencyTree\Finder\PathBuilder\SprykerSdkPathBuilder::buildPaths()} instead. * * Gets path to SprykerSdk core modules. * @@ -142,7 +249,9 @@ public function getPathToSdk() } /** - * @deprecated Use \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerShopModulePathBuilder::buildPath() instead. + * @api + * + * @deprecated Use {@link \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerShopModulePathBuilder::buildPaths()} instead. * * Gets path to SprykerShop core modules. * @@ -154,7 +263,23 @@ public function getPathToShop() } /** - * @deprecated Use \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerEcoModulePathBuilder::buildPath() instead. + * @api + * + * @deprecated Use {@link \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerShopModulePathBuilder::buildPaths()} instead. + * + * Gets path to SprykerFeature core modules. + * + * @return string + */ + public function getPathToFeature() + { + return $this->getPathToRoot() . 'vendor/spryker-feature/'; + } + + /** + * @api + * + * @deprecated Use {@link \Spryker\Zed\Development\Business\Module\PathBuilder\SprykerEcoModulePathBuilder::buildPaths()} instead. * * Gets path to SprykerEco core modules. * @@ -166,12 +291,15 @@ public function getPathToEco() } /** - * @return string[] + * @api + * + * @return array */ public function getOrganizationPathMap(): array { return [ 'Spryker' => $this->getPathToCore(), + 'SprykerFeature' => $this->getPathToCore(), 'SprykerEco' => $this->getPathToEco(), ]; } @@ -180,6 +308,10 @@ public function getOrganizationPathMap(): array * Either a relative or full path to the ruleset.xml or a name of an installed * standard (see `phpcs -i` for a list of available ones). * + * Deprecated: Directly provide a ROOT phpcs.xml in your project instead. + * + * @api + * * @return string */ public function getCodingStandard() @@ -193,16 +325,20 @@ public function getCodingStandard() * Either a relative or full path to the ruleset.xml or a name of an installed * standard. Can also be a comma separated list of multiple ones. * + * @api + * * @return string */ public function getArchitectureStandard() { - return __DIR__ . '/Business/PhpMd/ruleset.xml'; + return dirname(__DIR__, 4) . '/resources/phpmd/ruleset.xml'; } /** * Gets path to Application's composer.lock file. * + * @api + * * @return string */ public function getPathToComposerLock() @@ -211,6 +347,8 @@ public function getPathToComposerLock() } /** + * @api + * * @return string */ public function getPathToJsonDependencyTree() @@ -225,6 +363,8 @@ public function getPathToJsonDependencyTree() } /** + * @api + * * @return string */ public function getPhpstanConfigFilename(): string @@ -233,6 +373,8 @@ public function getPhpstanConfigFilename(): string } /** + * @api + * * @return string */ public function getPathToPhpstanModuleTemporaryConfigFolder() @@ -243,6 +385,8 @@ public function getPathToPhpstanModuleTemporaryConfigFolder() /** * Gets path to module config that holds information about engine modules. * + * @api + * * @return string */ public function getPathToBundleConfig() @@ -251,62 +395,136 @@ public function getPathToBundleConfig() } /** - * @return array + * @api + * + * @return array */ public function getExternalToInternalNamespaceMap() { return [ - 'Psr\\Log\\' => 'spryker/log', - 'Psr\\Container\\' => 'spryker/container', - 'Propel\\' => 'spryker/propel-orm', - 'Silex\\' => 'spryker/silex', - 'Pimple' => 'spryker/container', - 'Predis\\' => 'spryker/redis', + 'Codeception\\' => 'spryker/testify', + 'Doctrine\\Common\\Inflector' => 'spryker/doctrine-inflector', + 'Doctrine\\Inflector\\InflectorFactory' => 'spryker/doctrine-inflector', + 'DMS\\PHPUnitExtensions\\' => 'spryker/testify', + 'Egulias\\EmailValidator\\' => 'spryker/egulias', + 'Elastica\\' => 'spryker/elastica', + 'Faker\\' => 'spryker/testify', 'Guzzle\\' => 'spryker/guzzle', 'GuzzleHttp\\' => 'spryker/guzzle', + 'JsonPath\\' => 'spryker/json-path', + 'JsonSchema\\' => 'spryker/json-schema', + 'Laminas\\Config' => 'spryker/laminas', + 'Laminas\\Filter' => 'spryker/laminas', + 'Laminas\\ServiceManager' => 'spryker/laminas', 'League\\Csv\\' => 'spryker/csv', 'Monolog\\' => 'spryker/monolog', - 'Elastica\\' => 'spryker/elastica', + 'org\\bovigo\\vfs\\' => 'spryker/testify', + 'phpDocumentor\\GraphViz\\' => 'spryker/graphviz', + 'Propel\\' => 'spryker/propel-orm', + 'PHPUnit\\' => 'spryker/testify', + 'Pimple' => 'spryker/container', + 'Predis\\' => 'spryker/redis', + 'Psr\\Log\\' => 'spryker/log', + 'Psr\\Container\\' => 'spryker/container', + 'Ramsey\\Uuid' => 'spryker/ramsey-uuid', + 'Silex\\' => 'spryker/silex', + 'Spryker\\DecimalObject\\' => 'spryker/decimal-object', + 'Spryker\\ChecksumGenerator\\' => 'spryker/checksum-generator', + 'Symfony\\Bridge\\Twig\\' => 'spryker/symfony', + 'Symfony\\Bundle\\WebProfilerBundle\\' => 'spryker/symfony', 'Symfony\\Component\\' => 'spryker/symfony', + 'Symfony\\Contracts\\' => 'spryker/symfony', + 'Symfony\\Cmf\\' => 'spryker/symfony', 'Twig_' => 'spryker/twig', 'Twig\\' => 'spryker/twig', + 'Webmozart\\Glob' => 'spryker/util-glob', + 'Willdurand\\Negotiation\\' => 'spryker/willdurand-negotiation', 'Zend\\' => 'spryker/zend', - 'phpDocumentor\\GraphViz\\' => 'spryker/graphviz', - 'Egulias\\EmailValidator\\' => 'spryker/egulias', - 'Ramsey\\Uuid' => 'spryker/ramsey-uuid', - 'Doctrine\\Common\\Inflector' => 'spryker/doctrine-inflector', ]; } /** - * @return array + * @api + * + * @return array */ public function getExternalToInternalMap() { return [ - 'psr/log' => 'spryker/log', - 'propel/propel' => 'spryker/propel-orm', - 'silex/silex' => 'spryker/silex', - 'pimple/pimple' => 'spryker/container', - 'mandrill/mandrill' => 'spryker/mandrill', - 'predis/predis' => 'spryker/redis', - 'guzzle/guzzle' => 'spryker/guzzle', + 'codeception/codeception' => 'spryker/testify', + 'doctrine/inflector' => 'spryker/doctrine-inflector', + 'egulias/email-validator' => 'spryker/egulias', + 'fakerphp/faker' => 'spryker/testify', + 'galbar/jsonpath' => 'spryker/json-path', 'guzzlehttp/guzzle' => 'spryker/guzzle', + 'justinrainbow/json-schema' => 'spryker/json-schema', + 'laminas/laminas-config' => 'spryker/laminas', + 'laminas/laminas-filter' => 'spryker/laminas', + 'laminas/laminas-servicemanager' => 'spryker/laminas', 'league/csv' => 'spryker/csv', + 'league/oauth2-server' => 'spryker/oauth', + 'mandrill/mandrill' => 'spryker/mandrill', + 'mikey179/vfsstream' => 'spryker/testify', + 'minishlink/web-push' => 'spryker/push-notification-web-push-php', + 'moneyphp/money' => 'spryker/money', 'monolog/monolog' => 'spryker/monolog', - 'ruflin/elastica' => 'spryker/elastica', - '/symfony/' => 'spryker/symfony', - 'twig/twig' => 'spryker/twig', - '/zendframework/' => 'spryker/zend', + 'pimple/pimple' => 'spryker/container', + 'phpbench/phpbench' => 'spryker-sdk/benchmark', 'phpdocumentor/graphviz' => 'spryker/graphviz', - 'egulias/email-validator' => 'spryker/egulias', + 'predis/predis' => 'spryker/redis', + 'propel/propel' => 'spryker/propel-orm', + 'psr/log' => 'spryker/log', + 'psr/container' => 'spryker/container', 'ramsey/uuid' => 'spryker/ramsey-uuid', - 'doctrine/inflector' => 'spryker/doctrine-inflector', + 'ruflin/elastica' => 'spryker/elastica', + 'symfony-cmf/routing' => 'spryker/symfony', + 'symfony/config' => 'spryker/symfony', + 'symfony/console' => 'spryker/symfony', + 'symfony/debug' => 'spryker/symfony', + 'symfony/error-handler' => 'spryker/symfony', + 'symfony/event-dispatcher' => 'spryker/symfony', + 'symfony/filesystem' => 'spryker/symfony', + 'symfony/finder' => 'spryker/symfony', + 'symfony/form' => 'spryker/symfony', + 'symfony/http-client' => 'spryker/symfony', + 'symfony/http-foundation' => 'spryker/symfony', + 'symfony/http-kernel' => 'spryker/symfony', + 'symfony/intl' => 'spryker/symfony', + 'symfony/mime' => 'spryker/symfony', + 'symfony/messenger' => 'spryker/symfony', + 'symfony/lock' => 'spryker/symfony', + 'symfony/options-resolver' => 'spryker/symfony', + 'symfony/process' => 'spryker/symfony', + 'symfony/property-access' => 'spryker/symfony', + 'symfony/routing' => 'spryker/symfony', + 'symfony/security-core' => 'spryker/symfony', + 'symfony/security-csrf' => 'spryker/symfony', + 'symfony/security-guard' => 'spryker/symfony', + 'symfony/security-http' => 'spryker/symfony', + 'symfony/serializer' => 'spryker/symfony', + 'symfony/stopwatch' => 'spryker/symfony', + 'symfony/translation' => 'spryker/symfony', + 'symfony/translation-contracts' => 'spryker/symfony', + 'symfony/twig-bridge' => 'spryker/symfony', + 'symfony/validator' => 'spryker/symfony', + 'symfony/web-profiler-bundle' => 'spryker/web-profiler', + 'symfony/yaml' => 'spryker/symfony', + 'swiftmailer/swiftmailer' => 'spryker/mail', + 'twig/twig' => 'spryker/twig', + 'webmozart/glob' => 'spryker/util-glob', + 'willdurand/negotiation' => 'spryker/willdurand-negotiation', + 'zendframework/zend-config' => 'spryker/zend', + 'zendframework/zend-filter' => 'spryker/zend', + 'zendframework/zend-servicemanager' => 'spryker/zend', ]; } /** - * @return array + * @api + * + * @deprecated Will be removed without replacement. + * + * @return array */ public function getIgnorableDependencies() { @@ -317,7 +535,6 @@ public function getIgnorableDependencies() 'phploc/phploc', 'phpmd/phpmd', 'sebastian/phpcpd', - 'codeception/codeception', 'fabpot/php-cs-fixer', 'sensiolabs/security-checker', 'sllh/composer-versions-check', @@ -325,7 +542,9 @@ public function getIgnorableDependencies() } /** - * @return string[] + * @api + * + * @return array */ public function getYvesIdeAutoCompletionOptions() { @@ -336,7 +555,9 @@ public function getYvesIdeAutoCompletionOptions() } /** - * @return string[] + * @api + * + * @return array */ public function getZedIdeAutoCompletionOptions() { @@ -347,7 +568,9 @@ public function getZedIdeAutoCompletionOptions() } /** - * @return array + * @api + * + * @return array */ public function getClientIdeAutoCompletionOptions() { @@ -358,7 +581,9 @@ public function getClientIdeAutoCompletionOptions() } /** - * @return array + * @api + * + * @return array */ public function getGlueIdeAutoCompletionOptions() { @@ -369,6 +594,21 @@ public function getGlueIdeAutoCompletionOptions() } /** + * @api + * + * @return array + */ + public function getGlueBackendIdeAutoCompletionOptions(): array + { + $options = $this->getDefaultIdeAutoCompletionOptions(); + $options[IdeAutoCompletionOptionConstants::APPLICATION_NAME] = 'GlueBackend'; + + return $options; + } + + /** + * @api + * * @return array */ public function getServiceIdeAutoCompletionOptions() @@ -380,7 +620,7 @@ public function getServiceIdeAutoCompletionOptions() } /** - * @return array + * @return array */ protected function getDefaultIdeAutoCompletionOptions() { @@ -388,18 +628,20 @@ protected function getDefaultIdeAutoCompletionOptions() IdeAutoCompletionOptionConstants::TARGET_BASE_DIRECTORY => APPLICATION_SOURCE_DIR . '/', IdeAutoCompletionOptionConstants::TARGET_DIRECTORY_PATTERN => sprintf( 'Generated/%s/Ide', - IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER + IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, ), IdeAutoCompletionOptionConstants::TARGET_NAMESPACE_PATTERN => sprintf( 'Generated\%s\Ide', - IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER + IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, ), IdeAutoCompletionConstants::DIRECTORY_PERMISSION => $this->getPermissionMode(), ]; } /** - * @return string[] + * @api + * + * @return array */ public function getIdeAutoCompletionSourceDirectoryGlobPatterns() { @@ -410,7 +652,9 @@ public function getIdeAutoCompletionSourceDirectoryGlobPatterns() } /** - * @return string[] + * @api + * + * @return array */ public function getIdeAutoCompletionGeneratorTemplatePaths() { @@ -422,34 +666,75 @@ public function getIdeAutoCompletionGeneratorTemplatePaths() /** * Returns CLI commmand to run the architecture sniffer with [BUNDLE] placeholder * + * @api + * * @return string */ public function getArchitectureSnifferCommand() { - return $this->getPhpMdCommand() . ' ' . self::BUNDLE_PLACEHOLDER . ' xml ' . $this->getArchitectureSnifferRuleset(); + return $this->getPhpMdCommand() . ' ' . static::BUNDLE_PLACEHOLDER . ' xml ' . $this->getArchitectureSnifferRuleset(); } /** * Either a relative or full path to the ruleset.xml * + * @api + * * @return string */ public function getArchitectureSnifferRuleset() { $vendorDir = APPLICATION_VENDOR_DIR . DIRECTORY_SEPARATOR; + return $vendorDir . 'spryker/architecture-sniffer/src/ruleset.xml'; } /** + * @api + * + * @return string + */ + public function getCodeSnifferRuleset(): string + { + return dirname(__DIR__, 4) . DIRECTORY_SEPARATOR . 'ruleset.xml'; + } + + /** + * @api + * + * @return string + */ + public function getCodeSnifferStrictRuleset(): string + { + return dirname(__DIR__, 4) . DIRECTORY_SEPARATOR . 'rulesetStrict.xml'; + } + + /** + * Returns the path to the CodeSniffer feature ruleset. + * + * @api + * + * @return string + */ + public function getCodeSnifferFeatureRuleset(): string + { + return $this->getPathToFeature() . 'phpcs.xml'; + } + + /** + * @api + * * @return string */ public function getPhpMdCommand() { - return 'vendor/bin/phpmd'; + return 'php -d error_reporting=E_ALL&~E_DEPRECATED vendor/bin/phpmd'; } /** - * @return array + * @api + * + * @return array */ public function getProjectNamespaces() { @@ -457,7 +742,9 @@ public function getProjectNamespaces() } /** - * @return array + * @api + * + * @return array */ public function getCoreNamespaces() { @@ -467,6 +754,8 @@ public function getCoreNamespaces() /** * Gets default priority for architecture sniffer. * + * @api + * * @return int */ public function getArchitectureSnifferDefaultPriority(): int @@ -477,16 +766,22 @@ public function getArchitectureSnifferDefaultPriority(): int /** * Gets PHPStan default level. The higher, the better. * + * Recommended level is 8 (include nullable safety). + * + * @api + * * @return int */ public function getPhpstanLevel() { - return 3; + return 7; } /** * Gets CodeSniffer default level. The higher, the better. * + * @api + * * @return int */ public function getCodeSnifferLevel(): int @@ -495,7 +790,9 @@ public function getCodeSnifferLevel(): int } /** - * @return string[] + * @api + * + * @return array */ public function getInternalNamespacesList(): array { @@ -503,13 +800,16 @@ public function getInternalNamespacesList(): array } /** + * @api + * * @param string $namespace * * @return string|null */ public function getPathToInternalNamespace(string $namespace): ?string { - if ($pathToSprykerRoot = $this->checkPathToSprykerRoot($namespace)) { + $pathToSprykerRoot = $this->checkPathToSprykerRoot($namespace); + if ($pathToSprykerRoot) { return $pathToSprykerRoot; } @@ -521,7 +821,9 @@ public function getPathToInternalNamespace(string $namespace): ?string } /** - * @return string[] + * @api + * + * @return array */ public function getPathsToInternalNamespace(): array { @@ -550,10 +852,92 @@ protected function checkPathToSprykerRoot(string $namespace): ?string } /** - * @return string[] + * @api + * + * @deprecated Use `spryker/module-finder` instead. + * + * @return array */ public function getInternalPackageDirectories(): array { return static::INTERNAL_PACKAGE_DIRECTORIES; } + + /** + * Specification: + * - Returns group names to run only tests that have all of the groups. + * - Example: ['Customer', 'Communication'] inclusive parameter runs tests Communication suite in Customer module. + * + * @api + * + * @return array + */ + public function getDefaultInclusiveGroups(): array + { + return [ + static::GROUP_SPRYKER_TEST, + ]; + } + + /** + * Specification: + * - Returns Spryker namespace. + * + * @api + * + * @return string + */ + public function getNamespaceSpryker(): string + { + return static::NAMESPACE_SPRYKER; + } + + /** + * Specification: + * - Returns Spryker Shop namespace. + * + * @api + * + * @return string + */ + public function getNamespaceSprykerShop(): string + { + return static::NAMESPACE_SPRYKER_SHOP; + } + + /** + * @api + * + * @return int + */ + public function getProcessTimeout(): int + { + return static::TIMEOUT_DEFAULT; + } + + /** + * Specification: + * - Is used to determine if the application is in the standalone mode e.g. without the project context. + * + * @api + * + * @return bool + */ + public function isStandaloneMode(): bool + { + return (bool)getenv('DEVELOPMENT_STANDALONE_MODE'); + } + + /** + * Specification: + * - Returns Spryker Feature namespace. + * + * @api + * + * @return string + */ + public function getSprykerFeatureNamespace(): string + { + return static::NAMESPACE_SPRYKER_FEATURE; + } } diff --git a/src/Spryker/Zed/Development/DevelopmentDependencyProvider.php b/src/Spryker/Zed/Development/DevelopmentDependencyProvider.php index d1e33ac8..1cadb5b3 100644 --- a/src/Spryker/Zed/Development/DevelopmentDependencyProvider.php +++ b/src/Spryker/Zed/Development/DevelopmentDependencyProvider.php @@ -7,7 +7,10 @@ namespace Spryker\Zed\Development; +use Nette\DI\Config\Adapters\NeonAdapter; +use Nette\DI\Config\Adapters\PhpAdapter; use Nette\DI\Config\Loader; +use Spryker\Zed\Development\Dependency\Facade\DevelopmentToModuleFinderFacadeBridge; use Spryker\Zed\Graph\Communication\Plugin\GraphPlugin; use Spryker\Zed\Kernel\AbstractBundleDependencyProvider; use Spryker\Zed\Kernel\Container; @@ -21,13 +24,46 @@ */ class DevelopmentDependencyProvider extends AbstractBundleDependencyProvider { + /** + * @var string + */ + public const FACADE_MODULE_FINDER = 'module finder facade'; + + /** + * @var string + */ public const PLUGIN_GRAPH = 'graph plugin'; + + /** + * @var string + */ public const FINDER = 'finder'; + + /** + * @var string + */ public const FILESYSTEM = 'filesystem'; + + /** + * @var string + */ public const CONFIG_LOADER = 'config loader'; + + /** + * @var string + */ public const TWIG_ENVIRONMENT = 'twig environment'; + + /** + * @var string + */ public const TWIG_LOADER_FILESYSTEM = 'twig loader filesystem'; + /** + * @var string + */ + public const PHPSTAN_ADAPTERS = 'PHPSTAN_ADAPTERS'; + /** * @param \Spryker\Zed\Kernel\Container $container * @@ -35,29 +71,32 @@ class DevelopmentDependencyProvider extends AbstractBundleDependencyProvider */ public function provideBusinessLayerDependencies(Container $container) { - $container[static::PLUGIN_GRAPH] = function () { + $container->set(static::PLUGIN_GRAPH, function () { return $this->getGraphPlugin(); - }; + }); - $container[static::FINDER] = function () { + $container->set(static::FINDER, function () { return $this->createFinder(); - }; + }); - $container[static::FILESYSTEM] = function () { + $container->set(static::FILESYSTEM, function () { return $this->createFilesystem(); - }; + }); - $container[static::CONFIG_LOADER] = function () { + $container->set(static::CONFIG_LOADER, function () { return $this->createConfigLoader(); - }; + }); - $container[static::TWIG_ENVIRONMENT] = function () { + $container->set(static::TWIG_ENVIRONMENT, function () { return $this->createTwigEnvironment(); - }; + }); - $container[static::TWIG_LOADER_FILESYSTEM] = function () { + $container->set(static::TWIG_LOADER_FILESYSTEM, function () { return $this->createTwigLoaderFilesystem(); - }; + }); + + $container = $this->addModuleFinderFacade($container); + $container = $this->addPhpstanAdapters($container); return $container; } @@ -109,4 +148,39 @@ protected function createTwigLoaderFilesystem() { return new FilesystemLoader(); } + + /** + * @param \Spryker\Zed\Kernel\Container $container + * + * @return \Spryker\Zed\Kernel\Container + */ + protected function addModuleFinderFacade(Container $container): Container + { + $container->set(static::FACADE_MODULE_FINDER, function (Container $container) { + $developmentToModuleFinderFacadeBridge = new DevelopmentToModuleFinderFacadeBridge( + $container->getLocator()->moduleFinder()->facade(), + ); + + return $developmentToModuleFinderFacadeBridge; + }); + + return $container; + } + + /** + * @param \Spryker\Zed\Kernel\Container $container + * + * @return \Spryker\Zed\Kernel\Container + */ + protected function addPhpstanAdapters(Container $container): Container + { + $container->set(static::PHPSTAN_ADAPTERS, function (Container $container) { + return [ + 'php' => PhpAdapter::class, + 'neon' => NeonAdapter::class, + ]; + }); + + return $container; + } } diff --git a/src/Spryker/Zed/Development/Presentation/Dependency/incoming.twig b/src/Spryker/Zed/Development/Presentation/Dependency/incoming.twig index 44c958ac..945b2ed2 100644 --- a/src/Spryker/Zed/Development/Presentation/Dependency/incoming.twig +++ b/src/Spryker/Zed/Development/Presentation/Dependency/incoming.twig @@ -4,13 +4,17 @@

{{ "Incoming dependencies of the" | trans }} {{ bundle }} {{ "module" | trans }}

- - + + + + - {% for count, dependency in dependencies %} + {% for dependency in dependencies %} - - + + + + {% endfor %}
{{ 'Dependency' | trans }}{{ 'Count' | trans }}{{ 'Module' | trans }}{{ 'Total Count' | trans }}{{ 'Optional Count' | trans }}{{ 'Test Count' | trans }}
{{ count }}{{ dependency }}{{ dependency.name }}{{ dependency.totalDependencyCount }}{{ dependency.optionalDependencyCount }}{{ dependency.testDependencyCount }}
diff --git a/src/Spryker/Zed/Development/Presentation/Dependency/index.twig b/src/Spryker/Zed/Development/Presentation/Dependency/index.twig index d93c12c0..e0ed82c7 100644 --- a/src/Spryker/Zed/Development/Presentation/Dependency/index.twig +++ b/src/Spryker/Zed/Development/Presentation/Dependency/index.twig @@ -10,16 +10,16 @@ {{ 'Adjacency Matrix' | trans }}

- {% for bundle in bundles %} + {% for module in modules %} - + {% endfor %} diff --git a/src/Spryker/Zed/Development/Presentation/Dependency/stability.twig b/src/Spryker/Zed/Development/Presentation/Dependency/stability.twig index f1f9a490..3bc7b8fd 100644 --- a/src/Spryker/Zed/Development/Presentation/Dependency/stability.twig +++ b/src/Spryker/Zed/Development/Presentation/Dependency/stability.twig @@ -26,13 +26,13 @@ - - - - - - - 150 %} style="color: red"{% endif %} align="right">{{ info.sprykerStability }} + + + + + + + 150 %} style="color: red"{% endif %} align="right">{{ info.sprykerStabilityNotFormatted | executeFilterIfExists('formatFloat', app.locale) }} {% endfor %}
{{ bundle }}{{ module.name }} - {{ 'in' | trans }}  - {{ 'out' | trans }}  - {{ 'out graph' | trans }}  - {{ 'simple' | trans }}  - {{ 'detailed' | trans }}  - {{ 'adjacency' | trans }} + {{ 'in' | trans }}  + {{ 'out' | trans }}  + {{ 'out graph' | trans }}  + {{ 'simple' | trans }}  + {{ 'detailed' | trans }}  + {{ 'adjacency' | trans }}
{{ bundle }} {{ info.in | length }}{{ info.out | length }}{{ info.stability }}{{ info.indirectIn | length }}{{ info.indirectOut | length }}{{ info.indirectStability }}{{ info.in | length | executeFilterIfExists('formatInt', app.locale) }}{{ info.out | length | executeFilterIfExists('formatInt', app.locale) }}{{ info.stabilityNotFormatted | executeFilterIfExists('formatFloat', app.locale) }}{{ info.indirectIn | length | executeFilterIfExists('formatInt', app.locale) }}{{ info.indirectOut | length | executeFilterIfExists('formatInt', app.locale) }}{{ info.indirectStabilityNotFormatted | executeFilterIfExists('formatFloat', app.locale) }}
diff --git a/tests/SprykerTest/Zed/Development/Business/ArchitectureSniffer/ArchitectureSnifferTest.php b/tests/SprykerTest/Zed/Development/Business/ArchitectureSniffer/ArchitectureSnifferTest.php new file mode 100644 index 00000000..585aaa70 --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Business/ArchitectureSniffer/ArchitectureSnifferTest.php @@ -0,0 +1,209 @@ +createMock(ReaderInterface::class); + $configurationBuilderMock = $this->createMock(SnifferConfigurationBuilderInterface::class); + $configurationBuilderMock->method('getConfiguration')->willReturn([]); + + $architectureSniffer = new ArchitectureSniffer($xmlReaderMock, 'command', $configurationBuilderMock); + + // Act + $result = $architectureSniffer->run('directory', []); + + // Assert + $this->assertEmpty($result); + } + + /** + * @return void + */ + public function shouldThrowExceptionForInvalidDirectory(): void + { + // Assert + $this->expectException(Exception::class); + + // Arrange + $xmlReaderMock = $this->createMock(ReaderInterface::class); + $configurationBuilderMock = $this->createMock(SnifferConfigurationBuilderInterface::class); + $configurationBuilderMock + ->method('getConfiguration') + ->willReturn(['someOption' => 'value']); + + $architectureSniffer = new ArchitectureSniffer($xmlReaderMock, 'command', $configurationBuilderMock); + + // Act + $architectureSniffer->run('invalid/directory', []); + } + + /** + * @return void + */ + public function shouldProcessValidDirectory(): void + { + // Arrange + $xmlReaderMock = $this->createMock(ReaderInterface::class); + $xmlReaderMock->method('fromString')->willReturn([ + 'file' => [ + '@attributes' => ['name' => 'someFile'], + 'violation' => [ + ['@attributes' => ['priority' => 1], '_' => 'Some violation'], + ], + ], + ]); + $configurationBuilderMock = $this->createMock(SnifferConfigurationBuilderInterface::class); + $configurationBuilderMock + ->method('getConfiguration') + ->willReturn(['priority' => 1]); + + $architectureSniffer = new ArchitectureSniffer($xmlReaderMock, 'command', $configurationBuilderMock); + + // Act + $result = $architectureSniffer->run('vendor/spryker/spryker/Bundles/Development', []); + + // Assert + $this->assertNotEmpty($result); + $this->assertArrayHasKey('fileName', $result[0]); + $this->assertArrayHasKey('description', $result[0]); + } + + /** + * @return void + */ + public function shouldHandleDryRunOption(): void + { + // Arrange + $xmlReaderMock = $this->createMock(ReaderInterface::class); + $configurationBuilderMock = $this->createMock(SnifferConfigurationBuilderInterface::class); + $configurationBuilderMock + ->method('getConfiguration') + ->willReturn(['dry-run' => true]); + + $architectureSniffer = new ArchitectureSniffer($xmlReaderMock, 'command', $configurationBuilderMock); + + // Assert + $this->expectOutputRegex('/command/'); + + // Act + $architectureSniffer->run('directory', ['dry-run' => true]); + } + + /** + * @return void + */ + public function shouldIgnoreErrorsBasedOnConfiguration(): void + { + // Arrabge + $xmlReaderMock = $this->createMock(ReaderInterface::class); + $xmlReaderMock->method('fromString')->willReturn([ + 'file' => [ + '@attributes' => ['name' => 'someFile'], + 'violation' => [ + ['@attributes' => ['priority' => 1], '_' => 'Ignored violation'], + ['@attributes' => ['priority' => 2], '_' => 'Processed violation'], + ], + ], + ]); + $configurationBuilderMock = $this->createMock(SnifferConfigurationBuilderInterface::class); + $configurationBuilderMock + ->method('getConfiguration') + ->willReturn(['ignoreErrors' => ['/Ignored violation/']]); + + $architectureSniffer = new ArchitectureSniffer($xmlReaderMock, 'command', $configurationBuilderMock); + + // Act + $result = $architectureSniffer->run('directory', ['ignoreErrors' => ['/Ignored violation/']]); + + // Assert + $this->assertCount(1, $result); + $this->assertEquals('Processed violation', $result[0]['description']); + } + + /** + * @return void + */ + public function testResolveRulesetPathWithCustomRuleset(): void + { + // Arrange + $tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'testDir' . uniqid(); + mkdir($tempDir, 0777, true); + + $rulesetFile = $tempDir . DIRECTORY_SEPARATOR . 'architectural-ruleset.xml'; + touch($rulesetFile); + + $xmlReaderMock = $this->createMock(ReaderInterface::class); + $configurationBuilderMock = $this->createMock(SnifferConfigurationBuilderInterface::class); + $defaultCommand = 'phpmd /path/to/src text /path/to/ruleset.xml'; + $architectureSniffer = new ArchitectureSniffer($xmlReaderMock, $defaultCommand, $configurationBuilderMock); + + $reflectionMethod = new ReflectionMethod(ArchitectureSniffer::class, 'resolveRulesetPath'); + $reflectionMethod->setAccessible(true); + + // Act + $result = $reflectionMethod->invoke($architectureSniffer, $tempDir . DIRECTORY_SEPARATOR . 'module'); + + // Assert + $this->assertStringContainsString($rulesetFile, $result); + $this->assertNotEquals($defaultCommand, $result); + } + + /** + * @return void + */ + public function testResolveRulesetPathWithoutCustomRuleset(): void + { + // Arrange + $tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'testDir' . uniqid(); + mkdir($tempDir, 0777, true); + + $xmlReaderMock = $this->createMock(ReaderInterface::class); + $configurationBuilderMock = $this->createMock(SnifferConfigurationBuilderInterface::class); + $defaultCommand = 'phpmd /path/to/src text /path/to/ruleset.xml'; + $architectureSniffer = new ArchitectureSniffer($xmlReaderMock, $defaultCommand, $configurationBuilderMock); + + $reflectionMethod = new ReflectionMethod(ArchitectureSniffer::class, 'resolveRulesetPath'); + $reflectionMethod->setAccessible(true); + + // Act + $result = $reflectionMethod->invoke($architectureSniffer, $tempDir . DIRECTORY_SEPARATOR . 'module'); + + // Assert + $this->assertEquals($defaultCommand, $result); + } +} diff --git a/tests/SprykerTest/Zed/Development/Business/CodeStyleSniffer/CodeStyleSnifferTest.php b/tests/SprykerTest/Zed/Development/Business/CodeStyleSniffer/CodeStyleSnifferTest.php index 49e0e7f7..fc76cc30 100644 --- a/tests/SprykerTest/Zed/Development/Business/CodeStyleSniffer/CodeStyleSnifferTest.php +++ b/tests/SprykerTest/Zed/Development/Business/CodeStyleSniffer/CodeStyleSnifferTest.php @@ -8,10 +8,15 @@ namespace SprykerTest\Zed\Development\Business\CodeStyleSniffer; use Codeception\Test\Unit; +use ReflectionMethod; +use ReflectionObject; use Spryker\Zed\Development\Business\CodeStyleSniffer\CodeStyleSniffer; +use Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationInterface; +use Spryker\Zed\Development\Business\Resolver\CodeStylePathResolver; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -22,6 +27,11 @@ */ class CodeStyleSnifferTest extends Unit { + /** + * @var string + */ + protected const DEVELOPMENT_MODULE_PATH_REGEX = '#' . APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . '.+/Development/#'; + /** * @var \SprykerTest\Zed\Development\DevelopmentBusinessTester */ @@ -32,6 +42,11 @@ class CodeStyleSnifferTest extends Unit */ protected $pathToCore = 'vendor/spryker/spryker/Bundles/'; + /** + * @var string + */ + protected $developmentModule = 'Spryker.Development'; + /** * The list of default CodeStyleSniffer options. * @@ -59,114 +74,161 @@ class CodeStyleSnifferTest extends Unit /** * @return void */ - public function testCheckCodeStyleRunsCommandInProject() + public function testCheckCsForAllModulesRunsWithSpecificRuleset(): void { - $options = ['ignore' => 'vendor/'] + $this->defaultOptions; - $pathToApplicationRoot = APPLICATION_ROOT_DIR . '/'; - $codeStyleSnifferMock = $this->getCodeStyleSnifferMock($pathToApplicationRoot, $options); + $resolvedPaths = $this->getResolvedPathsForAllSprykerModules(); - $codeStyleSnifferMock->checkCodeStyle(null, $options); - } + $developmentModulePath = current(preg_grep(static::DEVELOPMENT_MODULE_PATH_REGEX, array_keys($resolvedPaths))); + $developmentLevel = $this->getDevelopmentCsLevel($resolvedPaths[$developmentModulePath]); - /** - * @return void - */ - public function testCheckCodeStyleRunsCommandInProjectModule() - { - $options = ['ignore' => 'vendor/'] + $this->defaultOptions; - $pathToApplicationRoot = APPLICATION_ROOT_DIR . '/src/Pyz/Zed/Development/'; - $codeStyleSnifferMock = $this->getCodeStyleSnifferMock($pathToApplicationRoot, $options); - - $codeStyleSnifferMock->checkCodeStyle('Development', $options); - } + $codeStyleSnifferMock = $this->getCodeStyleSnifferMock( + $this->normalizePathToModule($developmentModulePath), + $developmentLevel, + ); - /** - * @return void - */ - public function testCheckCodeStyleRunsCommandInCore() - { - $module = 'Spryker.all'; $options = [ - 'ignore' => 'vendor/', - 'module' => $module, - ] + $this->defaultOptions; + 'ignore' => 'vendor/', + 'module' => $this->developmentModule, + 'level' => $this->tester->getDefaultLevel(), + ] + $this->defaultOptions; - $path = APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . $this->pathToCore; - $codeStyleSnifferMock = $this->getCodeStyleSnifferMock($path, $options); - - $codeStyleSnifferMock->checkCodeStyle($module, $options); + $codeStyleSnifferMock->checkCodeStyle($this->developmentModule, $options); } /** * @return void */ - public function testCheckCodeStyleRunsCommandInCoreModuleForLevelOne() + public function testCheckCodeStyleRunsCommandInCoreModuleForLevelOne(): void { - $module = 'Spryker.Development'; $options = [ 'ignore' => 'vendor/', - 'module' => $module, + 'module' => $this->developmentModule, 'level' => 1, ] + $this->defaultOptions; - $path = APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . $this->pathToCore . 'Development/'; - $codeStyleSnifferMock = $this->getCodeStyleSnifferMock($path, $options); + $developmentModulePath = dirname(__DIR__, 6) . DIRECTORY_SEPARATOR; + $codeStyleSnifferMock = $this->getCodeStyleSnifferMock($developmentModulePath, $options['level']); - $codeStyleSnifferMock->checkCodeStyle($module, $options); + $codeStyleSnifferMock->checkCodeStyle($this->developmentModule, $options); } /** * @return void */ - public function testCheckCodeStyleRunsCommandInCoreModuleForLevelTwo() + public function testCheckCodeStyleRunsCommandInCoreModuleForLevelTwo(): void { - $module = 'Spryker.Development'; $options = [ 'ignore' => 'vendor/', - 'module' => $module, + 'module' => $this->developmentModule, 'level' => 2, ] + $this->defaultOptions; - $path = APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR . $this->pathToCore . 'Development/'; - $codeStyleSnifferMock = $this->getCodeStyleSnifferMock($path, $options); + $developmentModulePath = dirname(__DIR__, 6) . DIRECTORY_SEPARATOR; + $codeStyleSnifferMock = $this->getCodeStyleSnifferMock($developmentModulePath, $options['level']); - $codeStyleSnifferMock->checkCodeStyle($module, $options); + $codeStyleSnifferMock->checkCodeStyle($this->developmentModule, $options); } /** - * @param string $expectedPathToRunCommandWith - * @param array $options + * @param string $developmentModulePath + * @param int $level * * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\CodeStyleSniffer\CodeStyleSniffer */ - protected function getCodeStyleSnifferMock($expectedPathToRunCommandWith, array $options) + protected function getCodeStyleSnifferMock(string $developmentModulePath, int $level): CodeStyleSniffer { $developmentConfig = $this->tester->createDevelopmentConfig(); - $codingStandard = $developmentConfig->getCodingStandard(); + $codingStandard = $developmentModulePath . 'ruleset.xml'; - if ($options['level'] === 2) { + if ($level === $this->tester->getDefaultPriority()) { /** @see \Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfiguration::getCodingStandard() */ - $codingStandard = APPLICATION_VENDOR_DIR . DIRECTORY_SEPARATOR . 'spryker/code-sniffer/SprykerStrict/ruleset.xml'; + $codingStandard = $developmentModulePath . 'rulesetStrict.xml'; } $codeStyleSnifferMock = $this ->getMockBuilder(CodeStyleSniffer::class) ->setConstructorArgs([ $developmentConfig, - $this->tester->createCodeStyleSnifferConfigurationLoader(), + $this->tester->createCodeStylePathResolver(), ]) - ->setMethods(['runSnifferCommand']) + ->onlyMethods(['runSnifferCommand']) ->getMock(); $codeStyleSnifferMock ->method('runSnifferCommand') ->with( - $expectedPathToRunCommandWith, - $this->callback(function ($subject) use ($codingStandard) { - return is_callable([$subject, 'getCodingStandard']) && $subject->getCodingStandard() === $codingStandard; - }) + $this->buildPathWithProperRootDir($developmentModulePath), + $this->callback(function ($subject) use ($codingStandard, $developmentModulePath) { + return is_callable([$subject, 'getCodingStandard']) && + $subject->getCodingStandard($this->buildPathWithProperVendorDir($developmentModulePath)) === $codingStandard; + }), ); return $codeStyleSnifferMock; } + + /** + * @return array + */ + protected function getResolvedPathsForAllSprykerModules(): array + { + $module = 'Spryker.all'; + $options = [ + 'ignore' => 'vendor/', + 'module' => $module, + ] + $this->defaultOptions; + + $reflectedResolvePathsMethod = new ReflectionMethod(CodeStylePathResolver::class, 'resolvePaths'); + $paths = $reflectedResolvePathsMethod->invokeArgs( + $this->tester->createCodeStylePathResolver(), + ['all', 'Spryker', null, $options], + ); + + return $paths; + } + + /** + * @param \Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationInterface $developmentCsConfiguration + * + * @return int + */ + protected function getDevelopmentCsLevel(CodeStyleSnifferConfigurationInterface $developmentCsConfiguration): int + { + $reflectedObject = new ReflectionObject($developmentCsConfiguration); + $reflectedModuleConfigProperty = $reflectedObject->getProperty('moduleConfig'); + $reflectedModuleConfigProperty->setAccessible(true); + $moduleConfig = $reflectedModuleConfigProperty->getValue($developmentCsConfiguration); + + return $moduleConfig['level'] ?? $this->tester->getDefaultLevel(); + } + + /** + * @param string $modulePath + * + * @return string + */ + protected function buildPathWithProperRootDir(string $modulePath): string + { + return str_replace(APPLICATION_ROOT_DIR, APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR, $modulePath); + } + + /** + * @param string $modulePath + * + * @return string + */ + protected function buildPathWithProperVendorDir(string $modulePath): string + { + return str_replace(APPLICATION_VENDOR_DIR, APPLICATION_VENDOR_DIR . DIRECTORY_SEPARATOR, $modulePath); + } + + /** + * @param string $modulePath + * + * @return string + */ + protected function normalizePathToModule(string $modulePath): string + { + return str_replace(APPLICATION_ROOT_DIR . DIRECTORY_SEPARATOR, APPLICATION_ROOT_DIR, $modulePath); + } } diff --git a/tests/SprykerTest/Zed/Development/Business/Codeception/Argument/CodeceptionArgumentsTest.php b/tests/SprykerTest/Zed/Development/Business/Codeception/Argument/CodeceptionArgumentsTest.php new file mode 100644 index 00000000..e0162cc1 --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Business/Codeception/Argument/CodeceptionArgumentsTest.php @@ -0,0 +1,55 @@ + $argumentValues + * @param array $result + * + * @return void + */ + public function testAddArgument(string $argumentName, array $argumentValues, array $result): void + { + $codeceptionArgument = new CodeceptionArguments(); + + $codeceptionArgument->addArgument($argumentName, $argumentValues); + $this->assertSame($result, $codeceptionArgument->getArguments()); + } + + /** + * @return array + */ + public function argumentsDataProvider(): array + { + return [ + 'without value' => ['group', [], ['group']], + 'with value' => ['group', [1], ['group', 1]], + 'multiple value' => ['group', [1, 2, 3], ['group', 1, 'group', 2, 'group', 3]], + ]; + } +} diff --git a/tests/SprykerTest/Zed/Development/Business/Composer/Updater/AutoloadUpdaterTest.php b/tests/SprykerTest/Zed/Development/Business/Composer/Updater/AutoloadUpdaterTest.php index 971c54a8..bb9a2017 100644 --- a/tests/SprykerTest/Zed/Development/Business/Composer/Updater/AutoloadUpdaterTest.php +++ b/tests/SprykerTest/Zed/Development/Business/Composer/Updater/AutoloadUpdaterTest.php @@ -13,6 +13,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -27,7 +28,7 @@ class AutoloadUpdaterTest extends Unit /** * @return void */ - public function testWhenTestsFolderExistsDefaultAutoloadDevIsAddedToComposer() + public function testWhenTestsFolderExistsDefaultAutoloadDevIsAddedToComposer(): void { $updatedJson = $this->updateJsonForTests($this->getComposerJson()); $this->assertSame($this->getComposerJson()['autoload-dev'], $updatedJson['autoload-dev']); @@ -40,14 +41,14 @@ public function testWhenTestsFolderExistsDefaultAutoloadDevIsAddedToComposer() * * @return void */ - public function testWhenDeprecatedDirExistsAutoloadDevAddedToComposer($autoloadKey) + public function testWhenDeprecatedDirExistsAutoloadDevAddedToComposer(string $autoloadKey): void { $updatedJson = $this->getJsonAfterUpdate( [ AutoloadUpdater::BASE_TESTS_DIRECTORY, $autoloadKey, ], - $this->getComposerJson($autoloadKey) + $this->getComposerJson($autoloadKey), ); $this->assertSame($this->getComposerJson($autoloadKey)['autoload-dev'], $updatedJson['autoload-dev']); } @@ -55,7 +56,7 @@ public function testWhenDeprecatedDirExistsAutoloadDevAddedToComposer($autoloadK /** * @return void */ - public function testWhenTestFolderDoesNotExistNothingAddedToComposer() + public function testWhenTestFolderDoesNotExistNothingAddedToComposer(): void { $splFileInfo = $this->getSplFile(); $composerJson = $this->getComposerJson(); @@ -70,7 +71,7 @@ public function testWhenTestFolderDoesNotExistNothingAddedToComposer() /** * @return void */ - public function testWhenAutoloadDevNamespaceIsInvalidGetsRemoved() + public function testWhenAutoloadDevNamespaceIsInvalidGetsRemoved(): void { $composerJson = $this->getComposerJson(); $composerJson['autoload-dev']['psr-4']['invalidNamespace'] = 'validDirectory/'; @@ -83,7 +84,7 @@ public function testWhenAutoloadDevNamespaceIsInvalidGetsRemoved() /** * @return void */ - public function testWhenAutoloadPathIsInvalidGetsRemoved() + public function testWhenAutoloadPathIsInvalidGetsRemoved(): void { $composerJson = $this->getComposerJson(); $composerJson['autoload']['psr-4']['validNamespace'] = 'invalidDirectory/'; @@ -96,7 +97,7 @@ public function testWhenAutoloadPathIsInvalidGetsRemoved() /** * @return void */ - public function testWhenSupportFolderExistsWithHelpersItGetsAddedToAutoload() + public function testWhenSupportFolderExistsWithHelpersItGetsAddedToAutoload(): void { $pathParts = [ AutoloadUpdater::BASE_SRC_DIRECTORY, @@ -111,9 +112,9 @@ public function testWhenSupportFolderExistsWithHelpersItGetsAddedToAutoload() [ [ $pathParts, - implode($pathParts, DIRECTORY_SEPARATOR) . '/', + implode(DIRECTORY_SEPARATOR, $pathParts) . '/', ], - ] + ], ); $this->assertSame($this->getComposerJson()['autoload'], $updatedJson['autoload']); @@ -124,7 +125,7 @@ public function testWhenSupportFolderExistsWithHelpersItGetsAddedToAutoload() * * @return array */ - protected function updateJsonForTests(array $composerJson) + protected function updateJsonForTests(array $composerJson): array { $pathParts = [ AutoloadUpdater::BASE_TESTS_DIRECTORY, @@ -140,9 +141,9 @@ protected function updateJsonForTests(array $composerJson) [ [ $pathParts, - implode($pathParts, DIRECTORY_SEPARATOR) . '/', + implode(DIRECTORY_SEPARATOR, $pathParts) . '/', ], - ] + ], ); } @@ -153,7 +154,7 @@ protected function updateJsonForTests(array $composerJson) * * @return array */ - protected function getJsonAfterUpdate(array $pathParts, array $composerJson, array $dirMapAdditions = []) + protected function getJsonAfterUpdate(array $pathParts, array $composerJson, array $dirMapAdditions = []): array { $splFileInfo = $this->getSplFile(); @@ -168,7 +169,7 @@ protected function getJsonAfterUpdate(array $pathParts, array $composerJson, arr ], ]; - if (!empty($dirMapAdditions)) { + if ($dirMapAdditions) { $dirMap = array_merge($dirMap, $dirMapAdditions); } @@ -182,7 +183,7 @@ protected function getJsonAfterUpdate(array $pathParts, array $composerJson, arr /** * @return array */ - public function autoloadKeys() + public function autoloadKeys(): array { return [ ['Acceptance'], @@ -195,10 +196,10 @@ public function autoloadKeys() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\Composer\Updater\AutoloadUpdater */ - protected function getAutoloadUpdaterMock() + protected function getAutoloadUpdaterMock(): AutoloadUpdater { $autoloadUpdaterMock = $this->getMockBuilder(AutoloadUpdater::class) - ->setMethods(['pathExists', 'getPath']) + ->onlyMethods(['pathExists', 'getPath']) ->getMock(); return $autoloadUpdaterMock; @@ -209,7 +210,7 @@ protected function getAutoloadUpdaterMock() * * @return array */ - protected function getComposerJson($autoloadKey = '') + protected function getComposerJson(string $autoloadKey = ''): array { $composerArray = [ 'autoload' => [ @@ -224,7 +225,7 @@ protected function getComposerJson($autoloadKey = '') ], ]; - if (!empty($autoloadKey)) { + if ($autoloadKey) { $composerArray['autoload-dev']['psr-0'] = [$autoloadKey => 'tests/']; unset($composerArray['autoload-dev']['psr-4']); } @@ -235,7 +236,7 @@ protected function getComposerJson($autoloadKey = '') /** * @return \Symfony\Component\Finder\SplFileInfo */ - protected function getSplFile() + protected function getSplFile(): SplFileInfo { return new SplFileInfo(__FILE__, __DIR__, __DIR__); } diff --git a/tests/SprykerTest/Zed/Development/Business/Composer/Updater/TypeUpdaterTest.php b/tests/SprykerTest/Zed/Development/Business/Composer/Updater/TypeUpdaterTest.php index 29f8138c..b73007fb 100644 --- a/tests/SprykerTest/Zed/Development/Business/Composer/Updater/TypeUpdaterTest.php +++ b/tests/SprykerTest/Zed/Development/Business/Composer/Updater/TypeUpdaterTest.php @@ -13,6 +13,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -27,7 +28,7 @@ class TypeUpdaterTest extends Unit /** * @return void */ - public function testSetsTypeToPropelBehaviorWhenPackageNameContainsBehavior() + public function testSetsTypeToPropelBehaviorWhenPackageNameContainsBehavior(): void { $typeUpdater = new TypeUpdater(); $updatedJson = $typeUpdater->update($this->getComposerJson('foo-behavior'), $this->getSplFile()); @@ -38,7 +39,7 @@ public function testSetsTypeToPropelBehaviorWhenPackageNameContainsBehavior() /** * @return void */ - public function testSetsTypeToLibraryBehaviorWhenPackageNameNotContainsBehavior() + public function testSetsTypeToLibraryBehaviorWhenPackageNameNotContainsBehavior(): void { $typeUpdater = new TypeUpdater(); $updatedJson = $typeUpdater->update($this->getComposerJson('foo'), $this->getSplFile()); @@ -64,7 +65,7 @@ protected function getComposerJson(string $packageName): array /** * @return \Symfony\Component\Finder\SplFileInfo */ - protected function getSplFile() + protected function getSplFile(): SplFileInfo { return new SplFileInfo(__FILE__, __DIR__, __DIR__); } diff --git a/tests/SprykerTest/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParserTest.php b/tests/SprykerTest/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParserTest.php new file mode 100644 index 00000000..7042de3b --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Business/Dependency/SchemaParser/PropelSchemaParserTest.php @@ -0,0 +1,151 @@ +getPropelSchemaParser(); + $fileInfo = new SplFileInfo(Configuration::dataDir() . 'SchemaWithDependencies/test.schema.xml', '', ''); + $expectedResult = [ + 0 => 'spy_zip_zap.id_zip_zap', + 1 => 'spy_qux_quux.id_qux_quux', + ]; + + // Act + $foreignColumnNames = $propelSchemaParser->getForeignColumnNames($fileInfo); + + // Assert + $this->assertEquals($expectedResult, $foreignColumnNames); + } + + /** + * @return void + */ + public function testGetForeignColumnNamesForStaleSchemaReturnsForeignReferenceColumnNames(): void + { + // Arrange + $propelSchemaParser = $this->getPropelSchemaParser(); + $fileInfo = new SplFileInfo(Configuration::dataDir() . 'StaleSchemaWithDependencies/test.schema.xml', '', ''); + $expectedResult = [ + 0 => 'spy_zip_zap.id_zip_zap', + 1 => 'spy_qux_quux.id_qux_quux', + ]; + + // Act + $foreignColumnNames = $propelSchemaParser->getForeignColumnNames($fileInfo); + + // Assert + $this->assertEquals($expectedResult, $foreignColumnNames); + } + + /** + * @return void + */ + public function testGetModuleNameByForeignReferenceReturnsAllDependentModulesBothStaleAnsNamespacedOnes(): void + { + // Arrange + $propelSchemaParser = $this->getPropelSchemaParser(); + $foreignIdColumnNames = [ + 0 => 'spy_zip_zap.id_zip_zap', + 1 => 'spy_qux_quux.id_qux_quux', + ]; + $expectedResult = [ + 0 => 'ZipZap', + 1 => 'QuxQuux', + ]; + + $dependentModules = []; + + // Act + foreach ($foreignIdColumnNames as $foreignIdColumnName) { + $dependentModules[] = $propelSchemaParser->getModuleNameByForeignReference($foreignIdColumnName, 'FooBar'); + } + + // Assert + $this->assertEquals($expectedResult, $dependentModules); + } + + /** + * @return void + */ + public function testGetModuleNameByForeignReferenceForUnexistingReferencesThrowsPropelSchemaParserException(): void + { + // Arrange + $propelSchemaParser = $this->getPropelSchemaParser(); + $foreignIdColumnNames = [ + 0 => 'spy_zip_zap.id_zip_zap', + 1 => 'spy_baz_xyzzy.id_baz_xyzzy', + ]; + + // Assert + $this->expectException(PropelSchemaParserException::class); + + // Act + foreach ($foreignIdColumnNames as $foreignIdColumnName) { + $propelSchemaParser->getModuleNameByForeignReference($foreignIdColumnName, 'FooBar'); + } + } + + /** + * @return \Spryker\Zed\Development\Business\Dependency\SchemaParser\PropelSchemaParser + */ + protected function getPropelSchemaParser(): PropelSchemaParser + { + /** @var \Spryker\Zed\Development\DevelopmentConfig $developmentConfigMock */ + $developmentConfigMock = Stub::make(DevelopmentConfig::class, [ + 'getOrganizationPathMap' => function () { + return [ + 'Spryker' => Configuration::dataDir() . static::GENERATED_SCHEMA_FILES . DIRECTORY_SEPARATOR, + ]; + }, + ]); + + return new PropelSchemaParser($developmentConfigMock); + } +} diff --git a/tests/SprykerTest/Zed/Development/Business/Dependency/Validator/DependencyValidatorTest.php b/tests/SprykerTest/Zed/Development/Business/Dependency/Validator/DependencyValidatorTest.php index ea15dec4..ae88ca06 100644 --- a/tests/SprykerTest/Zed/Development/Business/Dependency/Validator/DependencyValidatorTest.php +++ b/tests/SprykerTest/Zed/Development/Business/Dependency/Validator/DependencyValidatorTest.php @@ -11,6 +11,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -30,7 +31,7 @@ class DependencyValidatorTest extends Unit /** * @return void */ - public function testDependencyIsValidWhenDependencyTypeIsDevOnly() + public function testDependencyIsValidWhenDependencyTypeIsDevOnly(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getDevOnlyComposerDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -41,7 +42,7 @@ public function testDependencyIsValidWhenDependencyTypeIsDevOnly() /** * @return void */ - public function testDependencyIsInvalidWhenDependencyInSourceButMissingInComposerRequire() + public function testDependencyIsInvalidWhenDependencyInSourceButMissingInComposerRequire(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidSourceDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -52,7 +53,7 @@ public function testDependencyIsInvalidWhenDependencyInSourceButMissingInCompose /** * @return void */ - public function testDependencyIsInvalidWhenDependencyNotInSourceButInComposerRequire() + public function testDependencyIsInvalidWhenDependencyNotInSourceButInComposerRequire(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidRequireDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -63,7 +64,7 @@ public function testDependencyIsInvalidWhenDependencyNotInSourceButInComposerReq /** * @return void */ - public function testDependencyIsValidWhenDependencyInSourceAndInComposerRequire() + public function testDependencyIsValidWhenDependencyInSourceAndInComposerRequire(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getValidSourceDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -74,7 +75,7 @@ public function testDependencyIsValidWhenDependencyInSourceAndInComposerRequire( /** * @return void */ - public function testDependencyIsInvalidWhenDependencyInTestButMissingInComposerRequireDev() + public function testDependencyIsInvalidWhenDependencyInTestButMissingInComposerRequireDev(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidTestDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -85,7 +86,7 @@ public function testDependencyIsInvalidWhenDependencyInTestButMissingInComposerR /** * @return void */ - public function testDependencyIsInvalidWhenDependencyNotInTestButInComposerRequireDev() + public function testDependencyIsInvalidWhenDependencyNotInTestButInComposerRequireDev(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidRequireDevDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -96,7 +97,7 @@ public function testDependencyIsInvalidWhenDependencyNotInTestButInComposerRequi /** * @return void */ - public function testDependencyIsValidWhenDependencyInTestAndInComposerRequireDev() + public function testDependencyIsValidWhenDependencyInTestAndInComposerRequireDev(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidTestDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -107,7 +108,7 @@ public function testDependencyIsValidWhenDependencyInTestAndInComposerRequireDev /** * @return void */ - public function testDependencyIsValidWhenDependencyIsOptionalAndNotInRequire() + public function testDependencyIsValidWhenDependencyIsOptionalAndNotInRequire(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getValidOptionalRequiredDevDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -118,7 +119,7 @@ public function testDependencyIsValidWhenDependencyIsOptionalAndNotInRequire() /** * @return void */ - public function testDependencyIsInvalidWhenDependencyIsOptionalButInRequire() + public function testDependencyIsInvalidWhenDependencyIsOptionalButInRequire(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidOptionalRequiredDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -129,7 +130,7 @@ public function testDependencyIsInvalidWhenDependencyIsOptionalButInRequire() /** * @return void */ - public function testDependencyIsInvalidWhenDependencyIsOptionalButNotInRequireDev() + public function testDependencyIsInvalidWhenDependencyIsOptionalButNotInRequireDev(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidOptionalNotRequiredDevDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -140,7 +141,7 @@ public function testDependencyIsInvalidWhenDependencyIsOptionalButNotInRequireDe /** * @return void */ - public function testDependencyIsInvalidWhenDependencyIsOptionalButNotSuggested() + public function testDependencyIsInvalidWhenDependencyIsOptionalButNotSuggested(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidOptionalNotSuggestedDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); @@ -151,7 +152,7 @@ public function testDependencyIsInvalidWhenDependencyIsOptionalButNotSuggested() /** * @return void */ - public function testDependencyIsInvalidWhenDependencyInRequireAndInRequireDev() + public function testDependencyIsInvalidWhenDependencyInRequireAndInRequireDev(): void { $developmentFacade = $this->tester->getFacadeForDependencyTests($this->tester->getInvalidRequireAndRequireDevDependency()); $dependencyValidationResponseTransfer = $developmentFacade->validateModuleDependencies($this->tester->getDependencyValidationRequestTransfer()); diff --git a/tests/SprykerTest/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependencyTest.php b/tests/SprykerTest/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependencyTest.php index 5735006c..58a75437 100644 --- a/tests/SprykerTest/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependencyTest.php +++ b/tests/SprykerTest/Zed/Development/Business/DependencyTree/DependencyFinder/ExternalDependencyTest.php @@ -14,9 +14,11 @@ use Spryker\Zed\Development\Business\DependencyTree\FileInfoExtractor; use Spryker\Zed\Development\DevelopmentConfig; use Symfony\Component\Finder\Finder; +use Symfony\Component\Finder\SplFileInfo; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -33,7 +35,7 @@ class ExternalDependencyTest extends Unit * * @return \Symfony\Component\Finder\SplFileInfo */ - public function getTestFile() + public function getTestFile(): SplFileInfo { $finder = new Finder(); $finder->files()->in(__DIR__ . '/test_files'); @@ -48,7 +50,7 @@ public function getTestFile() /** * @return void */ - public function testAddDependency() + public function testAddDependency(): void { $developmentConfig = new DevelopmentConfig(); $testFile = $this->getTestFile(); diff --git a/tests/SprykerTest/Zed/Development/Business/DevelopmentFacadeTest.php b/tests/SprykerTest/Zed/Development/Business/DevelopmentFacadeTest.php index d67ec783..b5276036 100644 --- a/tests/SprykerTest/Zed/Development/Business/DevelopmentFacadeTest.php +++ b/tests/SprykerTest/Zed/Development/Business/DevelopmentFacadeTest.php @@ -15,6 +15,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development diff --git a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilderTest.php b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilderTest.php index 2096ef51..ff3be150 100644 --- a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilderTest.php +++ b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ClientMethodBuilderTest.php @@ -11,10 +11,12 @@ use Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\ClientMethodBuilder; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractor; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface; use Symfony\Component\Finder\SplFileInfo; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -27,19 +29,26 @@ */ class ClientMethodBuilderTest extends Unit { + /** + * @var string + */ public const BASE_DIRECTORY = '/foo/bar/baz/*/src/'; + + /** + * @var string + */ public const BUNDLE_DIRECTORY = '/foo/bar/baz/FooBundle/src/Spryker/Client/'; /** * @return void */ - public function testMethodNameIsClient() + public function testMethodNameIsClient(): void { $methodBuilderMock = $this->getClientMethodBuilderMock(); $methodBuilderMock ->expects($this->any()) ->method('findFileByName') - ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/FooBundleClientInterface.php', null, null)); + ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/FooBundleClientInterface.php', 'foo', 'bar')); $bundleMethodTransfer = $methodBuilderMock->getMethod($this->getBundleTransfer()); @@ -49,7 +58,7 @@ public function testMethodNameIsClient() /** * @return void */ - public function testFileLookupIsPerformedInClientApplication() + public function testFileLookupIsPerformedInClientApplication(): void { $methodBuilderMock = $this->getClientMethodBuilderMock(); $methodBuilderMock @@ -63,12 +72,12 @@ public function testFileLookupIsPerformedInClientApplication() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\ClientMethodBuilder */ - protected function getClientMethodBuilderMock() + protected function getClientMethodBuilderMock(): ClientMethodBuilder { $methodBuilderMock = $this ->getMockBuilder(ClientMethodBuilder::class) ->setConstructorArgs([$this->getNamespaceExtractorMock()]) - ->setMethods(['findFileByName', 'isSearchDirectoryAccessible']) + ->onlyMethods(['findFileByName', 'isSearchDirectoryAccessible']) ->getMock(); $methodBuilderMock @@ -82,7 +91,7 @@ protected function getClientMethodBuilderMock() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface */ - protected function getNamespaceExtractorMock() + protected function getNamespaceExtractorMock(): NamespaceExtractorInterface { return $this ->getMockBuilder(NamespaceExtractor::class) @@ -92,7 +101,7 @@ protected function getNamespaceExtractorMock() /** * @return \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer */ - protected function getBundleTransfer() + protected function getBundleTransfer(): IdeAutoCompletionBundleTransfer { $bundleTransfer = new IdeAutoCompletionBundleTransfer(); $bundleTransfer->setName('FooBundle'); diff --git a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilderTest.php b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilderTest.php index d93200b8..23e81683 100644 --- a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilderTest.php +++ b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/FacadeMethodBuilderTest.php @@ -11,10 +11,12 @@ use Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\FacadeMethodBuilder; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractor; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface; use Symfony\Component\Finder\SplFileInfo; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -28,19 +30,26 @@ */ class FacadeMethodBuilderTest extends Unit { + /** + * @var string + */ public const BASE_DIRECTORY = '/foo/bar/baz/*/src/'; + + /** + * @var string + */ public const BUNDLE_DIRECTORY = '/foo/bar/baz/FooBundle/src/Spryker/FooApplication/'; /** * @return void */ - public function testMethodNameIsFacade() + public function testMethodNameIsFacade(): void { $methodBuilderMock = $this->getFacadeMethodBuilderMock(); $methodBuilderMock ->expects($this->any()) ->method('findFileByName') - ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacadeInterface.php', null, null)); + ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacadeInterface.php', 'foo', 'bar')); $bundleMethodTransfer = $methodBuilderMock->getMethod($this->getBundleTransfer()); @@ -50,7 +59,7 @@ public function testMethodNameIsFacade() /** * @return void */ - public function testFileLookupIsPerformedInBusinessLayer() + public function testFileLookupIsPerformedInBusinessLayer(): void { $methodBuilderMock = $this->getFacadeMethodBuilderMock(); $methodBuilderMock @@ -64,19 +73,16 @@ public function testFileLookupIsPerformedInBusinessLayer() /** * @return void */ - public function testFileLookupPrefersInterface() + public function testFileLookupPrefersInterface(): void { $methodBuilderMock = $this->getFacadeMethodBuilderMock(); $methodBuilderMock ->expects($this->exactly(1)) ->method('findFileByName') - ->withConsecutive( - [$this->equalTo('FooBundleFacadeInterface.php'), $this->anything()] - ) - ->will($this->onConsecutiveCalls( - new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacadeInterface.php', null, null), - new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacade.php', null, null) - )); + ->willReturnOnConsecutiveCalls( + new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacadeInterface.php', 'foo', 'bar'), + new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacade.php', 'foo', 'bar'), + ); $bundleMethodTransfer = $methodBuilderMock->getMethod($this->getBundleTransfer()); @@ -86,20 +92,16 @@ public function testFileLookupPrefersInterface() /** * @return void */ - public function testFileLookupFallsBackToConcreteClassIfInterfaceIsMissing() + public function testFileLookupFallsBackToConcreteClassIfInterfaceIsMissing(): void { $methodBuilderMock = $this->getFacadeMethodBuilderMock(); $methodBuilderMock ->expects($this->exactly(2)) ->method('findFileByName') - ->withConsecutive( - [$this->equalTo('FooBundleFacadeInterface.php'), $this->anything()], - [$this->equalTo('FooBundleFacade.php'), $this->anything()] - ) - ->will($this->onConsecutiveCalls( - null, - new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacade.php', null, null) - )); + ->willReturnOnConsecutiveCalls( + null, // First call returns null (interface missing) + new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Business/FooBundleFacade.php', 'foo', 'bar'), // Second call returns concrete class file + ); $bundleMethodTransfer = $methodBuilderMock->getMethod($this->getBundleTransfer()); @@ -107,14 +109,14 @@ public function testFileLookupFallsBackToConcreteClassIfInterfaceIsMissing() } /** - * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\ClientMethodBuilder + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\FacadeMethodBuilder|\PHPUnit\Framework\MockObject\MockObject */ - protected function getFacadeMethodBuilderMock() + protected function getFacadeMethodBuilderMock(): FacadeMethodBuilder { $methodBuilderMock = $this ->getMockBuilder(FacadeMethodBuilder::class) ->setConstructorArgs([$this->getNamespaceExtractorMock()]) - ->setMethods(['findFileByName', 'isSearchDirectoryAccessible']) + ->onlyMethods(['findFileByName', 'isSearchDirectoryAccessible']) ->getMock(); $methodBuilderMock @@ -128,7 +130,7 @@ protected function getFacadeMethodBuilderMock() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface */ - protected function getNamespaceExtractorMock() + protected function getNamespaceExtractorMock(): NamespaceExtractorInterface { return $this ->getMockBuilder(NamespaceExtractor::class) @@ -138,7 +140,7 @@ protected function getNamespaceExtractorMock() /** * @return \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer */ - protected function getBundleTransfer() + protected function getBundleTransfer(): IdeAutoCompletionBundleTransfer { $bundleTransfer = new IdeAutoCompletionBundleTransfer(); $bundleTransfer->setName('FooBundle'); diff --git a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilderTest.php b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilderTest.php index 97493e62..7e717622 100644 --- a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilderTest.php +++ b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/QueryContainerMethodBuilderTest.php @@ -11,10 +11,12 @@ use Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\QueryContainerMethodBuilder; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractor; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface; use Symfony\Component\Finder\SplFileInfo; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -27,19 +29,26 @@ */ class QueryContainerMethodBuilderTest extends Unit { + /** + * @var string + */ public const BASE_DIRECTORY = '/foo/bar/baz/*/src/'; + + /** + * @var string + */ public const BUNDLE_DIRECTORY = '/foo/bar/baz/FooBundle/src/Spryker/FooApplication/'; /** * @return void */ - public function testMethodNameIsQueryConntainer() + public function testMethodNameIsQueryConntainer(): void { $methodBuilderMock = $this->getQueryContainerMethodBuilderMock(); $methodBuilderMock ->expects($this->any()) ->method('findFileByName') - ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Persistence/FooBundleQueryContainerInterface.php', null, null)); + ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/Persistence/FooBundleQueryContainerInterface.php', 'foo', 'bar')); $bundleMethodTransfer = $methodBuilderMock->getMethod($this->getBundleTransfer()); @@ -49,7 +58,7 @@ public function testMethodNameIsQueryConntainer() /** * @return void */ - public function testFileLookupIsPerformedInPersistenceLayer() + public function testFileLookupIsPerformedInPersistenceLayer(): void { $methodBuilderMock = $this->getQueryContainerMethodBuilderMock(); $methodBuilderMock @@ -61,14 +70,14 @@ public function testFileLookupIsPerformedInPersistenceLayer() } /** - * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\ClientMethodBuilder + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\QueryContainerMethodBuilder|\PHPUnit\Framework\MockObject\MockObject */ - protected function getQueryContainerMethodBuilderMock() + protected function getQueryContainerMethodBuilderMock(): QueryContainerMethodBuilder { $methodBuilderMock = $this ->getMockBuilder(QueryContainerMethodBuilder::class) ->setConstructorArgs([$this->getNamespaceExtractorMock()]) - ->setMethods(['findFileByName', 'isSearchDirectoryAccessible']) + ->onlyMethods(['findFileByName', 'isSearchDirectoryAccessible']) ->getMock(); $methodBuilderMock @@ -82,7 +91,7 @@ protected function getQueryContainerMethodBuilderMock() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface */ - protected function getNamespaceExtractorMock() + protected function getNamespaceExtractorMock(): NamespaceExtractorInterface { return $this ->getMockBuilder(NamespaceExtractor::class) @@ -92,7 +101,7 @@ protected function getNamespaceExtractorMock() /** * @return \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer */ - protected function getBundleTransfer() + protected function getBundleTransfer(): IdeAutoCompletionBundleTransfer { $bundleTransfer = new IdeAutoCompletionBundleTransfer(); $bundleTransfer->setName('FooBundle'); diff --git a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilderTest.php b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilderTest.php index c3ad545a..c92fbd6e 100644 --- a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilderTest.php +++ b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/MethodBuilder/ServiceMethodBuilderTest.php @@ -11,10 +11,12 @@ use Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\ServiceMethodBuilder; use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractor; +use Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface; use Symfony\Component\Finder\SplFileInfo; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -27,19 +29,26 @@ */ class ServiceMethodBuilderTest extends Unit { + /** + * @var string + */ public const BASE_DIRECTORY = '/foo/bar/baz/*/src/'; + + /** + * @var string + */ public const BUNDLE_DIRECTORY = '/foo/bar/baz/FooBundle/src/Spryker/Service/'; /** * @return void */ - public function testMethodNameIsClient() + public function testMethodNameIsClient(): void { $methodBuilderMock = $this->getServiceMethodBuilderMock(); $methodBuilderMock ->expects($this->any()) ->method('findFileByName') - ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/FooBundleServiceInterface.php', null, null)); + ->willReturn(new SplFileInfo(static::BUNDLE_DIRECTORY . 'FooBundle/FooBundleServiceInterface.php', 'foo', 'bar')); $bundleMethodTransfer = $methodBuilderMock->getMethod($this->getBundleTransfer()); @@ -49,7 +58,7 @@ public function testMethodNameIsClient() /** * @return void */ - public function testFileLookupIsPerformedInClientApplication() + public function testFileLookupIsPerformedInClientApplication(): void { $methodBuilderMock = $this->getServiceMethodBuilderMock(); $methodBuilderMock @@ -61,14 +70,14 @@ public function testFileLookupIsPerformedInClientApplication() } /** - * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\ClientMethodBuilder + * @return \Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\MethodBuilder\ServiceMethodBuilder|\PHPUnit\Framework\MockObject\MockObject */ - protected function getServiceMethodBuilderMock() + protected function getServiceMethodBuilderMock(): ServiceMethodBuilder { $methodBuilderMock = $this ->getMockBuilder(ServiceMethodBuilder::class) ->setConstructorArgs([$this->getNamespaceExtractorMock()]) - ->setMethods(['findFileByName', 'isSearchDirectoryAccessible']) + ->onlyMethods(['findFileByName', 'isSearchDirectoryAccessible']) ->getMock(); $methodBuilderMock @@ -82,7 +91,7 @@ protected function getServiceMethodBuilderMock() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\IdeAutoCompletion\Bundle\NamespaceExtractorInterface */ - protected function getNamespaceExtractorMock() + protected function getNamespaceExtractorMock(): NamespaceExtractorInterface { return $this ->getMockBuilder(NamespaceExtractor::class) @@ -92,7 +101,7 @@ protected function getNamespaceExtractorMock() /** * @return \Generated\Shared\Transfer\IdeAutoCompletionBundleTransfer */ - protected function getBundleTransfer() + protected function getBundleTransfer(): IdeAutoCompletionBundleTransfer { $bundleTransfer = new IdeAutoCompletionBundleTransfer(); $bundleTransfer->setName('FooBundle'); diff --git a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/NamespaceExtractorTest.php b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/NamespaceExtractorTest.php index 5c0e9e4d..70e563a9 100644 --- a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/NamespaceExtractorTest.php +++ b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Bundle/NamespaceExtractorTest.php @@ -13,6 +13,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -27,10 +28,10 @@ class NamespaceExtractorTest extends Unit /** * @return void */ - public function testReplacementOfRegularBaseDirectory() + public function testReplacementOfRegularBaseDirectory(): void { $baseDirectory = '/foo/bar/baz/Bundle/src/'; - $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', null, null); + $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', 'foo', 'bar'); $namespaceExtractor = new NamespaceExtractor(); $namespace = $namespaceExtractor->fromDirectory($directory, $baseDirectory); @@ -40,10 +41,10 @@ public function testReplacementOfRegularBaseDirectory() /** * @return void */ - public function testReplacementOfAsteriskGlobPatternBaseDirectory() + public function testReplacementOfAsteriskGlobPatternBaseDirectory(): void { $baseDirectory = '/foo/bar/baz/*/src/'; - $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', null, null); + $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', 'foo', 'bar'); $namespaceExtractor = new NamespaceExtractor(); $namespace = $namespaceExtractor->fromDirectory($directory, $baseDirectory); @@ -53,10 +54,10 @@ public function testReplacementOfAsteriskGlobPatternBaseDirectory() /** * @return void */ - public function testReplacementOfQuestionMarkGlobPatternBaseDirectory() + public function testReplacementOfQuestionMarkGlobPatternBaseDirectory(): void { $baseDirectory = '/foo/bar/?az/Bundle/src/'; - $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', null, null); + $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', 'foo', 'bar'); $namespaceExtractor = new NamespaceExtractor(); $namespace = $namespaceExtractor->fromDirectory($directory, $baseDirectory); @@ -66,16 +67,16 @@ public function testReplacementOfQuestionMarkGlobPatternBaseDirectory() /** * @return void */ - public function testReplacementOfBraceGlobPatternBaseDirectory() + public function testReplacementOfBraceGlobPatternBaseDirectory(): void { $baseDirectory = '/foo/bar/{baz,spryker}/Bundle/src/'; $namespaceExtractor = new NamespaceExtractor(); - $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', null, null); + $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', 'foo', 'bar'); $namespace = $namespaceExtractor->fromDirectory($directory, $baseDirectory); $this->assertSame('Spryker\Application\Bundle', $namespace); - $directory = new SplFileInfo('/foo/bar/spryker/Bundle/src/Spryker/Application/Bundle', null, null); + $directory = new SplFileInfo('/foo/bar/spryker/Bundle/src/Spryker/Application/Bundle', 'foo', 'bar'); $namespace = $namespaceExtractor->fromDirectory($directory, $baseDirectory); $this->assertSame('Spryker\Application\Bundle', $namespace); } @@ -83,16 +84,16 @@ public function testReplacementOfBraceGlobPatternBaseDirectory() /** * @return void */ - public function testReplacementOfCharacterClassGlobPatternBasePath() + public function testReplacementOfCharacterClassGlobPatternBasePath(): void { $baseDirectory = '/foo/bar/[bf]az/Bundle/src/'; $namespaceExtractor = new NamespaceExtractor(); - $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', null, null); + $directory = new SplFileInfo('/foo/bar/baz/Bundle/src/Spryker/Application/Bundle', 'foo', 'bar'); $namespace = $namespaceExtractor->fromDirectory($directory, $baseDirectory); $this->assertSame('Spryker\Application\Bundle', $namespace); - $directory = new SplFileInfo('/foo/bar/faz/Bundle/src/Spryker/Application/Bundle', null, null); + $directory = new SplFileInfo('/foo/bar/faz/Bundle/src/Spryker/Application/Bundle', 'foo', 'bar'); $namespace = $namespaceExtractor->fromDirectory($directory, $baseDirectory); $this->assertSame('Spryker\Application\Bundle', $namespace); } diff --git a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Generator/BundleGeneratorTest.php b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Generator/BundleGeneratorTest.php index 680c7df7..1ff6e38a 100644 --- a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Generator/BundleGeneratorTest.php +++ b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/Generator/BundleGeneratorTest.php @@ -16,6 +16,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -30,7 +31,7 @@ class BundleGeneratorTest extends Unit /** * @return void */ - public function testTemplateNameIsDerivedFromGeneratorName() + public function testTemplateNameIsDerivedFromGeneratorName(): void { $twigEnvironmentMock = $this->createTwigEnvironmentMock(); $twigEnvironmentMock @@ -46,7 +47,7 @@ public function testTemplateNameIsDerivedFromGeneratorName() /** * @return void */ - public function testNamespacePatternIsFilledWithApplicationName() + public function testNamespacePatternIsFilledWithApplicationName(): void { $twigEnvironmentMock = $this->createTwigEnvironmentMock(); $twigEnvironmentMock @@ -66,7 +67,7 @@ public function testNamespacePatternIsFilledWithApplicationName() /** * @return array */ - protected function getGeneratorOptions() + protected function getGeneratorOptions(): array { return [ IdeAutoCompletionOptionConstants::APPLICATION_NAME => 'FooApplication', @@ -74,7 +75,7 @@ protected function getGeneratorOptions() IdeAutoCompletionOptionConstants::TARGET_DIRECTORY_PATTERN => '/', IdeAutoCompletionOptionConstants::TARGET_NAMESPACE_PATTERN => sprintf( 'Generated\%s\Ide', - IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER + IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, ), ]; } @@ -82,7 +83,7 @@ protected function getGeneratorOptions() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Twig\Environment */ - protected function createTwigEnvironmentMock() + protected function createTwigEnvironmentMock(): Environment { return $this ->getMockBuilder(Environment::class) diff --git a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriterTest.php b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriterTest.php index 9a1760db..08c893da 100644 --- a/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriterTest.php +++ b/tests/SprykerTest/Zed/Development/Business/IdeAutoCompletion/IdeAutoCompletionWriterTest.php @@ -14,11 +14,13 @@ use Spryker\Zed\Development\DevelopmentConfig; use Spryker\Zed\Development\DevelopmentDependencyProvider; use Spryker\Zed\Kernel\Container; +use SprykerTest\Zed\Development\DevelopmentBusinessTester; use SprykerTest\Zed\Development\Helper\IdeAutoCompletion; use Symfony\Component\Finder\Finder; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -37,11 +39,11 @@ class IdeAutoCompletionWriterTest extends Unit /** * @return void */ - public function testWriterCreatesYvesAutoCompletionFiles() + public function testWriterCreatesYvesAutoCompletionFiles(): void { $tester = $this->createFunctionalTester(); - $tester->execute(function () { + $tester->execute(function (): void { $this ->getDevelopmentBusinessFactory() ->createYvesIdeAutoCompletionWriter() @@ -58,11 +60,11 @@ public function testWriterCreatesYvesAutoCompletionFiles() /** * @return void */ - public function testWriterCreatesZedAutoCompletionFiles() + public function testWriterCreatesZedAutoCompletionFiles(): void { $tester = $this->createFunctionalTester(); - $tester->execute(function () { + $tester->execute(function (): void { $this ->getDevelopmentBusinessFactory() ->createZedIdeAutoCompletionWriter() @@ -80,11 +82,11 @@ public function testWriterCreatesZedAutoCompletionFiles() /** * @return void */ - public function testWriterCreatesClientAutoCompletionFiles() + public function testWriterCreatesClientAutoCompletionFiles(): void { $tester = $this->createFunctionalTester(); - $tester->execute(function () { + $tester->execute(function (): void { $this ->getDevelopmentBusinessFactory() ->createClientIdeAutoCompletionWriter() @@ -102,11 +104,11 @@ public function testWriterCreatesClientAutoCompletionFiles() /** * @return void */ - public function testWriterCreatesServiceAutoCompletionFiles() + public function testWriterCreatesServiceAutoCompletionFiles(): void { $tester = $this->createFunctionalTester(); - $tester->execute(function () { + $tester->execute(function (): void { $this ->getDevelopmentBusinessFactory() ->createServiceIdeAutoCompletionWriter() @@ -116,10 +118,44 @@ public function testWriterCreatesServiceAutoCompletionFiles() $tester->canSeeFileFound('AutoCompletion.php', IdeAutoCompletion::TEST_TARGET_DIRECTORY . 'Generated/Service/Ide/'); } + /** + * @return void + */ + public function testWriterCreatesGlueAutoCompletionFiles(): void + { + $tester = $this->createFunctionalTester(); + + $tester->execute(function (): void { + $this + ->getDevelopmentBusinessFactory() + ->createGlueIdeAutoCompletionWriter() + ->writeCompletionFiles(); + }); + + $tester->canSeeFileFound('AutoCompletion.php', IdeAutoCompletion::TEST_TARGET_DIRECTORY . 'Generated/Glue/Ide/'); + } + + /** + * @return void + */ + public function testWriterCreatesGlueBackendAutoCompletionFiles(): void + { + $tester = $this->createFunctionalTester(); + + $tester->execute(function (): void { + $this + ->getDevelopmentBusinessFactory() + ->createGlueBackendIdeAutoCompletionWriter() + ->writeCompletionFiles(); + }); + + $tester->canSeeFileFound('AutoCompletion.php', IdeAutoCompletion::TEST_TARGET_DIRECTORY . 'Generated/GlueBackend/Ide/'); + } + /** * @return \SprykerTest\Zed\Development\DevelopmentBusinessTester */ - protected function createFunctionalTester() + protected function createFunctionalTester(): DevelopmentBusinessTester { return $this->tester; } @@ -127,7 +163,7 @@ protected function createFunctionalTester() /** * @return \Spryker\Zed\Development\Business\DevelopmentBusinessFactory */ - protected function getDevelopmentBusinessFactory() + protected function getDevelopmentBusinessFactory(): DevelopmentBusinessFactory { $container = new Container(); $dependencyProvider = new DevelopmentDependencyProvider(); @@ -144,11 +180,11 @@ protected function getDevelopmentBusinessFactory() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\DevelopmentConfig */ - protected function getDevelopmentConfigMock() + protected function getDevelopmentConfigMock(): DevelopmentConfig { $configMock = $this ->getMockBuilder(DevelopmentConfig::class) - ->setMethods(['getDefaultIdeAutoCompletionOptions']) + ->onlyMethods(['getDefaultIdeAutoCompletionOptions']) ->getMock(); $configMock @@ -157,11 +193,11 @@ protected function getDevelopmentConfigMock() IdeAutoCompletionOptionConstants::TARGET_BASE_DIRECTORY => IdeAutoCompletion::TEST_TARGET_DIRECTORY, IdeAutoCompletionOptionConstants::TARGET_DIRECTORY_PATTERN => sprintf( 'Generated/%s/Ide', - IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER + IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, ), IdeAutoCompletionOptionConstants::TARGET_NAMESPACE_PATTERN => sprintf( 'Generated\%s\Ide', - IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER + IdeAutoCompletionConstants::APPLICATION_NAME_PLACEHOLDER, ), IdeAutoCompletionConstants::DIRECTORY_PERMISSION => 0777, ]); diff --git a/tests/SprykerTest/Zed/Development/Business/Normalizer/NameNormalizerTest.php b/tests/SprykerTest/Zed/Development/Business/Normalizer/NameNormalizerTest.php new file mode 100644 index 00000000..d70b2df7 --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Business/Normalizer/NameNormalizerTest.php @@ -0,0 +1,96 @@ +> + */ + public function dasherizeDataProvider() + { + return [ + ['TestName', 'test-name'], + ['testName', 'test-name'], + ['TestNameWithMultipleCAPS', 'test-name-with-multiple-caps'], + ['', ''], + ]; + } + + /** + * @return array> + */ + public function camelizeDataProvider() + { + return [ + ['test-name', 'TestName'], + ['test_name', 'TestName'], + ['test-name_with_mixed', 'TestNameWithMixed'], + ['', ''], + ]; + } + + /** + * @dataProvider dasherizeDataProvider + * + * @param string $input + * @param string $expected + * + * @return void + */ + public function shouldDasherizeCamelCaseToDash($input, $expected): void + { + // Arrange + $nameNormalizer = new NameNormalizer(); + + // Act + $result = $nameNormalizer->dasherize($input); + + // Assert + $this->assertSame($expected, $result); + } + + /** + * @dataProvider camelizeDataProvider + * + * @param string $input + * @param string $expected + * + * @return void + */ + public function shouldCamelizeUnderscoreToCamelCase($input, $expected): void + { + // Arrange + $nameNormalizer = new NameNormalizer(); + + // Act + $result = $nameNormalizer->camelize($input); + + // Assert + $this->assertSame($expected, $result); + } +} diff --git a/tests/SprykerTest/Zed/Development/Business/PhpMd/PhpMdRunnerTest.php b/tests/SprykerTest/Zed/Development/Business/PhpMd/PhpMdRunnerTest.php new file mode 100644 index 00000000..62d320bb --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Business/PhpMd/PhpMdRunnerTest.php @@ -0,0 +1,123 @@ +createPhpMdRunner(); + + // Act + $exitCode = $phpMdRunner->run('Development', []); + + // Assert + $this->assertEquals(static::EXIT_CODE_SUCCESS, $exitCode); + } + + /** + * @return void + */ + public function shouldIgnoreVendorDirectoryByDefault(): void + { + // Arrange + $phpMdRunner = $this->createPhpMdRunner(); + + // Act + $exitCode = $phpMdRunner->run(null, []); + + // Assert + $this->assertEquals(static::EXIT_CODE_SUCCESS, $exitCode); + } + + /** + * @return void + */ + public function shouldThrowExceptionForInvalidBundlePath(): void + { + // Assert + $this->expectException(ErrorException::class); + + // Arrange + $phpMdRunner = $this->createPhpMdRunner(); + + // Act + $phpMdRunner->run('InvalidModuleName', []); + } + + /** + * @return void + */ + public function shouldUseCustomConfigForStandaloneMode(): void + { + // Arrange + $standaloneMode = true; + $phpMdRunner = $this->createPhpMdRunner($standaloneMode); + + // Assuming the mock setup and expectations here + $exitCode = $phpMdRunner->run('Development'); + + // Assert + $this->assertEquals(static::EXIT_CODE_SUCCESS, $exitCode); + } + + /** + * @param bool $standaloneMode + * + * @return \Spryker\Zed\Development\Business\PhpMd\PhpMdRunner + */ + protected function createPhpMdRunner(bool $standaloneMode = false): PhpMdRunner + { + $configMock = $this + ->getMockBuilder(DevelopmentConfig::class) + ->getMock(); + + $configMock->method('isStandaloneMode') + ->willReturn($standaloneMode); + + $nameNormalizerMock = $this->createMock(NameNormalizerInterface::class); + + $processMock = $this->getMockBuilder(Process::class) + ->disableOriginalConstructor() + ->getMock(); + + return new PhpMdRunner($configMock, $nameNormalizerMock); + } +} diff --git a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjectsTest.php b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjectsTest.php index b0e1cc8c..6f431b29 100644 --- a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjectsTest.php +++ b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/CouplingBetweenObjectsTest.php @@ -13,6 +13,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -25,7 +26,14 @@ */ class CouplingBetweenObjectsTest extends Unit { + /** + * @var int + */ public const NUMBER_OF_COUPLING_BETWEEN_OBJECTS = 2; + + /** + * @var int + */ public const THRESHOLD = 1; /** @@ -36,7 +44,7 @@ class CouplingBetweenObjectsTest extends Unit * * @return void */ - public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedClassName, $nodeName) + public function testApplyDoesNotAddViolationIfNodeIsIgnorable(string $fullyQualifiedClassName, string $nodeName): void { $nodeMock = $this->getNodeMock($fullyQualifiedClassName, $nodeName); @@ -48,7 +56,7 @@ public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedCla /** * @return array */ - public function ignorableNodesProvider() + public function ignorableNodesProvider(): array { return [ ['Zed\Foo\BarDependencyProvider', 'BarDependencyProvider'], @@ -63,7 +71,7 @@ public function ignorableNodesProvider() /** * @return void */ - public function testApplyAddsViolationWhenClassIsNotIgnorable() + public function testApplyAddsViolationWhenClassIsNotIgnorable(): void { $nodeMock = $this->getNodeMock('Foo', 'Bar'); @@ -75,10 +83,10 @@ public function testApplyAddsViolationWhenClassIsNotIgnorable() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\PhpMd\Rules\Design\CouplingBetweenObjects */ - protected function getCouplingBetweenObjectsMock() + protected function getCouplingBetweenObjectsMock(): CouplingBetweenObjects { $mockBuilder = $this->getMockBuilder(CouplingBetweenObjects::class); - $mockBuilder->setMethods(['addViolation', 'getIntProperty']); + $mockBuilder->onlyMethods(['addViolation', 'getIntProperty']); $couplingBetweenObjectsMock = $mockBuilder->getMock(); $couplingBetweenObjectsMock->expects($this->once())->method('getIntProperty')->willReturn(static::THRESHOLD); @@ -92,10 +100,11 @@ protected function getCouplingBetweenObjectsMock() * * @return \PHPUnit\Framework\MockObject\MockObject|\PHPMD\AbstractNode */ - protected function getNodeMock($fullyQualifiedClassName, $nodeName) + protected function getNodeMock(string $fullyQualifiedClassName, string $nodeName): AbstractNode { $mockBuilder = $this->getMockBuilder(AbstractNode::class); - $mockBuilder->setMethods(['getMetric', 'getName', 'getNamespace', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName']) + $mockBuilder->addMethods(['getNamespace']) + ->onlyMethods(['getMetric', 'getName', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName']) ->disableOriginalConstructor(); $nodeMock = $mockBuilder->getMock(); diff --git a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildrenTest.php b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildrenTest.php index 1841e96a..361fa94f 100644 --- a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildrenTest.php +++ b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/NumberOfChildrenTest.php @@ -13,6 +13,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -25,7 +26,14 @@ */ class NumberOfChildrenTest extends Unit { + /** + * @var int + */ public const NUMBER_OF_CHILDREN = 2; + + /** + * @var int + */ public const THRESHOLD = 1; /** @@ -35,7 +43,7 @@ class NumberOfChildrenTest extends Unit * * @return void */ - public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedClassName) + public function testApplyDoesNotAddViolationIfNodeIsIgnorable(string $fullyQualifiedClassName): void { $nodeMock = $this->getNodeMock($fullyQualifiedClassName); @@ -47,7 +55,7 @@ public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedCla /** * @return array */ - public function ignorableNodesProvider() + public function ignorableNodesProvider(): array { return [ ['Zed\\Importer\\Business\\Importer\\AbstractImporter'], @@ -58,7 +66,7 @@ public function ignorableNodesProvider() /** * @return void */ - public function testApplyAddsViolationWhenClassIsNotIgnorable() + public function testApplyAddsViolationWhenClassIsNotIgnorable(): void { $nodeMock = $this->getNodeMock('Foo'); @@ -70,10 +78,10 @@ public function testApplyAddsViolationWhenClassIsNotIgnorable() /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\PhpMd\Rules\Design\NumberOfChildren */ - protected function getNumberOfChildrenMock() + protected function getNumberOfChildrenMock(): NumberOfChildren { $mockBuilder = $this->getMockBuilder(NumberOfChildren::class); - $mockBuilder->setMethods(['addViolation', 'getIntProperty']); + $mockBuilder->onlyMethods(['addViolation', 'getIntProperty']); $numberOfChildrenMock = $mockBuilder->getMock(); $numberOfChildrenMock->expects($this->once())->method('getIntProperty')->willReturn(static::THRESHOLD); @@ -86,10 +94,11 @@ protected function getNumberOfChildrenMock() * * @return \PHPUnit\Framework\MockObject\MockObject|\PHPMD\AbstractNode */ - protected function getNodeMock($fullyQualifiedClassName) + protected function getNodeMock(string $fullyQualifiedClassName): AbstractNode { $mockBuilder = $this->getMockBuilder(AbstractNode::class); - $mockBuilder->setMethods(['getMetric', 'getName', 'getNamespace', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName']) + $mockBuilder->addMethods(['getNamespace']) + ->onlyMethods(['getMetric', 'getName', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName']) ->disableOriginalConstructor(); $nodeMock = $mockBuilder->getMock(); diff --git a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethodsTest.php b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethodsTest.php index 09bed260..ee41b3b4 100644 --- a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethodsTest.php +++ b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyMethodsTest.php @@ -8,11 +8,13 @@ namespace SprykerTest\Zed\Development\Business\PhpMd\Rules\Design; use Codeception\Test\Unit; +use PHPMD\AbstractNode; use PHPMD\Node\AbstractTypeNode; use Spryker\Zed\Development\Business\PhpMd\Rules\Design\TooManyMethods; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -25,8 +27,19 @@ */ class TooManyMethodsTest extends Unit { + /** + * @var int + */ public const THRESHOLD_LOW = 1; + + /** + * @var int + */ public const THRESHOLD_HIGH = 3; + + /** + * @var int + */ public const NUMBER_OF_METHODS = 2; /** @@ -37,12 +50,12 @@ class TooManyMethodsTest extends Unit * * @return void */ - public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedClassName, $nodeName) + public function testApplyDoesNotAddViolationIfNodeIsIgnorable(string $fullyQualifiedClassName, string $nodeName): void { $nodeMock = $this->getNodeMock($fullyQualifiedClassName, $nodeName); $tooManyMethodsMock = $this->getTooManyMethodsMock(); - $tooManyMethodsMock->expects($this->once())->method('getIntProperty')->willReturn(self::THRESHOLD_LOW); + $tooManyMethodsMock->expects($this->once())->method('getIntProperty')->willReturn(static::THRESHOLD_LOW); $tooManyMethodsMock->expects($this->never())->method('addViolation'); $tooManyMethodsMock->apply($nodeMock); } @@ -50,7 +63,7 @@ public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedCla /** * @return array */ - public function ignorableNodesProvider() + public function ignorableNodesProvider(): array { return [ ['Client\\Foo\\BarFacade', 'BarFacade'], @@ -65,7 +78,7 @@ public function ignorableNodesProvider() /** * @return void */ - public function testApplyAddsViolationWhenClassIsNotIgnorable() + public function testApplyAddsViolationWhenClassIsNotIgnorable(): void { $nodeMock = $this->getNodeMock('Foo', 'Bar'); @@ -78,7 +91,7 @@ public function testApplyAddsViolationWhenClassIsNotIgnorable() /** * @return void */ - public function testApplyDoesNotAddViolationIfNumberOfMethodsLowerThenThreshold() + public function testApplyDoesNotAddViolationIfNumberOfMethodsLowerThenThreshold(): void { $nodeMock = $this->getNodeMock('Foo', 'Bar'); @@ -91,10 +104,10 @@ public function testApplyDoesNotAddViolationIfNumberOfMethodsLowerThenThreshold( /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\PhpMd\Rules\Design\TooManyMethods */ - protected function getTooManyMethodsMock() + protected function getTooManyMethodsMock(): TooManyMethods { $mockBuilder = $this->getMockBuilder(TooManyMethods::class); - $mockBuilder->setMethods(['addViolation', 'getIntProperty', 'getStringProperty']); + $mockBuilder->onlyMethods(['addViolation', 'getIntProperty', 'getStringProperty']); $tooManyMethodsMock = $mockBuilder->getMock(); $tooManyMethodsMock->expects($this->any())->method('getStringProperty')->willReturn('/ignore regex pattern/'); @@ -108,10 +121,11 @@ protected function getTooManyMethodsMock() * * @return \PHPUnit\Framework\MockObject\MockObject|\PHPMD\AbstractNode */ - protected function getNodeMock($fullyQualifiedClassName, $nodeName) + protected function getNodeMock(string $fullyQualifiedClassName, string $nodeName): AbstractNode { $mockBuilder = $this->getMockBuilder(AbstractTypeNode::class); - $mockBuilder->setMethods(['getMetric', 'getName', 'getNamespace', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName', 'getMethodNames']) + $mockBuilder->addMethods(['getNamespace']) + ->onlyMethods(['getMetric', 'getName', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName', 'getMethodNames']) ->disableOriginalConstructor(); $nodeMock = $mockBuilder->getMock(); diff --git a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethodsTest.php b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethodsTest.php index 58087d30..829b9d71 100644 --- a/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethodsTest.php +++ b/tests/SprykerTest/Zed/Development/Business/PhpMd/Rules/Design/TooManyPublicMethodsTest.php @@ -8,11 +8,13 @@ namespace SprykerTest\Zed\Development\Business\PhpMd\Rules\Design; use Codeception\Test\Unit; +use PHPMD\AbstractNode; use PHPMD\Node\AbstractTypeNode; use Spryker\Zed\Development\Business\PhpMd\Rules\Design\TooManyPublicMethods; /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -25,8 +27,19 @@ */ class TooManyPublicMethodsTest extends Unit { + /** + * @var int + */ public const THRESHOLD_LOW = 1; + + /** + * @var int + */ public const THRESHOLD_HIGH = 3; + + /** + * @var int + */ public const NUMBER_OF_METHODS = 2; /** @@ -37,12 +50,12 @@ class TooManyPublicMethodsTest extends Unit * * @return void */ - public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedClassName, $nodeName) + public function testApplyDoesNotAddViolationIfNodeIsIgnorable(string $fullyQualifiedClassName, string $nodeName): void { $nodeMock = $this->getNodeMock($fullyQualifiedClassName, $nodeName); $tooManyPublicMethodsMock = $this->getTooManyPublicMethodsMock(); - $tooManyPublicMethodsMock->expects($this->once())->method('getIntProperty')->willReturn(self::THRESHOLD_LOW); + $tooManyPublicMethodsMock->expects($this->once())->method('getIntProperty')->willReturn(static::THRESHOLD_LOW); $tooManyPublicMethodsMock->expects($this->never())->method('addViolation'); $tooManyPublicMethodsMock->apply($nodeMock); } @@ -50,7 +63,7 @@ public function testApplyDoesNotAddViolationIfNodeIsIgnorable($fullyQualifiedCla /** * @return array */ - public function ignorableNodesProvider() + public function ignorableNodesProvider(): array { return [ ['Client\\Foo\\BarFacade', 'BarFacade'], @@ -63,7 +76,7 @@ public function ignorableNodesProvider() /** * @return void */ - public function testApplyAddsViolationWhenClassIsNotIgnorable() + public function testApplyAddsViolationWhenClassIsNotIgnorable(): void { $nodeMock = $this->getNodeMock('Foo', 'Bar'); $nodeMock->method('getMethods')->willReturn([]); @@ -77,7 +90,7 @@ public function testApplyAddsViolationWhenClassIsNotIgnorable() /** * @return void */ - public function testApplyDoesNotAddViolationIfNumberOfMethodsLowerThenThreshold() + public function testApplyDoesNotAddViolationIfNumberOfMethodsLowerThenThreshold(): void { $nodeMock = $this->getNodeMock('Foo', 'Bar'); @@ -90,10 +103,10 @@ public function testApplyDoesNotAddViolationIfNumberOfMethodsLowerThenThreshold( /** * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Development\Business\PhpMd\Rules\Design\TooManyPublicMethods */ - protected function getTooManyPublicMethodsMock() + protected function getTooManyPublicMethodsMock(): TooManyPublicMethods { $mockBuilder = $this->getMockBuilder(TooManyPublicMethods::class); - $mockBuilder->setMethods(['addViolation', 'getIntProperty', 'getStringProperty']); + $mockBuilder->onlyMethods(['addViolation', 'getIntProperty', 'getStringProperty']); $tooManyMethodsMock = $mockBuilder->getMock(); $tooManyMethodsMock->expects($this->any())->method('getStringProperty')->willReturn('/ignore regex pattern/'); @@ -107,10 +120,11 @@ protected function getTooManyPublicMethodsMock() * * @return \PHPUnit\Framework\MockObject\MockObject|\PHPMD\AbstractNode */ - protected function getNodeMock($fullyQualifiedClassName, $nodeName) + protected function getNodeMock(string $fullyQualifiedClassName, string $nodeName): AbstractNode { $mockBuilder = $this->getMockBuilder(AbstractTypeNode::class); - $mockBuilder->setMethods(['getMetric', 'getName', 'getNamespace', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName', 'getMethods']) + $mockBuilder->addMethods(['getNamespace']) + ->onlyMethods(['getMetric', 'getName', 'getNamespaceName', 'hasSuppressWarningsAnnotationFor', 'getFullQualifiedName', 'getParentName', 'getMethods']) ->disableOriginalConstructor(); $nodeMock = $mockBuilder->getMock(); diff --git a/tests/SprykerTest/Zed/Development/Business/Resolver/CodeStylePathResolverTest.php b/tests/SprykerTest/Zed/Development/Business/Resolver/CodeStylePathResolverTest.php new file mode 100644 index 00000000..e1205580 --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Business/Resolver/CodeStylePathResolverTest.php @@ -0,0 +1,106 @@ +createPathResolver(); + + // Act + $resolvedPaths = $pathResolver->resolvePaths('Development', null, null, []); + + // Assert + $this->assertNotEmpty($resolvedPaths); + } + + /** + * @return void + */ + public function shouldThrowExceptionForInvalidNamespace(): void + { + // Assert + $this->expectException(RuntimeException::class); + + // Arrange + $pathResolver = $this->createPathResolver(); + + // Act + $pathResolver->resolvePaths(null, 'InvalidNamespace', null, []); + } + + /** + * @return void + */ + public function shouldHandleAllModulesForCoreNamespace(): void + { + // Arrange + $pathResolver = $this->createPathResolver(); + + // Act + $resolvedPaths = $pathResolver->resolvePaths('all', 'Spryker', null, []); + + // Assert + $this->assertNotEmpty($resolvedPaths); + } + + /** + * @return void + */ + public function shouldThrowExceptionForSuffixWithAllModules() + { + // Assert + $this->expectException(RuntimeException::class); + + // Arrange + $pathResolver = $this->createPathResolver(); + + // Act + $pathResolver->resolvePaths('all', 'Spryker', null, ['pathSuffix' => 'someSuffix']); + } + + /** + * @return \Spryker\Zed\Development\Business\Resolver\CodeStylePathResolver + */ + protected function createPathResolver(): CodeStylePathResolver + { + $configMock = $this->createMock(DevelopmentConfig::class); + $nameNormalizerMock = $this->createMock(NameNormalizerInterface::class); + $codeStyleSnifferConfigurationLoaderMock = $this->createMock(CodeStyleSnifferConfigurationLoaderInterface::class); + + return new CodeStylePathResolver($configMock, $nameNormalizerMock, $codeStyleSnifferConfigurationLoaderMock); + } +} diff --git a/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/Builder/ArchitectureSnifferConfigurationBuilderTest.php b/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/Builder/ArchitectureSnifferConfigurationBuilderTest.php index f037777c..e9d07e1b 100644 --- a/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/Builder/ArchitectureSnifferConfigurationBuilderTest.php +++ b/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/Builder/ArchitectureSnifferConfigurationBuilderTest.php @@ -11,6 +11,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -22,7 +23,14 @@ */ class ArchitectureSnifferConfigurationBuilderTest extends Unit { + /** + * @var string + */ protected const CONFIG_PRIORITY_NAME = 'priority'; + + /** + * @var string + */ protected const CONFIG_IGNORE_ERRORS = 'ignoreErrors'; /** @@ -41,7 +49,7 @@ class ArchitectureSnifferConfigurationBuilderTest extends Unit public function testAclModuleHasPriorityDifferentFromDefaultPriority(): void { $aclModuleArchitectureSnifferConfig = $this->tester->createArchitectureSnifferConfigurationBuilder()->getConfiguration( - $this->tester->getZedAclModulePath() + $this->tester->getZedAclModulePath(), ); $aclPriority = $aclModuleArchitectureSnifferConfig[static::CONFIG_PRIORITY_NAME]; @@ -54,11 +62,11 @@ public function testAclModuleHasPriorityDifferentFromDefaultPriority(): void */ public function testCustomerModuleWillBeSkipped(): void { + $this->expectExceptionMessage('Priority should be more than 0'); + $customerModuleArchitectureSnifferConfig = $this->tester->createArchitectureSnifferConfigurationBuilder()->getConfiguration( - $this->tester->getZedCustomerModulePath() + $this->tester->getZedCustomerModulePath(), ); - - $this->assertEmpty($customerModuleArchitectureSnifferConfig); } /** @@ -67,7 +75,7 @@ public function testCustomerModuleWillBeSkipped(): void public function testDiscountModuleHasDefaultPriorityBecauseDoesNotHavePriorityParamInConfigFile(): void { $discountModuleArchitectureSnifferConfig = $this->tester->createArchitectureSnifferConfigurationBuilder()->getConfiguration( - $this->tester->getZedDiscountModulePath() + $this->tester->getZedDiscountModulePath(), ); $discountPriority = $discountModuleArchitectureSnifferConfig[static::CONFIG_PRIORITY_NAME]; @@ -81,7 +89,7 @@ public function testDiscountModuleHasDefaultPriorityBecauseDoesNotHavePriorityPa public function testCountryModuleHasDefaultPriorityBecauseConfigFileHasWrongExtension(): void { $countryModuleArchitectureSnifferConfig = $this->tester->createArchitectureSnifferConfigurationBuilder()->getConfiguration( - $this->tester->getZedCountryPath() + $this->tester->getZedCountryPath(), ); $countryPriority = $countryModuleArchitectureSnifferConfig[static::CONFIG_PRIORITY_NAME]; @@ -95,7 +103,7 @@ public function testCountryModuleHasDefaultPriorityBecauseConfigFileHasWrongExte public function testProductModuleHasDefaultPriorityBecauseConfigFileDoesNotExist(): void { $productModuleArchitectureSnifferConfig = $this->tester->createArchitectureSnifferConfigurationBuilder()->getConfiguration( - $this->tester->getZedProductModulePath() + $this->tester->getZedProductModulePath(), ); $productPriority = $productModuleArchitectureSnifferConfig[static::CONFIG_PRIORITY_NAME]; @@ -109,7 +117,7 @@ public function testProductModuleHasDefaultPriorityBecauseConfigFileDoesNotExist public function testCustomDirectoryHasDefaultPriorityBecauseConfigFileDoesNotHaveArchitectureSnifferBlock(): void { $customDirectoryArchitectureSnifferConfig = $this->tester->createArchitectureSnifferConfigurationBuilder()->getConfiguration( - $this->tester->getZedCustomPath() + $this->tester->getZedCustomPath(), ); $customDirectoryPriority = $customDirectoryArchitectureSnifferConfig[static::CONFIG_PRIORITY_NAME]; @@ -123,7 +131,7 @@ public function testCustomDirectoryHasDefaultPriorityBecauseConfigFileDoesNotHav public function testDiscountModuleHasIgnoreErrorPatternsInConfigFile(): void { $discountModuleArchitectureSnifferConfig = $this->tester->createArchitectureSnifferConfigurationBuilder()->getConfiguration( - $this->tester->getZedDiscountModulePath() + $this->tester->getZedDiscountModulePath(), ); $discountModuleIgnoreErrorPatterns = $discountModuleArchitectureSnifferConfig[static::CONFIG_IGNORE_ERRORS]; diff --git a/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReaderTest.php b/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReaderTest.php index a8bf6a13..32eda902 100644 --- a/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReaderTest.php +++ b/tests/SprykerTest/Zed/Development/Business/SnifferConfiguration/ConfigurationReader/ConfigurationReaderTest.php @@ -11,6 +11,7 @@ /** * Auto-generated group annotations + * * @group SprykerTest * @group Zed * @group Development @@ -33,7 +34,7 @@ class ConfigurationReaderTest extends Unit public function testAclModuleHasToolingFileAndParseIt(): void { $data = $this->tester->createConfigurationReader()->getModuleConfigurationByAbsolutePath( - $this->tester->getZedAclModulePath() + $this->tester->getZedAclModulePath(), ); $this->assertNotEmpty($data); @@ -45,7 +46,7 @@ public function testAclModuleHasToolingFileAndParseIt(): void public function testDiscountModuleHasToolingFileAndParseIt(): void { $data = $this->tester->createConfigurationReader()->getModuleConfigurationByAbsolutePath( - $this->tester->getZedDiscountModulePath() + $this->tester->getZedDiscountModulePath(), ); $this->assertNotEmpty($data); @@ -57,7 +58,7 @@ public function testDiscountModuleHasToolingFileAndParseIt(): void public function testCustomerModuleHasToolingFileAndParseIt(): void { $data = $this->tester->createConfigurationReader()->getModuleConfigurationByAbsolutePath( - $this->tester->getZedCustomerModulePath() + $this->tester->getZedCustomerModulePath(), ); $this->assertNotEmpty($data); @@ -69,7 +70,7 @@ public function testCustomerModuleHasToolingFileAndParseIt(): void public function testCountryModuleHasToolingFileWithWrongExtension(): void { $data = $this->tester->createConfigurationReader()->getModuleConfigurationByAbsolutePath( - $this->tester->getZedCountryPath() + $this->tester->getZedCountryPath(), ); $this->assertEmpty($data); @@ -81,7 +82,7 @@ public function testCountryModuleHasToolingFileWithWrongExtension(): void public function testProductModuleDoesNotHaveToolingFile(): void { $data = $this->tester->createConfigurationReader()->getModuleConfigurationByAbsolutePath( - $this->tester->getZedProductModulePath() + $this->tester->getZedProductModulePath(), ); $this->assertEmpty($data); @@ -93,7 +94,7 @@ public function testProductModuleDoesNotHaveToolingFile(): void public function testCustomFolderHasToolingFileAndParseIt(): void { $data = $this->tester->createConfigurationReader()->getModuleConfigurationByAbsolutePath( - $this->tester->getZedCustomPath() + $this->tester->getZedCustomPath(), ); $this->assertNotEmpty($data); diff --git a/tests/SprykerTest/Zed/Development/Communication/Console/CodePhpstanConsoleTest.php b/tests/SprykerTest/Zed/Development/Communication/Console/CodePhpstanConsoleTest.php new file mode 100644 index 00000000..31f835b5 --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Communication/Console/CodePhpstanConsoleTest.php @@ -0,0 +1,132 @@ +createCommandTester(); + + // Act + $exitCode = $commandTester->execute([]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Run PHPStan static analyzer for project or core', $commandTester->getDisplay()); + } + + /** + * @return void + */ + public function executesSuccessfullyWithModuleOption(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--module' => 'Spryker.Development', + ]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Run PHPStan for Spryker.Development', $commandTester->getDisplay()); + } + + /** + * @return void + */ + public function executesSuccessfullyWithDryRunOption(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--dry-run' => true, + ]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Dry-run the command, display it only', $commandTester->getDisplay()); + } + + /** + * @return void + */ + public function executesSuccessfullyWithLevelOption(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--level' => '7', + ]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Level of rule options - the higher the stricter', $commandTester->getDisplay()); + } + + /** + * @return void + */ + public function failsWithInvalidLevelOption(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--level' => 'invalid', + ]); + + // Assert + $this->assertNotSame(0, $exitCode); + } + + /** + * @return \Symfony\Component\Console\Tester\CommandTester + */ + protected function createCommandTester(): CommandTester + { + $application = new Application(); + $application->add(new CodePhpstanConsole()); + + $command = $application->find('code:phpstan'); + + return new CommandTester($command); + } +} diff --git a/tests/SprykerTest/Zed/Development/Communication/Console/CodeStyleSnifferConsoleTest.php b/tests/SprykerTest/Zed/Development/Communication/Console/CodeStyleSnifferConsoleTest.php new file mode 100644 index 00000000..b04b3e3f --- /dev/null +++ b/tests/SprykerTest/Zed/Development/Communication/Console/CodeStyleSnifferConsoleTest.php @@ -0,0 +1,134 @@ +createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--module' => 'Development', + ]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Run Code Style Sniffer for PROJECT in Development', $commandTester->getDisplay()); + } + + /** + * @return void + */ + public function executesSuccessfullyWithCoreModule(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--module' => 'Spryker.Development', + ]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Run Code Style Sniffer for CORE in Spryker.Development', $commandTester->getDisplay()); + } + + /** + * @return void + */ + public function executesWithDryRunOption(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--dry-run' => true, + ]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Dry-Run the command, display it only', $commandTester->getDisplay()); + } + + /** + * @return void + */ + public function failsWithInvalidModule(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--module' => 'InvalidModule', + ]); + + // Assert + $this->assertNotSame(0, $exitCode); + } + + /** + * @return void + */ + public function executesWithFixOption(): void + { + // Arrange + $commandTester = $this->createCommandTester(); + + // Act + $exitCode = $commandTester->execute([ + '--fix' => true, + ]); + + // Assert + $this->assertSame(0, $exitCode); + $this->assertStringContainsString('Automatically fix errors that can be fixed', $commandTester->getDisplay()); + } + + /** + * @return \Symfony\Component\Console\Tester\CommandTester + */ + protected function createCommandTester(): CommandTester + { + $application = new Application(); + $application->add(new CodeStyleSnifferConsole()); + + $command = $application->find('code:sniff:style'); + + return new CommandTester($command); + } +} diff --git a/tests/SprykerTest/Zed/Development/_support/DevelopmentBusinessTester.php b/tests/SprykerTest/Zed/Development/_support/DevelopmentBusinessTester.php index 597b01ed..bd8f14ff 100644 --- a/tests/SprykerTest/Zed/Development/_support/DevelopmentBusinessTester.php +++ b/tests/SprykerTest/Zed/Development/_support/DevelopmentBusinessTester.php @@ -8,8 +8,12 @@ namespace SprykerTest\Zed\Development; use Codeception\Actor; +use Spryker\Zed\Development\Business\CodeStyleSniffer\CodeStyleSniffer; use Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfiguration; use Spryker\Zed\Development\Business\CodeStyleSniffer\Config\CodeStyleSnifferConfigurationLoader; +use Spryker\Zed\Development\Business\Normalizer\NameNormalizer; +use Spryker\Zed\Development\Business\Resolver\CodeStylePathResolver; +use Spryker\Zed\Development\Business\Resolver\PathResolverInterface; use Spryker\Zed\Development\Business\SnifferConfiguration\Builder\ArchitectureSnifferConfigurationBuilder; use Spryker\Zed\Development\Business\SnifferConfiguration\Builder\SnifferConfigurationBuilderInterface; use Spryker\Zed\Development\Business\SnifferConfiguration\ConfigurationReader\ConfigurationReader; @@ -18,7 +22,6 @@ use Symfony\Component\Yaml\Parser; /** - * Inherited Methods * @method void wantToTest($text) * @method void wantTo($text) * @method void execute($callable) @@ -28,7 +31,7 @@ * @method void am($role) * @method void lookForwardTo($achieveValue) * @method void comment($description) - * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL) + * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = null) * * @SuppressWarnings(PHPMD) */ @@ -36,8 +39,16 @@ class DevelopmentBusinessTester extends Actor { use _generated\DevelopmentBusinessTesterActions; + /** + * @var int + */ protected const DEFAULT_PRIORITY = 2; + /** + * @var int + */ + protected const DEFAULT_LEVEL = 1; + /** * @return \Spryker\Zed\Development\Business\SnifferConfiguration\Builder\SnifferConfigurationBuilderInterface */ @@ -45,7 +56,7 @@ public function createArchitectureSnifferConfigurationBuilder(): SnifferConfigur { return new ArchitectureSnifferConfigurationBuilder( $this->createConfigurationReader(), - static::DEFAULT_PRIORITY + static::DEFAULT_PRIORITY, ); } @@ -55,7 +66,7 @@ public function createArchitectureSnifferConfigurationBuilder(): SnifferConfigur public function createConfigurationReader(): ConfigurationReaderInterface { return new ConfigurationReader( - $this->createSymfonyYamlParser() + $this->createSymfonyYamlParser(), ); } @@ -67,6 +78,14 @@ public function getDefaultPriority(): int return static::DEFAULT_PRIORITY; } + /** + * @return int + */ + public function getDefaultLevel(): int + { + return static::DEFAULT_LEVEL; + } + /** * @return \Symfony\Component\Yaml\Parser */ @@ -82,7 +101,7 @@ public function createCodeStyleSnifferConfigurationLoader(): CodeStyleSnifferCon { return new CodeStyleSnifferConfigurationLoader( $this->createConfigurationReader(), - $this->createCodeStyleSnifferConfiguration() + $this->createCodeStyleSnifferConfiguration(), ); } @@ -92,7 +111,7 @@ public function createCodeStyleSnifferConfigurationLoader(): CodeStyleSnifferCon public function createCodeStyleSnifferConfiguration(): CodeStyleSnifferConfiguration { return new CodeStyleSnifferConfiguration( - $this->createDevelopmentConfig() + $this->createDevelopmentConfig(), ); } @@ -103,4 +122,27 @@ public function createDevelopmentConfig(): DevelopmentConfig { return new DevelopmentConfig(); } + + /** + * @return \Spryker\Zed\Development\Business\CodeStyleSniffer\CodeStyleSniffer + */ + public function createCodeStyleSniffer(): CodeStyleSniffer + { + return new CodeStyleSniffer( + $this->createDevelopmentConfig(), + $this->createCodeStylePathResolver(), + ); + } + + /** + * @return \Spryker\Zed\Development\Business\Resolver\PathResolverInterface + */ + public function createCodeStylePathResolver(): PathResolverInterface + { + return new CodeStylePathResolver( + $this->createDevelopmentConfig(), + new NameNormalizer(), + $this->createCodeStyleSnifferConfigurationLoader(), + ); + } } diff --git a/tests/SprykerTest/Zed/Development/_support/DevelopmentCommunicationTester.php b/tests/SprykerTest/Zed/Development/_support/DevelopmentCommunicationTester.php new file mode 100644 index 00000000..91ec4492 --- /dev/null +++ b/tests/SprykerTest/Zed/Development/_support/DevelopmentCommunicationTester.php @@ -0,0 +1,29 @@ +getDevelopmentFactory($composerDependency); + $developmentFactory->setContainer($this->getContainerWithProvidedDependencies()); + $developmentFacade = new DevelopmentFacade(); + $developmentFacade->setFactory($developmentFactory); + + return $developmentFacade; + } + + /** + * @param array $composerDependency + * + * @return \Spryker\Zed\Development\Business\DevelopmentBusinessFactory|\PHPUnit\Framework\MockObject\MockObject + */ + protected function getDevelopmentFactory(array $composerDependency) + { $developmentFactory = Stub::make(DevelopmentBusinessFactory::class, [ 'createModuleDependencyParser' => function () { - return Stub::makeEmpty(ModuleDependencyParserInterface::class); + return Stub::makeEmpty(ModuleDependencyParserInterface::class, [ + 'parseOutgoingDependencies' => function () { + return new DependencyCollectionTransfer(); + }, + ]); }, 'createComposerDependencyParser' => function () use ($composerDependency) { return Stub::makeEmpty(ComposerDependencyParserInterface::class, [ @@ -42,9 +65,19 @@ public function getFacadeForDependencyTests(array $composerDependency): Developm }, ]); - $developmentFacade->setFactory($developmentFactory); + return $developmentFactory; + } - return $developmentFacade; + /** + * @return \Spryker\Zed\Kernel\Container + */ + protected function getContainerWithProvidedDependencies(): Container + { + $container = new Container(); + $developmentDependencyProvider = new DevelopmentDependencyProvider(); + $container = $developmentDependencyProvider->provideBusinessLayerDependencies($container); + + return $container; } /** @@ -57,11 +90,13 @@ public function getDependencyValidationRequestTransfer(string $moduleName = 'Def { $organizationTransfer = new OrganizationTransfer(); $organizationTransfer - ->setName('Spryker'); + ->setName('Spryker') + ->setNameDashed('spryker'); $moduleTransfer = new ModuleTransfer(); $moduleTransfer ->setName($moduleName) + ->setNameDashed(strtolower($moduleName)) ->setOrganization($organizationTransfer); $dependencyValidationRequestTransfer = new DependencyValidationRequestTransfer(); @@ -78,13 +113,14 @@ public function getDependencyValidationRequestTransfer(string $moduleName = 'Def public function getDevOnlyComposerDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => [], 'isOptional' => true, 'src' => '', 'tests' => '', 'composerRequire' => '', - 'composerRequireDev' => 'Foo', + 'composerRequireDev' => 'bar/foo', 'suggested' => '', 'isOwnExtensionModule' => false, ]; @@ -98,10 +134,11 @@ public function getDevOnlyComposerDependency(): array public function getInvalidSourceDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => false, - 'src' => 'Foo', + 'src' => 'bar/foo', 'tests' => '', 'composerRequire' => '', 'composerRequireDev' => '', @@ -118,12 +155,13 @@ public function getInvalidSourceDependency(): array public function getInvalidRequireDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => false, 'src' => '', 'tests' => '', - 'composerRequire' => 'Foo', + 'composerRequire' => 'bar/foo', 'composerRequireDev' => '', 'suggested' => '', 'isOwnExtensionModule' => false, @@ -138,12 +176,13 @@ public function getInvalidRequireDependency(): array public function getValidSourceDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => false, - 'src' => 'Foo', + 'src' => 'bar/foo', 'tests' => '', - 'composerRequire' => 'Foo', + 'composerRequire' => 'bar/foo', 'composerRequireDev' => '', 'suggested' => '', 'isOwnExtensionModule' => false, @@ -158,11 +197,12 @@ public function getValidSourceDependency(): array public function getInvalidTestDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => false, 'src' => '', - 'tests' => 'Foo', + 'tests' => 'bar/foo', 'composerRequire' => '', 'composerRequireDev' => '', 'suggested' => '', @@ -178,13 +218,14 @@ public function getInvalidTestDependency(): array public function getInvalidRequireDevDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => false, 'src' => '', 'tests' => '', 'composerRequire' => '', - 'composerRequireDev' => 'Foo', + 'composerRequireDev' => 'bar/foo', 'suggested' => '', 'isOwnExtensionModule' => false, ]; @@ -198,13 +239,14 @@ public function getInvalidRequireDevDependency(): array public function getValidTestDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => false, 'src' => '', - 'tests' => 'Foo', + 'tests' => 'bar/foo', 'composerRequire' => '', - 'composerRequireDev' => 'Foo', + 'composerRequireDev' => 'bar/foo', 'suggested' => '', 'isOwnExtensionModule' => false, ]; @@ -218,12 +260,13 @@ public function getValidTestDependency(): array public function getInvalidOptionalRequiredDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => true, 'src' => '', 'tests' => '', - 'composerRequire' => 'Foo', + 'composerRequire' => 'bar/foo', 'composerRequireDev' => '', 'suggested' => '', 'isOwnExtensionModule' => false, @@ -238,27 +281,29 @@ public function getInvalidOptionalRequiredDependency(): array public function getValidOptionalRequiredDevDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => true, 'src' => '', 'tests' => '', 'composerRequire' => '', - 'composerRequireDev' => 'Foo', + 'composerRequireDev' => 'bar/foo', 'suggested' => '', 'isOwnExtensionModule' => false, ]; } /** - * Invalid dependency marked as optional not found in require-de + * Invalid dependency marked as optional not found in require-dev * * @return array */ public function getInvalidOptionalNotRequiredDevDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => true, 'src' => '', @@ -278,13 +323,14 @@ public function getInvalidOptionalNotRequiredDevDependency(): array public function getInvalidOptionalNotSuggestedDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => true, - 'src' => 'Foo', + 'src' => 'bar/foo', 'tests' => '', 'composerRequire' => '', - 'composerRequireDev' => 'Foo', + 'composerRequireDev' => 'bar/foo', 'suggested' => '', 'isOwnExtensionModule' => false, ]; @@ -298,13 +344,14 @@ public function getInvalidOptionalNotSuggestedDependency(): array public function getInvalidRequireAndRequireDevDependency(): array { return [ - 'dependencyModule' => 'Foo', + 'moduleName' => 'Foo', + 'composerName' => 'bar/foo', 'types' => ['foo'], 'isOptional' => false, - 'src' => 'Foo', - 'tests' => 'Foo', - 'composerRequire' => 'Foo', - 'composerRequireDev' => 'Foo', + 'src' => 'bar/foo', + 'tests' => 'bar/foo', + 'composerRequire' => 'bar/foo', + 'composerRequireDev' => 'bar/foo', 'suggested' => '', 'isOwnExtensionModule' => false, ]; @@ -318,7 +365,7 @@ public function getInvalidRequireAndRequireDevDependency(): array public function assertValidDependencies(DependencyValidationResponseTransfer $dependencyValidationResponseTransfer): void { foreach ($dependencyValidationResponseTransfer->getModuleDependencies() as $moduleDependency) { - $this->assertTrue($moduleDependency->getIsValid(), sprintf('Expected valid dependency but "%s" is marked as invalid', $moduleDependency->getModule())); + $this->assertTrue($moduleDependency->getIsValid(), sprintf('Expected valid dependency but "%s" is marked as invalid', $moduleDependency->getModuleName())); } } @@ -330,7 +377,7 @@ public function assertValidDependencies(DependencyValidationResponseTransfer $de public function assertInvalidDependencies(DependencyValidationResponseTransfer $dependencyValidationResponseTransfer): void { foreach ($dependencyValidationResponseTransfer->getModuleDependencies() as $moduleDependency) { - $this->assertFalse($moduleDependency->getIsValid(), sprintf('Expected invalid dependency but "%s" is marked as valid', $moduleDependency->getModule())); + $this->assertFalse($moduleDependency->getIsValid(), sprintf('Expected invalid dependency but "%s" is marked as valid', $moduleDependency->getModuleName())); } } } diff --git a/tests/SprykerTest/Zed/Development/_support/Helper/IdeAutoCompletion.php b/tests/SprykerTest/Zed/Development/_support/Helper/IdeAutoCompletion.php index 012032d1..def45f66 100644 --- a/tests/SprykerTest/Zed/Development/_support/Helper/IdeAutoCompletion.php +++ b/tests/SprykerTest/Zed/Development/_support/Helper/IdeAutoCompletion.php @@ -12,6 +12,9 @@ class IdeAutoCompletion extends Module { + /** + * @var string + */ public const TEST_TARGET_DIRECTORY = '/tmp/development-ide-auto-completion-test/'; /** @@ -19,7 +22,7 @@ class IdeAutoCompletion extends Module * * @return void */ - public function _before(TestInterface $test) + public function _before(TestInterface $test): void { parent::_before($test); @@ -30,7 +33,7 @@ public function _before(TestInterface $test) /** * @return void */ - protected function removeTestTargetDirectory() + protected function removeTestTargetDirectory(): void { if (!is_dir(static::TEST_TARGET_DIRECTORY)) { return; @@ -50,7 +53,7 @@ protected function getFilesystem() /** * @return void */ - protected function createTestTargetDirectory() + protected function createTestTargetDirectory(): void { mkdir(static::TEST_TARGET_DIRECTORY, 0777, true); } @@ -60,7 +63,7 @@ protected function createTestTargetDirectory() * * @return void */ - public function _after(TestInterface $test) + public function _after(TestInterface $test): void { parent::_after($test); @@ -69,11 +72,11 @@ public function _after(TestInterface $test) /** * @param \Codeception\TestInterface $test - * @param bool $fail + * @param \Exception $fail * * @return void */ - public function _failed(TestInterface $test, $fail) + public function _failed(TestInterface $test, $fail): void { parent::_failed($test, $fail); diff --git a/tests/SprykerTest/Zed/Development/_support/Helper/SnifferConfigurationHelper.php b/tests/SprykerTest/Zed/Development/_support/Helper/SnifferConfigurationHelper.php index fba0a6ac..9f352403 100644 --- a/tests/SprykerTest/Zed/Development/_support/Helper/SnifferConfigurationHelper.php +++ b/tests/SprykerTest/Zed/Development/_support/Helper/SnifferConfigurationHelper.php @@ -11,11 +11,34 @@ class SnifferConfigurationHelper extends Module { + /** + * @var string + */ protected const PATH_SPRYKER_ZED_ACL_MODULE = 'ConfigurationReader/Spryker/Zed/Acl/'; + + /** + * @var string + */ protected const PATH_SPRYKER_ZED_CUSTOMER_MODULE = 'ConfigurationReader/Spryker/Zed/Customer/'; + + /** + * @var string + */ protected const PATH_SPRYKER_ZED_COUNTRY_MODULE = 'ConfigurationReader/Spryker/Zed/Country/'; + + /** + * @var string + */ protected const PATH_SPRYKER_ZED_DISCOUNT_MODULE = 'ConfigurationReader/Spryker/Zed/Discount/'; + + /** + * @var string + */ protected const PATH_SPRYKER_ZED_PRODUCT_MODULE = 'ConfigurationReader/Spryker/Zed/Product/'; + + /** + * @var string + */ protected const PATH_CUSTOM_FOLDER = 'ConfigurationReader/custom/'; /** diff --git a/tests/SprykerTest/Zed/Development/codeception.yml b/tests/SprykerTest/Zed/Development/codeception.yml index a008f7f4..f1664059 100644 --- a/tests/SprykerTest/Zed/Development/codeception.yml +++ b/tests/SprykerTest/Zed/Development/codeception.yml @@ -3,7 +3,7 @@ paths: tests: . data: ../../../_data support: _support - log: ../../../_output + output: ../../../_output coverage: enabled: true remote: false @@ -13,10 +13,9 @@ coverage: suites: Business: path: Business - class_name: DevelopmentBusinessTester + actor: DevelopmentBusinessTester modules: enabled: - - Asserts - Filesystem - \SprykerTest\Shared\Testify\Helper\Environment - \SprykerTest\Shared\Testify\Helper\ConfigHelper @@ -26,3 +25,14 @@ suites: - \SprykerTest\Zed\Development\Helper\IdeAutoCompletion - \SprykerTest\Zed\Development\Helper\DependencyValidatorModule - \SprykerTest\Zed\Development\Helper\SnifferConfigurationHelper + Communication: + path: Communication + actor: DevelopmentCommunicationTester + modules: + enabled: + - Asserts + - Filesystem + - \SprykerTest\Shared\Testify\Helper\Environment + - \SprykerTest\Shared\Testify\Helper\ConfigHelper + - \SprykerTest\Shared\Testify\Helper\LocatorHelper + - \SprykerTest\Shared\Testify\Helper\DependencyHelper diff --git a/tests/_data/SchemaFiles/QuxQuux/src/Spryker/Zed/QuxQuux/Persistence/Propel/Schema/qux_quux.schema.xml b/tests/_data/SchemaFiles/QuxQuux/src/Spryker/Zed/QuxQuux/Persistence/Propel/Schema/qux_quux.schema.xml new file mode 100644 index 00000000..9c55feca --- /dev/null +++ b/tests/_data/SchemaFiles/QuxQuux/src/Spryker/Zed/QuxQuux/Persistence/Propel/Schema/qux_quux.schema.xml @@ -0,0 +1,9 @@ + + + + + + +
+ +
diff --git a/tests/_data/SchemaFiles/ZipZap/src/Spryker/Zed/ZipZap/Persistence/Propel/Schema/zip_zap.schema.xml b/tests/_data/SchemaFiles/ZipZap/src/Spryker/Zed/ZipZap/Persistence/Propel/Schema/zip_zap.schema.xml new file mode 100644 index 00000000..3be7f7f4 --- /dev/null +++ b/tests/_data/SchemaFiles/ZipZap/src/Spryker/Zed/ZipZap/Persistence/Propel/Schema/zip_zap.schema.xml @@ -0,0 +1,9 @@ + + + + + + +
+ +
diff --git a/tests/_data/SchemaWithBadDependencies/test.schema.xml b/tests/_data/SchemaWithBadDependencies/test.schema.xml new file mode 100644 index 00000000..fc13462e --- /dev/null +++ b/tests/_data/SchemaWithBadDependencies/test.schema.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + +
+ +
diff --git a/tests/_data/SchemaWithDependencies/test.schema.xml b/tests/_data/SchemaWithDependencies/test.schema.xml new file mode 100644 index 00000000..fc13462e --- /dev/null +++ b/tests/_data/SchemaWithDependencies/test.schema.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + +
+ +
diff --git a/tests/_data/StaleSchemaWithDependencies/test.schema.xml b/tests/_data/StaleSchemaWithDependencies/test.schema.xml new file mode 100644 index 00000000..1d805619 --- /dev/null +++ b/tests/_data/StaleSchemaWithDependencies/test.schema.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + +
+ +
diff --git a/tests/dd.php b/tests/dd.php index e4cf4fb3..f85b91f6 100644 --- a/tests/dd.php +++ b/tests/dd.php @@ -1,7 +1,7 @@