diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 83e02c4..b89176d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ on: branches: - '3.x' schedule: - - cron: "0 7 * * *" + - cron: '0 7 * * *' workflow_dispatch: env: @@ -19,7 +19,6 @@ env: LOCALGOV_DRUPAL_PROJECT_PATH: jobs: - build: name: Install LocalGov Drupal runs-on: ubuntu-latest @@ -39,7 +38,6 @@ jobs: - '8.3' steps: - - name: Save git branch and git repo names to env if this is not a pull request if: github.event_name != 'pull_request' run: | @@ -98,12 +96,9 @@ jobs: drupal-version: - '~10.0' php-version: - - '8.1' - - '8.2' - '8.3' steps: - - name: Cached workspace uses: actions/cache@v2 with: @@ -123,7 +118,7 @@ jobs: ./bin/phpcs -p ${LOCALGOV_DRUPAL_PROJECT_PATH} phpstan: - name: Deprecated code checks + name: Static analysis checks needs: build runs-on: ubuntu-latest @@ -135,12 +130,9 @@ jobs: drupal-version: - '~10.0' php-version: - - '8.1' - - '8.2' - '8.3' steps: - - name: Cached workspace uses: actions/cache@v2 with: @@ -154,7 +146,7 @@ jobs: with: php-version: ${{ matrix.php-version }} - - name: Run deprecated code checks + - name: Run PHPStan code checks run: | cd html ./bin/phpstan analyse -c ./phpstan.neon ./web/modules/contrib/localgov* ./web/profiles/contrib/localgov* ./web/themes/contrib/localgov* @@ -176,7 +168,6 @@ jobs: - '8.3' steps: - - name: Clone Drupal container uses: actions/checkout@v2 with: diff --git a/.lando.dist.yml b/.lando.dist.yml index bf0e12f..65d92f9 100644 --- a/.lando.dist.yml +++ b/.lando.dist.yml @@ -75,7 +75,7 @@ tooling: composer: service: appserver cmd: /usr/local/bin/composer - deprecated: + sca: service: appserver cmd: 'bash -c "/app/vendor/bin/phpstan analyse -c /app/phpstan.neon /app/web/profiles/contrib/localgov* /app/web/modules/contrib/localgov* /app/web/themes/contrib/localgov*"' drush: diff --git a/composer.json b/composer.json index c521a28..69d3cf6 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "phpspec/prophecy-phpunit": "^2", "phpstan/phpstan": "^1.0", "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.5", "squizlabs/php_codesniffer": "^3.6" }, "conflict": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..ac88f9b --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,306 @@ +parameters: + ignoreErrors: + - + message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/localgov_directories.install + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/localgov_directories.module + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_directories/modules/localgov_directories_db/tests/Kernel/InstallTest.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/modules/localgov_directories_location/localgov_directories_location.module + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/modules/localgov_directories_location/src/ProximitySearchSetup.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/modules/contrib/localgov_directories/modules/localgov_directories_or/src/FacetMapping.php + + - + message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/src/ConfigurationHelper.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/src/ConfigurationHelper.php + + - + message: "#^Parameter \\#2 \\$callback of function array_reduce expects callable\\(array\\, Drupal\\\\Core\\\\Entity\\\\EntityInterface\\)\\: array\\, Closure\\(array, Drupal\\\\node\\\\NodeInterface\\)\\: array\\ given\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/src/Plugin/Block/ChannelSearchBlock.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 3 + path: web/modules/contrib/localgov_directories/src/Plugin/facets/query_type/LocalGovDirectoriesQueryType.php + + - + message: "#^Variable \\$bundle might not be defined\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/src/Plugin/facets/query_type/LocalGovDirectoriesQueryType.php + + - + message: "#^Variable \\$query in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/src/Plugin/facets/query_type/LocalGovDirectoriesQueryType.php + + - + message: "#^Method Drupal\\\\Tests\\\\BrowserTestBase\\:\\:drupalLogout\\(\\) invoked with 1 parameter, 0 required\\.$#" + count: 1 + path: web/modules/contrib/localgov_directories/tests/src/Functional/FacetsTest.php + + - + message: "#^Call to method Drupal\\\\Tests\\\\UnitTestCase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_directories/tests/src/Unit/FacetPreprocessTest.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/modules/contrib/localgov_events/localgov_events.module + + - + message: "#^Call to static method Drupal\\\\Component\\\\Utility\\\\Html\\:\\:escape\\(\\) with incorrect case\\: Escape$#" + count: 1 + path: web/modules/contrib/localgov_geo/modules/localgov_geo_address/tests/Functional/AddressFormsTest.php + + - + message: "#^Undefined variable\\: \\$new_config$#" + count: 1 + path: web/modules/contrib/localgov_geo/modules/localgov_geo_update/src/MigrateDisplayModes.php + + - + message: "#^Variable \\$new_base_array might not be defined\\.$#" + count: 2 + path: web/modules/contrib/localgov_geo/modules/localgov_geo_update/src/MigrateDisplayModes.php + + - + message: "#^Variable \\$new_config in empty\\(\\) is never defined\\.$#" + count: 1 + path: web/modules/contrib/localgov_geo/modules/localgov_geo_update/src/MigrateDisplayModes.php + + - + message: "#^Variable \\$url might not be defined\\.$#" + count: 2 + path: web/modules/contrib/localgov_geo/modules/localgov_geo_update/tests/modules/localgov_geo_update_to_geo_test/src/Element/AutocompleteAddress.php + + - + message: "#^Parameter \\#2 \\$callback of function uasort expects callable\\(Drupal\\\\Core\\\\Entity\\\\EntityInterface, Drupal\\\\Core\\\\Entity\\\\EntityInterface\\)\\: int, Closure\\(Drupal\\\\geocoder\\\\Entity\\\\GeocoderProvider, Drupal\\\\geocoder\\\\Entity\\\\GeocoderProvider\\)\\: \\(\\-1\\|0\\|1\\) given\\.$#" + count: 1 + path: web/modules/contrib/localgov_geo/modules/localgov_geo_update/tests/modules/localgov_geo_update_to_geo_test/src/Plugin/Field/FieldWidget/AutocompleteAddress.php + + - + message: "#^Variable \\$overview might not be defined\\.$#" + count: 2 + path: web/modules/contrib/localgov_guides/src/Plugin/PreviewLinkAutopopulate/Guides.php + + - + message: "#^Parameter \\#2 \\$callback of function array_walk expects callable\\(Drupal\\\\Core\\\\Entity\\\\EntityInterface, int\\|string\\)\\: mixed, array\\{Drupal\\\\localgov_menu_link_group\\\\MenuLinkGrouper, 'groupChildMenuLinks'\\} given\\.$#" + count: 1 + path: web/modules/contrib/localgov_menu_link_group/localgov_menu_link_group.module + + - + message: "#^Parameter \\#1 \\$group of method Drupal\\\\localgov_menu_link_group\\\\Controller\\\\LocalGovMenuLinkGroupListBuilder\\:\\:determineParentMenuLinkLabel\\(\\) expects Drupal\\\\localgov_menu_link_group\\\\Entity\\\\LocalGovMenuLinkGroupInterface, Drupal\\\\Core\\\\Entity\\\\EntityInterface given\\.$#" + count: 1 + path: web/modules/contrib/localgov_menu_link_group/src/Controller/LocalGovMenuLinkGroupListBuilder.php + + - + message: "#^Dynamic call to static method Drupal\\\\localgov_menu_link_group\\\\Form\\\\LocalGovMenuLinkGroupForm\\:\\:prepareMenuLinkOption\\(\\)\\.$#" + count: 1 + path: web/modules/contrib/localgov_menu_link_group/src/Form/LocalGovMenuLinkGroupForm.php + + - + message: "#^Class DOMXPath referenced with incorrect case\\: DomXPath\\.$#" + count: 2 + path: web/modules/contrib/localgov_menu_link_group/tests/src/Kernel/GroupAccessTest.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/modules/contrib/localgov_menu_link_group/tests/src/Kernel/GroupConfigImportTest.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/modules/contrib/localgov_publications/localgov_publications.install + + - + message: "#^Variable \\$themeInfo in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: web/modules/contrib/localgov_publications/localgov_publications.install + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/modules/contrib/localgov_publications/localgov_publications.module + + - + message: "#^Access to an undefined property Drupal\\\\Tests\\\\localgov_publications\\\\Functional\\\\PublicationCoverPageTest\\:\\:\\$nodeStorage\\.$#" + count: 1 + path: web/modules/contrib/localgov_publications/tests/src/Functional/PublicationCoverPageTest.php + + - + message: "#^Access to an undefined property Drupal\\\\Tests\\\\localgov_publications\\\\Functional\\\\PublicationPageTest\\:\\:\\$nodeStorage\\.$#" + count: 1 + path: web/modules/contrib/localgov_publications/tests/src/Functional/PublicationPageTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_search/modules/localgov_search_db/tests/Kernel/InstallTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_search/tests/src/Kernel/ContentTypesAddedToSearchTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_search_solr/tests/Kernel/InstallTest.php + + - + message: "#^Parameter \\#1 \\$items of method Drupal\\\\Core\\\\Field\\\\Plugin\\\\Field\\\\FieldFormatter\\\\EntityReferenceFormatterBase\\:\\:getEntitiesToView\\(\\) expects Drupal\\\\Core\\\\Field\\\\EntityReferenceFieldItemListInterface, Drupal\\\\Core\\\\Field\\\\FieldItemListInterface given\\.$#" + count: 1 + path: web/modules/contrib/localgov_services/modules/localgov_services_landing/src/Plugin/Field/FieldFormatter/TaxonomyVerticalList.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_services/modules/localgov_services_navigation/src/EntityChildRelationshipUi.php + + - + message: "#^Parameter \\#1 \\$node of method Drupal\\\\localgov_services_navigation\\\\EntityChildRelationshipUi\\:\\:childrenField\\(\\) expects Drupal\\\\node\\\\NodeInterface, Drupal\\\\Core\\\\Entity\\\\EntityInterface given\\.$#" + count: 1 + path: web/modules/contrib/localgov_services/modules/localgov_services_navigation/src/EntityChildRelationshipUi.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/modules/contrib/localgov_services/modules/localgov_services_navigation/tests/src/Kernel/ChildReferencesTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_services/modules/localgov_services_navigation/tests/src/Kernel/ChildReferencesTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_services/modules/localgov_services_navigation/tests/src/Kernel/ParentFieldPathautoTest.php + + - + message: "#^Variable \\$overview might not be defined\\.$#" + count: 2 + path: web/modules/contrib/localgov_step_by_step/src/Plugin/PreviewLinkAutopopulate/StepBySteps.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_subsites/localgov_subsites.module + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_subsites/src/Plugin/Block/SubsitesAbstractBlockBase.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_subsites/src/Plugin/Block/SubsitesNavigationBlock.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_subsites/src/Subsite.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/modules/contrib/localgov_workflows/localgov_workflows.install + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 3 + path: web/modules/contrib/localgov_workflows/localgov_workflows.module + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_workflows/modules/localgov_review_date/localgov_review_date.module + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_workflows/modules/localgov_review_date/tests/src/Kernel/ReviewDateEntityTest.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 1 + path: web/modules/contrib/localgov_workflows/modules/localgov_workflows_notifications/localgov_workflows_notifications.module + + - + message: "#^Method Drupal\\\\localgov_workflows_notifications\\\\Form\\\\LocalgovServiceContactForm\\:\\:validateForm\\(\\) should return Drupal\\\\Core\\\\Entity\\\\ContentEntityInterface but return statement is missing\\.$#" + count: 2 + path: web/modules/contrib/localgov_workflows/modules/localgov_workflows_notifications/src/Form/LocalgovServiceContactForm.php + + - + message: "#^Variable \\$queue_item might not be defined\\.$#" + count: 1 + path: web/modules/contrib/localgov_workflows/modules/localgov_workflows_notifications/src/WorkflowNotification.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_workflows/modules/localgov_workflows_notifications/tests/src/Kernel/ReviewNotificationCronHookTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_workflows/modules/localgov_workflows_notifications/tests/src/Kernel/ReviewNotificationEmailTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_workflows/modules/localgov_workflows_notifications/tests/src/Kernel/WorkflowNotificationTest.php + + - + message: "#^Parameter \\#1 \\$node of method Drupal\\\\Tests\\\\localgov_workflows\\\\Functional\\\\WorkflowsAccessTest\\:\\:updateState\\(\\) expects Drupal\\\\node\\\\Entity\\\\Node, Drupal\\\\node\\\\NodeInterface given\\.$#" + count: 2 + path: web/modules/contrib/localgov_workflows/tests/src/Functional/WorkflowsAccessTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_workflows/tests/src/Kernel/WorkflowsEnableTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_workflows/tests/src/Kernel/WorkflowsInstallTest.php + + - + message: "#^Call to method Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:setUp\\(\\) with incorrect case\\: setup$#" + count: 1 + path: web/modules/contrib/localgov_workflows/tests/src/Kernel/WorkflowsScheduledTransitionsTest.php + + - + message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" + count: 2 + path: web/profiles/contrib/localgov/localgov.install diff --git a/phpstan.neon b/phpstan.neon index e21ac3c..e046f08 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,8 +1,25 @@ +includes: + - phpstan-baseline.neon + - vendor/phpstan/phpstan/conf/bleedingEdge.neon + parameters: - # we don't set a level so that we check deprecations only, and - # not to highlight unknown classes which are from composer suggestions + level: 1 customRulesetUsed: true reportUnmatchedIgnoredErrors: false + checkFunctionArgumentTypes: true + + drupal: + rules: + classExtendsInternalClassRule: false + + strictRules: + allRules: false + strictCalls: true + + # Exclude microsite project submodules from phpstan checks on the main project. + excludePaths: + - web/modules/contrib/localgov_alert_banner/modules/group_alert_banner/* + # Ignore phpstan-drupal extension's rules. ignoreErrors: - '#\Drupal calls should be avoided in classes, use dependency injection instead#' @@ -11,3 +28,9 @@ parameters: - '#Plugin manager has cache backend specified but does not declare cache tags.#' # new static() is a best practice in Drupal, so we cannot fix that. - '#^Unsafe usage of new static#' + # Disable PHPUnit dynamic call until core decision - https://www.drupal.org/project/drupal/issues/3029358 + - '#Dynamic call to static method PHPUnit\\Framework\\.*#' + # FIXME: ignore Drupal 12 deprecations + - '#Class Drupal\\localgov_forms\\Element\\AddressLookupElement extends deprecated class Drupal\\Core\\Render\\Element\\FormElement#' + - '#Call to deprecated method renderPlain\(\)#' + - '#Call to deprecated method rebuildThemeData\(\)#'