{"id":14968576,"url":"https://github.com/mglaman/phpstan-drupal","last_synced_at":"2025-05-14T12:09:35.826Z","repository":{"id":38850236,"uuid":"160881720","full_name":"mglaman/phpstan-drupal","owner":"mglaman","description":"Extension for PHPStan to allow analysis of Drupal code.","archived":false,"fork":false,"pushed_at":"2025-04-10T15:56:43.000Z","size":1103,"stargazers_count":200,"open_issues_count":106,"forks_count":78,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-10T16:03:24.293Z","etag":null,"topics":["drupal","hacktoberfest","php","phpstan","static-analysis"],"latest_commit_sha":null,"homepage":"https://phpstan-drupal.mglaman.dev/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mglaman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"mglaman","patreon":null,"open_collective":"phpstan-drupal","tidelift":"packagist/mglaman/phpstan-drupal","ko_fi":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2018-12-07T22:26:26.000Z","updated_at":"2025-04-10T15:38:09.000Z","dependencies_parsed_at":"2023-11-23T20:06:17.648Z","dependency_job_id":"895e8fdc-1f9d-4b65-92a0-de2c325f8214","html_url":"https://github.com/mglaman/phpstan-drupal","commit_stats":{"total_commits":548,"total_committers":60,"mean_commits":9.133333333333333,"dds":"0.30109489051094895","last_synced_commit":"2ff2cc855820553c266077cd9e42c6f128288166"},"previous_names":[],"tags_count":91,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mglaman%2Fphpstan-drupal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mglaman%2Fphpstan-drupal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mglaman%2Fphpstan-drupal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mglaman%2Fphpstan-drupal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mglaman","download_url":"https://codeload.github.com/mglaman/phpstan-drupal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345273,"owners_count":21088244,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drupal","hacktoberfest","php","phpstan","static-analysis"],"created_at":"2024-09-24T13:40:09.986Z","updated_at":"2025-04-11T05:00:29.520Z","avatar_url":"https://github.com/mglaman.png","language":"PHP","readme":"# phpstan-drupal\n\n[![Tests](https://github.com/mglaman/phpstan-drupal/actions/workflows/php.yml/badge.svg)](https://github.com/mglaman/phpstan-drupal/actions/workflows/php.yml) [![CircleCI](https://circleci.com/gh/mglaman/phpstan-drupal.svg?style=svg)](https://circleci.com/gh/mglaman/phpstan-drupal)\n\nExtension for [PHPStan](https://phpstan.org/) to allow analysis of Drupal code.\n\nPHPStan is able to [discover symbols](https://phpstan.org/user-guide/discovering-symbols) by using autoloading provided \nby Composer. However, Drupal does not provide autoloading information for modules and themes. This project registers \nthose namespaces so that PHPStan can properly discover symbols in your Drupal code base automatically.\n\n\u003e [!NOTE]\n\u003e With Drupal 11.2, Drupal core is now using PHPStan 2.0. The 1.x branch of phpstan-drupal will be supported until \n\u003e Drupal 10 loses security support when Drupal 12 is released.\n\n## Sponsors\n\n\u003ca href=\"https://www.undpaul.de/\"\u003e\u003cimg src=\"https://www.undpaul.de/themes/custom/undpaul3/logo.svg\" alt=\"undpaul\" width=\"250\" /\u003e\u003c/a\u003e \u003ca href=\"https://www.optasy.com/\"\u003e\u003cimg src=\"https://optasy.com/themes/custom/optasy/img/logo_optasy.png\" alt=\"Optasy\" width=\"250\"\u003e\u003c/a\u003e \u003ca href=\"https://www.fame.fi/\"\u003e\u003cimg src=\"https://www.fame.fi/assets/images/fame-logo.png\" alt=\"Fame Helsinki\" width=\"250\" \u003e\u003c/a\u003e\n\n[Would you like to sponsor?](https://github.com/sponsors/mglaman)\n\n## Usage\n\nWhen you are using [`phpstan/extension-installer`](https://github.com/phpstan/extension-installer), `phpstan.neon` will be automatically included.\n\n\u003cdetails\u003e\n  \u003csummary\u003eManual installation\u003c/summary\u003e\n\nIf you don't want to use `phpstan/extension-installer`, include `extension.neon` in your project's PHPStan config:\n\n```\nincludes:\n    - vendor/mglaman/phpstan-drupal/extension.neon\n```\n\nTo include Drupal specific analysis rules, include this file:\n\n```\nincludes:\n    - vendor/mglaman/phpstan-drupal/rules.neon\n```\n\u003c/details\u003e\n\n## Getting help\n\nAsk for assistance in the [discussions](https://github.com/mglaman/phpstan-drupal/discussions) or [#phpstan](https://drupal.slack.com/archives/C033S2JUMLJ) channel on Drupal Slack.\n\n## Excluding tests from analysis\n\nTo exclude tests from analysis, add the following parameter\n\n```\nparameters:\n\texcludePaths:\n\t\t- *Test.php\n\t\t- *TestBase.php\n```\n\n## Deprecation testing\n\nThis project depends on `phpstan/phpstan-deprecation-rules` which adds deprecation rules. We provide Drupal-specific \ndeprecated scope resolvers.\n\nTo only handle deprecation testing, use a `phpstan.neon` like this:\n\n```\nparameters:\n\tcustomRulesetUsed: true\n\treportUnmatchedIgnoredErrors: false\n\t# Ignore phpstan-drupal extension's rules.\n\tignoreErrors:\n\t\t- '#\\Drupal calls should be avoided in classes, use dependency injection instead#'\n\t\t- '#Plugin definitions cannot be altered.#'\n\t\t- '#Missing cache backend declaration for performance.#'\n\t\t- '#Plugin manager has cache backend specified but does not declare cache tags.#'\nincludes:\n\t- vendor/mglaman/phpstan-drupal/extension.neon\n\t- vendor/phpstan/phpstan-deprecation-rules/rules.neon\n```\n\nTo disable deprecation rules while using `phpstan/extension-installer`, you can do the following:\n\n```json\n{\n  \"extra\": {\n    \"phpstan/extension-installer\": {\n      \"ignore\": [\n        \"phpstan/phpstan-deprecation-rules\"\n      ]\n    }\n  }\n}\n```\n\nSee the `extension-installer` documentation for more information: https://github.com/phpstan/extension-installer#ignoring-a-particular-extension\n\n## Adapting to your project\n\n### Customizing rules\n\n#### Disabling checks for extending `@internal` classes\n\nYou can disable the `ClassExtendsInternalClassRule` rule by adding the following to your `phpstan.neon`:\n\n```neon\nparameters: \n    drupal:\n        rules:\n            classExtendsInternalClassRule: false\n```\n\n### Entity storage mappings.\n\nThe `EntityTypeManagerGetStorageDynamicReturnTypeExtension` service helps map dynamic return types. This inspects the\npassed entity type ID and tries to return a known storage class, besides the default `EntityStorageInterface`. The\ndefault mapping can be found in `extension.neon`. For example:\n\n```\nparameters:\n\tdrupal:\n\t\tentityMapping:\n\t\t\tblock:\n\t\t\t\tclass: Drupal\\block\\Entity\\Block\n\t\t\t\tstorage: Drupal\\Core\\Config\\Entity\\ConfigEntityStorage\n\t\t\tnode:\n\t\t\t\tclass: Drupal\\node\\Entity\\Node\n\t\t\t\tstorage: Drupal\\node\\NodeStorage\n\t\t\ttaxonomy_term:\n\t\t\t\tclass: Drupal\\taxonomy\\Entity\\Term\n\t\t\t\tstorage: Drupal\\taxonomy\\TermStorage\n\t\t\tuser:\n\t\t\t\tclass: Drupal\\user\\Entity\\User\n\t\t\t\tstorage: Drupal\\user\\UserStorage\n```\n\nTo add support for custom entities, you may add the same definition in your project's `phpstan.neon`. See the following\nexample for adding a mapping for Search API:\n\n```\nparameters:\n\tdrupal:\n\t\tentityMapping:\n\t\t\tsearch_api_index:\n\t\t\t\tclass: Drupal\\search_api\\Entity\\Index\n\t\t\t\tstorage: Drupal\\search_api\\Entity\\SearchApiConfigEntityStorage\n\t\t\tsearch_api_server:\n\t\t\t\tclass: Drupal\\search_api\\Entity\\Server\n\t\t\t\tstorage: Drupal\\search_api\\Entity\\SearchApiConfigEntityStorage\t\t\t    \n```\n\nSimilarly, the `EntityStorageDynamicReturnTypeExtension` service helps to determine the type of the entity which is\nloaded, created etc.. when using an entity storage.\nFor instance when using\n\n```php\n$node = \\Drupal::entityTypeManager()-\u003egetStorage('node')-\u003ecreate(['type' =\u003e 'page', 'title' =\u003e 'foo']);\n```\n\nIt helps with knowing the type of the `$node` variable is `Drupal\\node\\Entity\\Node`.\n\nThe default mapping can be found in `extension.neon`:\n\n```neon\nparameters:\n\tdrupal:\n\t\tentityMapping:\n\t\t\tblock:\n\t\t\t\tclass: Drupal\\block\\Entity\\Block\n\t\t\t\tstorage: Drupal\\Core\\Config\\Entity\\ConfigEntityStorage\n\t\t\tnode:\n\t\t\t\tclass: Drupal\\node\\Entity\\Node\n\t\t\t\tstorage: Drupal\\node\\NodeStorage\n\t\t\ttaxonomy_term:\n\t\t\t\tclass: Drupal\\taxonomy\\Entity\\Term\n\t\t\t\tstorage: Drupal\\taxonomy\\TermStorage\n\t\t\tuser:\n\t\t\t\tclass: Drupal\\user\\Entity\\User\n\t\t\t\tstorage: Drupal\\user\\UserStorage\n```\n\nTo add support for custom entities, you may add the same definition in your project's `phpstan.neon` likewise.\n\n### Providing entity type mappings for a contrib module\n\nContributed modules can provide their own mapping that can be automatically registered with a user's code base when \nthey use the `phpstan/extension-installer`.  The extension installer scans installed package's `composer.json` for a \nvalue in `extra.phpstan`. This will automatically bundle the defined include that contains an entity mapping \nconfiguration.\n\nFor example, the Paragraphs module could have the following `entity_mapping.neon` file:\n\n```neon\nparameters:\n\tdrupal:\n\t\tentityMapping:\n\t\t\tparagraph:\n\t\t\t\tclass: Drupal\\paragraphs\\Entity\\Paragraph\n\t\t\tparagraphs_type:\n\t\t\t\tclass: Drupal\\paragraphs\\Entity\\ParagraphsType\n```\n\nThen in the `composer.json` for Paragraphs, the `entity_mapping.neon` would be provided as a PHPStan include\n\n```json\n{\n  \"name\": \"drupal/paragraphs\",\n  \"description\": \"Enables the creation of Paragraphs entities.\",\n  \"type\": \"drupal-module\",\n  \"license\": \"GPL-2.0-or-later\",\n  \"require\": {\n    \"drupal/entity_reference_revisions\": \"~1.3\"\n  },\n  \"extra\": {\n    \"phpstan\": {\n      \"includes\": [\n        \"entity_mapping.neon\"\n      ]\n    }\n  }\n}\n\n```\n","funding_links":["https://github.com/sponsors/mglaman","https://opencollective.com/phpstan-drupal","https://tidelift.com/funding/github/packagist/mglaman/phpstan-drupal"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmglaman%2Fphpstan-drupal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmglaman%2Fphpstan-drupal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmglaman%2Fphpstan-drupal/lists"}