DrupalPractice standard¶
Core's phpcs.xml.dist runs only ExpectedException, ExceptionT, GlobalFunction,
NamespacedDependency and part of VariableAnalysis from this standard. The rules and the analyzer
checks that port the other sniffs are off in Drupal core.
| Sniff | Handled by |
|---|---|
DrupalPractice.Commenting.AuthorTag |
drupal/author-tag |
DrupalPractice.Commenting.CommentEmptyLine |
drupal/inline-comment-blank-line, mago format, partly |
DrupalPractice.Commenting.ExpectedException |
drupal/expected-exception-tag |
DrupalPractice.Constants.GlobalConstant |
drupal/global-constant |
DrupalPractice.Constants.GlobalDefine |
drupal/global-constant |
DrupalPractice.FunctionCalls.CurlSslVerifier |
drupal/curl-ssl-verify |
DrupalPractice.FunctionCalls.InsecureUnserialize |
drupal/insecure-unserialize, partly |
DrupalPractice.FunctionCalls.TCheckPlain |
drupal/escaped-placeholder |
DrupalPractice.FunctionDefinitions.FormAlterDoc |
drupal/form-alter-comment |
DrupalPractice.General.ClassName |
drupal/class-prefix |
DrupalPractice.General.DescriptionT |
drupal/untranslated-description |
DrupalPractice.General.ExceptionT |
drupal/translated-exception |
DrupalPractice.General.OptionsT |
drupal/untranslated-options |
DrupalPractice.InfoFiles.CoreVersionRequirement |
drupal/info-core-version-requirement |
DrupalPractice.InfoFiles.Description |
drupal/info-description |
DrupalPractice.InfoFiles.NamespacedDependency |
drupal/info-namespaced-dependency |
DrupalPractice.Objects.GlobalClass |
drupal/static-entity-load, partly |
DrupalPractice.Objects.GlobalDrupal |
drupal/global-drupal-call, partly |
DrupalPractice.Objects.GlobalFunction |
drupal/global-function |
DrupalPractice.Objects.StrictSchemaDisabled |
drupal/strict-config-schema |
DrupalPractice.Objects.UnusedPrivateMethod |
mago analyze (unused-method) |
DrupalPractice.Variables.GetRequestData |
drupal/request-superglobal |
DrupalPractice.Yaml.RoutingAccess |
drupal/routing-access |
VariableAnalysis.CodeAnalysis.VariableAnalysis |
mago analyze (self-outside-class-scope), mago analyze (static-outside-class-scope), nothing, drupal/unused-variable, drupal/variable-redeclaration |
DrupalPractice.Commenting.CommentEmptyLine¶
The rule leaves the blank line between a comment and a closing bracket to the formatter. Before the closing brace of a class, interface, trait or enum with members the formatter always writes one, and Coder reports it. A // comment with no text is reported by Mago's no-empty-comment, and a comment after code on the same line by drupal/post-statement-comment. The rule skips a comment right before the docblock of a declaration, where FunctionSpacing asks for the blank line, and a // @code example.
DrupalPractice.FunctionCalls.InsecureUnserialize¶
The rule skips a payload built with serialize() in the same function and a call that spreads its arguments, which are both reported by Coder, and reads a named options argument by its name. It also reports \unserialize() and (TRUE), which Coder misses.
DrupalPractice.Objects.GlobalClass¶
Coder reports a static load() or loadMultiple() call on one of 46 core entity classes, written with an imported name, in the same classes as its GlobalDrupal sniff. The analyzer check takes every entity class and a name written in full, and checks the classes of drupal/global-drupal-call. It skips a first-class callable, a constructor with a nullable parameter, deprecated code, anonymous classes and test code, which Coder reports.
DrupalPractice.Objects.GlobalDrupal¶
Coder reports a \Drupal:: call in a non-static method of a service, of a class that implements ContainerInjectionInterface, or of a class that extends one of 12 base classes such as FormBase. It reads the services from the nearest, shortest-named services file, so it misses a service whose id names its class. In a module that also has a drush.services.yml with a shorter name than the module's own file, it reads that one, and misses the module's services. The analyzer check reads the services file named after each module and profile, and core's, so it doesn't read drush.services.yml. It also reports entity handlers, container derivers, hook classes and subclasses of those base classes. It skips a constructor with a nullable parameter, deprecated code, anonymous classes and test code, which Coder reports.
DrupalPractice.Objects.UnusedPrivateMethod¶
The analyzer also reports an unused private static method, an unused private method of an enum, and a private method that is called only from its own body, which Coder skips. Coder reports a private __destruct() and a private method that is called only as $other->helper(), self::helper(), static::helper() or [self::class, 'helper']; the analyzer doesn't report any of them.
VariableAnalysis.CodeAnalysis.VariableAnalysis¶
Coder's ruleset skips *.tpl.php files, and so do drupal/unused-variable and drupal/variable-redeclaration. mago analyze checks them.
| Codes | Handled by |
|---|---|
SelfOutsideClass |
mago analyze (self-outside-class-scope) |
StaticOutsideClass |
mago analyze (static-outside-class-scope) |
UndefinedUnsetVariable |
nothing |
UnusedVariable |
drupal/unused-variable |
VariableRedeclaration |
drupal/variable-redeclaration |
UndefinedUnsetVariable: Anunset()of a variable that was never set. Not ported. Core'sphpcs.xml.distturns this code off. Coder doesn't count an element write such as$x['k'] = 1as setting$x, so it also reportsunset($x['k'])after one.mago analyzereports such a variable asundefined-variableat its first element write. A read afterunset()isUndefinedVariable, which Coder's ruleset turns off, andmago analyzereports it aspossibly-undefined-variable.
Checks for the Drupal 7 API¶
These checks look for Drupal 7 functions, hooks and arrays, such as check_plain(), hook_menu()
or $form_state['input'], and Coder runs some of them only on a Drupal 7 module. Most aren't
ported. On Drupal 8 and later most of those functions don't exist, and mago analyze reports a call
to one as an unknown function. The notes say where a check has a Drupal 8 form that something else
reports. The Drupal 7 checks of the Drupal standard are on the Drupal standard page,
since core's config still runs them.
| Sniff | Handled by | Notes |
|---|---|---|
DrupalPractice.FunctionCalls.CheckPlain |
nothing | |
DrupalPractice.FunctionCalls.DbQuery |
nothing | A Drupal 7 API, deprecated in Drupal 8. On Drupal 9 and later the function doesn't exist, and mago analyze reports it as unknown. |
DrupalPractice.FunctionCalls.DbSelectBraces |
nothing | A Drupal 7 API, deprecated in Drupal 8. On Drupal 9 and later the function doesn't exist, and mago analyze reports it as unknown. |
DrupalPractice.FunctionCalls.DefaultValueSanitize |
nothing | Reports a '#default_value' set to the result of check_plain(), check_markup(), check_url(), filter_xss() or filter_xss_admin(). Of these, only check_markup() exists on Drupal 11, and it is deprecated in 11.4. |
DrupalPractice.FunctionCalls.FormErrorT |
drupal/untranslated-message, partly |
Coder checks only the Drupal 7 functions form_set_error() and form_error(), which don't exist on Drupal 8 and later, and mago analyze reports a call to one as unknown. The analyzer check reports the same mistake in the methods that replace them instead: setErrorByName() and setError() of FormStateInterface. |
DrupalPractice.FunctionCalls.LCheckPlain |
nothing | |
DrupalPractice.FunctionCalls.MessageT |
drupal/untranslated-message, partly |
Coder checks only the Drupal 7 function drupal_set_message(), which doesn't exist on Drupal 9 and later, and mago analyze reports a call to it as unknown. The analyzer check reports the same mistake in the methods that replace it instead: addMessage(), addStatus(), addWarning() and addError() of MessengerInterface. |
DrupalPractice.FunctionCalls.Theme |
nothing | Coder also reports a call to theme_settings_convert_to_config(), which still exists on Drupal 11. That report is wrong: the function isn't a theme function, and the call is the right API. Mago doesn't report it. |
DrupalPractice.FunctionCalls.VariableSetSanitize |
nothing | |
DrupalPractice.FunctionDefinitions.AccessHookMenu |
nothing | Reports an 'access callback' => TRUE with no comment above it in hook_menu(), a Drupal 7 API. Mago doesn't report it. The routing file form, an open route with _access: 'TRUE' and no comment above it, is reported by drupal/routing-access. |
DrupalPractice.FunctionDefinitions.HookInitCss |
nothing | |
DrupalPractice.FunctionDefinitions.InstallT |
nothing | Coder runs it only on a Drupal 7 module, for t() and st() in hook_install() and hook_requirements(). |
DrupalPractice.General.AccessAdminPages |
nothing | Reports the access administration pages permission in hook_menu(), a Drupal 7 API. Mago doesn't report it. The routing file form, _permission: 'access administration pages', is reported by drupal/routing-access. |
DrupalPractice.General.FormStateInput |
nothing | Reports $form_state['input'], a read of the Drupal 7 form state array. When $form_state is typed as FormStateInterface, mago analyze reports any array access on it as invalid-array-access. Without the type, Mago doesn't report the key. |
DrupalPractice.General.LanguageNone |
nothing | Reports ['und'] written without spaces, as an index or as an array with one item, where Drupal 7 field code uses LANGUAGE_NONE. Mago doesn't report the key. On Drupal 8 and later LANGUAGE_NONE doesn't exist, and mago analyze reports it as non-existent-constant. |
DrupalPractice.General.VariableName |
nothing | A Drupal 7 variable_get() name without the module prefix, as the value of a '#default_value' key. |