You are here

good.php in Coder 8.2

This file contains all the valid notations for the drupal coding standard.

The goal is to create a style checker that validates all of this constructs.

Theme files often have lists in their file block:

  • item 1
  • item 2
  • sublist:
    • sub item 1
    • sub item2

File

coder_sniffer/Drupal/Test/good/good.php
View source
<?php

/**
 * @file
 * This file contains all the valid notations for the drupal coding standard.
 *
 * The goal is to create a style checker that validates all of this
 * constructs.
 *
 * Theme files often have lists in their file block:
 * - item 1
 * - item 2
 * - sublist:
 *   - sub item 1
 *   - sub item2
 */
use Drupal\very_long_module_name_i_am_inventing_here_trololololo\SuperManager;
use Drupal\some_module\ExampleClass as AliasedExampleClass;
use Drupal\mymodule\TestReturnType;

// Singleline comment before a code line.
$foo = 'bar';

/**
 * Doxygen comment style is allowed before define() statements.
 */
define('FOO_BAR', 5);

// Global variable names.
global $argc, $argv, $user, $is_https, $_mymodule_myvar;

/*
 * Multiline comment
 *
 * @see my_function()
 */

// PHP Constants must be written in CAPITAL letters.
TRUE;
FALSE;
NULL;

// Has whitespace at the end of the line.
$whitespaces = 'Yes, Please';

// Operators - have a space before and after.
$i = 0;
$i += 0;
$i -= 0;
$i == 0;
$i != 0;
$i > 0;
$i < 0;
$i >= 0;
$i <= 0;

// Unary operators must not have a space.
$i--;
--$i;
$i++;
++$i;
$x = $success ? $context['results']['success']++ : $context['results']['error']++;
$i = -1;
array(
  'i' => -1,
);
$i = 1 == -1;
$i = 1 === -1;
range(-50, -45);
$i[0] + 1;
$x->{$i} + 1;
REQUEST_TIME + 42;
!$x;
!($x + $y);
array(
  -1,
  -2,
  -3,
);
[
  -1,
  -2,
  -3,
];

// Operator line break for long lines.
$x = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1;
$x = $test ? -1 : 1;
$x = $test ? 1 : -1;

// Operators on new lines are allowed.
$x = CRM_Foo_Bar::singleton()
  ->checkWhizBang($option1, $option2) ? $something . $notes['baz'] : $notes['quux'] . $something_else;

// Casting has a space.
(int) $i;

// The last item in an multiline array should be followed by a comma.
// But not in a inline array.
$a = array();
$a = array(
  '1',
  '2',
  '3',
);
$a = array(
  '1',
  '2',
  '3',
);
$a = array(
  '1',
  '2',
  array(
    '3',
  ),
);
$a = array(
  '1',
  '2',
  array(
    'one',
    'two',
    'three',
    array(
      'key' => $value,
      'title' => 'test',
    ),
  ),
);

// Short array syntax.
$a = [];
$a = [
  '1',
  '2',
  '3',
];
$a = [
  '1',
  '2',
  '3',
];
$a = [
  '1',
  '2',
  [
    '3',
  ],
];
$a = [
  '1',
  '2',
  [
    'one',
    'two',
    'three',
    [
      'key' => $value,
      'title' => 'test',
    ],
  ],
];

// Array indentation.
$x = array(
  'foo' => 'bar',
  'fi' => long_function_call('hsdfsdmfsldkfnmdflkngdfngfg', 'fghfghfghfghfgh', $z),
  'a' => 'b',
  'foo' => array(
    'blu' => 1,
    'f' => x(1) + array(
      'h' => 'x',
    ),
  ),
);
$x = [
  'foo' => 'bar',
  'fi' => long_function_call('hsdfsdmfsldkfnmdflkngdfngfg', 'fghfghfghfghfgh', $z),
  'a' => 'b',
  'foo' => [
    'blu' => 1,
    'f' => x(1) + [
      'h' => 'x',
    ],
  ],
];

// Arrays in function calls.
foo(array(
  'value' => 0,
  'description' => t('xyz @url', array(
    '@url' => 'http://example.com',
  )),
));
foo([
  'value' => 0,
  'description' => t('xyz @url', [
    '@url' => 'http://example.com',
  ]),
]);

// Pretty array layout.
$a = array(
  'title' => 1,
  'weight' => 2,
  'callback' => 3,
);
$a = [
  'title' => 1,
  'weight' => 2,
  'callback' => 3,
];

// Arrays with multi line strings.
$query = db_query("\n  SELECT * FROM {foobar} WHERE nid IN (1, 2, 3)\n  AND date BETWEEN '%s' AND '%s'\n  ", array(
  ':from_date' => $from_date,
  ':to_date' => $to_date,
));
$query = db_query("\n  SELECT * FROM {foobar} WHERE nid IN (1, 2, 3)\n  AND date BETWEEN '%s' AND '%s'\n  ", [
  ':from_date' => $from_date,
  ':to_date' => $to_date,
]);

// Array with multi line comments.
$query = db_query("\n  SELECT * FROM {foobar} WHERE nid IN (1, 2, 3)\n  AND date BETWEEN '%s' AND '%s'", array(
  ':from_date' => $from_date,
  ':to_date' => $to_date,
));
$query = db_query("\n  SELECT * FROM {foobar} WHERE nid IN (1, 2, 3)\n  AND date BETWEEN '%s' AND '%s'", [
  ':from_date' => $from_date,
  ':to_date' => $to_date,
]);

// Array with multi-line constant string in it.
$array = array(
  'name' => 'example_a',
  'title' => 'Example A',
  'xml' => '
<foo>
  <bar>
    123456789 123456789 123456789 123456789 123456789 123456789 123456789
    123456789 123456789 123456789 123456789 123456789 123456789 123456789
  </bar>
</foo>',
);
$array = [
  'name' => 'example_a',
  'title' => 'Example A',
  'xml' => '
<foo>
  <bar>
    123456789 123456789 123456789 123456789 123456789 123456789 123456789
    123456789 123456789 123456789 123456789 123456789 123456789 123456789
  </bar>
</foo>',
];

// Indentation: multi line function call with array and fuction closer on the
// same line.
$result = example_fetch_data($id, array(
  'include_detail' => TRUE,
  'quiet' => TRUE,
));
some_function();
$result = example_fetch_data($id, [
  'include_detail' => TRUE,
  'quiet' => TRUE,
]);
some_function();

// Indentation: multi line function call with array and closing brace on the
// same line.
watchdog('example', 'Some warning %code for %id', array(
  '%code' => $code,
  '%doi' => $id,
), WATCHDOG_WARNING);
watchdog('example', 'Some warning %code for %id', [
  '%code' => $code,
  '%doi' => $id,
], WATCHDOG_WARNING);

// Nested short array syntax.
$x = [
  'label' => x([
    'test' => 'bar',
  ]),
];

// Nested arrays with object operators.
$derivatives["entity:{$entity_type_id}"] = array(
  'label' => t('Create @entity_type path alias', array(
    '@entity_type' => $entity_type
      ->getLowercaseLabel(),
  )),
  'category' => t('Path'),
  'entity_type_id' => $entity_type_id,
  'context' => array(
    'entity' => ContextDefinition::create("entity:{$entity_type_id}")
      ->setLabel($entity_type
      ->getLabel())
      ->setRequired(TRUE)
      ->setDescription(t('The @entity_type for which to create a path alias.', array(
      '@entity_type' => $entity_type
        ->getLowercaseLabel(),
    ))),
    'alias' => ContextDefinition::create('string')
      ->setLabel(t('Path alias'))
      ->setRequired(TRUE)
      ->setDescription(t("Specify an alternative path by which the content can be accessed. For example, 'about' for an about page. Use a relative path and do not add a trailing slash.")),
  ),
  'provides' => array(),
) + $base_plugin_definition;
$derivatives["entity:{$entity_type_id}"] = [
  'label' => t('Create @entity_type path alias', [
    '@entity_type' => $entity_type
      ->getLowercaseLabel(),
  ]),
  'category' => t('Path'),
  'entity_type_id' => $entity_type_id,
  'context' => [
    'entity' => ContextDefinition::create("entity:{$entity_type_id}")
      ->setLabel($entity_type
      ->getLabel())
      ->setRequired(TRUE)
      ->setDescription(t('The @entity_type for which to create a path alias.', [
      '@entity_type' => $entity_type
        ->getLowercaseLabel(),
    ])),
    'alias' => ContextDefinition::create('string')
      ->setLabel(t('Path alias'))
      ->setRequired(TRUE)
      ->setDescription(t("Specify an alternative path by which the content can be accessed. For example, 'about' for an about page. Use a relative path and do not add a trailing slash.")),
  ],
  'provides' => [],
] + $base_plugin_definition;
$test = array(
  'columns' => $columns,
  'indexes' => array(),
  'foreign keys' => array(
    'format' => array(
      'table' => 'filter_format',
      'columns' => array(
        'format' => 'format',
      ),
    ),
    'file_managed' => array(
      'table' => 'file_managed',
      'columns' => array(
        'fid' => 'carousel_image',
      ),
    ),
  ),
);

// Arrays by reference in arrays.
$x = array(
  'foo',
);
$y = array(
  &$x,
);
$x = [
  'foo',
];
$y = [
  &$x,
];

// Multi-line function call with array and anonymous function.
multiline_call(Inspector::assertAllCallable([
  'strchr',
  [
    $x,
    'callMe',
  ],
  [
    'test',
    'callMeStatic',
  ],
  function () {
    return TRUE;
  },
]));
multiline_call(Inspector::assertAllCallable(array(
  'strchr',
  array(
    $x,
    'callMe',
  ),
  array(
    'test',
    'callMeStatic',
  ),
  function () {
    return TRUE;
  },
)));

// Nested array indentation with closures.
$options = array(
  'value' => array(
    'Callback' => array(
      'callback' => function ($value, ExecutionContextInterface $context) {
        TheaterItem::theaterValidate($value, $context);
      },
    ),
  ),
);
$options = array(
  'value' => [
    'Callback' => array(
      'callback' => function ($value, ExecutionContextInterface $context) {
        TheaterItem::theaterValidate($value, $context);
      },
    ),
  ],
);
$test = array(
  'original' => '$no_index_value_scalar = TRUE;',
  'settings' => array(
    'no_index_value_foo' => array(
      'foo' => array(
        'value' => (object) array(
          'value' => NULL,
          'required' => TRUE,
          'comment' => 'comment',
        ),
      ),
    ),
  ),
  'expected' => <<<'EXPECTED'
$no_index_value_scalar = TRUE;
$no_index_value_foo['foo']['value'] = NULL; // comment
EXPECTED
,
);
$test = array(
  'original' => '$no_index_value_scalar = TRUE;',
  'settings' => array(
    'no_index_value_foo' => array(
      'foo' => array(
        'value' => (object) array(
          'value' => NULL,
          'required' => TRUE,
          'comment' => 'comment',
        ),
      ),
    ),
  ),
  'expected' => <<<EXPECTED
abc
def
EXPECTED
,
);

// Item assignment operators must be prefixed and followed by a space.
$a = array(
  'one' => '1',
  'two' => '2',
);
foreach ($a as $key => $value) {
}

// If conditions have a space before and after the condition parenthesis.
if (TRUE || TRUE) {
  $i;
}
elseif (TRUE && TRUE) {
  $i;
}
else {
  $i;
}
while (1 == 1) {
  if (TRUE || TRUE) {
    $i;
  }
  else {
    $i;
  }
}
switch ($condition) {
  case 1:
    $i;
    break;
  case 2:
    $i;
    break;

  // Blank line after the case statement is allowed.
  case 3:
    $i;
    break;
  default:
    $i;
}

// Empty case statements are allowed.
switch ($code) {
  case 200:
  case 304:
    break;
  case 301:
  case 302:
  case 307:
    call_function();
    break;
  default:
    $result->error = $status_message;
}

/**
 * Allowed switch() statement in a function without breaks.
 */
function foo() {
  switch ($x) {
    case 1:
      return 5;
    case 2:
      return 6;
    case 3:
      return array(
        'whiz',
        'bang',
      );
    case 4:
      return helper_func('whiz', 'bang');
    default:
      throw new Exception();
  }
}
do {
  $i;
} while ($condition);

/**
 * Short description.
 *
 * We use doxygen style comments.
 * What's sad because eclipse PDT and
 * PEAR CodeSniffer base on phpDoc comment style.
 * Makes working with drupal not easier :|
 *
 * @param string $field1
 *   Doxygen style comments.
 * @param int $field2
 *   Doxygen style comments.
 * @param bool $field3
 *   Doxygen style comments.
 * @param bool $field4
 *   Don't check for & in docblock of referenced variable.
 *
 * @return array
 *   Doxygen style comments.
 *
 * @see example_reference()
 * @see Example::exampleMethod()
 * @see https://www.drupal.org
 * @see http://example.com/see/documentation/is/allowed/to/exceed/eighty/characters
 */
function foo_bar($field1, $field2, $field3 = NULL, &$field4 = NULL) {
  $system["description"] = t("This module inserts funny text into posts randomly.");
  return $system[$field];
}

// Function call.
$var = foo($i, $i, $i);

// Multiline function call.
$var = foo($i, $i, $i);

// Multiline function call with array.
$var = foo(array(
  $i,
  $i,
  $i,
), $i, $i);

// Multiline function call with only one array.
$var = foo(array(
  $i,
  $i,
  $i,
));

/**
 * Class declaration.
 *
 * Classes can have a multiline comment.
 */
class Bar {

  /**
   * Private properties have no prefix.
   *
   * @var int
   */
  private $secret = 1;

  /**
   * Protected properties also don't have a prefix.
   *
   * @var int
   */
  protected $foo = 1;

  /**
   * Longer properties use camelCase naming.
   *
   * @var int
   */
  public $barProperty = 1;

  /**
   * Public static variables use camelCase, too.
   *
   * @var string
   */
  public static $basePath = NULL;

  /**
   * {@inheritdoc}
   */
  protected $modules = [
    'node',
    'user',
  ];

  /**
   * Enter description here ...
   */
  public function foo() {
  }

  /**
   * Enter description here ...
   */
  protected function barMethod() {
  }

  /**
   * Test the ++ and -- operator.
   */
  public function incDecTest() {
    $this->foo++;
    $this->foo--;
    --$this->foo;
    ++$this->foo;
  }

  /**
   * It is allowed to leave out param docs on methods.
   */
  public function noParamDocs($a, $b) {
  }

  /**
   * Param comments with references are found correctly.
   *
   * @param string $a
   *   Parameter one.
   * @param array $b
   *   Parameter two.
   */
  public function test($a, array &$b) {
  }

}

/**
 * Enter description here ...
 */
function _private_foo() {
}

// When calling class constructors with no arguments, always include
// parentheses.
$bar = new Bar();
$bar = new Bar($arg1, $arg2);
$bar = 'Bar';
$foo = new $bar();
$foo = new $bar($i, $i);

// Static class variables use camelCase.
Bar::$basePath = '/foo';

// Concatenation - there has to be a space.
$i . "test";
$i . 'test';
$i . $i;
$i . NULL;

/**
 * It is allowed to have the closing "}" on the same line if the class is empty.
 */
class MyException extends Exception {

}

/**
 * Nice alignment is allowed for assignments.
 */
class MyExampleLog {
  const INFO = 0;
  const WARNING = 1;
  const ERROR = 2;
  const EMERGENCY = 3;

  /**
   * Empty method implementation is allowed.
   */
  public function emptyMethod() {
  }

  /**
   * Protected functions are allowed.
   */
  protected function protectedTest() {
  }

}

/**
 * Nice allignment in functions.
 */
function test_test2() {
  $a = 5;
  $aa = 6;
  $aaa = 7;
}

/**
 * Example of chained method invocations in a function.
 */
function test3() {

  // Uses the Rules API as example.
  $rule = rule();
  $rule
    ->condition('rules_test_condition_true')
    ->condition('rules_test_condition_true')
    ->condition(rules_or()
    ->condition(rules_condition('rules_test_condition_true')
    ->negate())
    ->condition('rules_test_condition_false')
    ->condition(rules_and()
    ->condition('rules_test_condition_false')
    ->condition('rules_test_condition_true')
    ->negate()));
}

// Test usages of t().
t('special character: \\"');
t("special character: \\'");

// Escaping is allowed here because we make use of the other quote type, too.
t('Link to Drupal\'s <a href="@url">admin pages</a>.', array(
  '@url' => url('admin'),
));

// Test inline comment style.
// Comment one.
t('x');

// Comment two.
// @todo this is valid!
t('x');

// Goes on?
t('x');

/* Longer comment
 * bla bla
 * end!
 */
t('x');

// @see http://example.com/with/a/very/long/link/that/is/longer/than/80/characters
t('x');

// http://example.com/with/a/very/long/link/that/is/longer/than/80/characters/really
t('x');

// @see my_function()
t('x');

// Some text here, then a reference.
// @see \Drupal\rules\Entity\ReactionRuleStorage
t('x');

// t() refers to a function name and should not be capitalized.
t('x');

// rules_admin is a fancy machine name word with underscores and should not be
// capitalized and ignored.
t('x');

// {} this comment start should not be flagged.
t('x');

// Some code examples in inline comments:
// @code
//   function mymodule_menu() {
//     $items['abc/def'] = array(
//       'page callback' => 'mymodule_abc_view',
//     );
//     return $items;
//   }
// @endcode
// @todo A long description what is left to be done. Exceeds the first line and
//   is indented on the second line.
// Now follows a list:
// - item 1
//   additional description line.
// - item 2
// - item 3 comes with a sub list:
//   - sub item 1
//   - sub item 2
//     description of sub item 2.
// List is closed, normal indentation here. Now comes a paragraph empty line.
//
// And here continues the long comment.
// Now some UTF-8 characters that do not exceed 80 characters.
// Hà Nội là thủ đô, đồng thời là thành phố đứng đầu Việt Nam về diện tích tự.
//
// Further information:
// - @link https://api.drupal.org/api/drupal/groups/8 All topics @endlink
// - @link https://www.drupal.org/project/examples Examples project (sample modules) @endlink
// - @link https://www.drupal.org/list-changes API change notices @endlink
// - @link https://www.drupal.org/developing/api/8 Drupal 8 API longer references @endlink
t('x');

// People want to pretty-format their numbered lists, do not throw an error for
// this:
// 1. A link has the current path in its 'data-drupal-link-system-path'
//    attribute.
// 2. We are on the front page and a link has the special '<front>' value in
//    its 'data-drupal-link-system-path' attribute.
t('x');

// Concatenating some symbols is fine.
$x = '(' . t('Test') . ')';
$x = '[' . t('Test') . ']';
$x = '- ' . t('Test') . ' -';
$x = '<' . t('Test') . '>';
$x = '«' . t('Test') . '»';
$x = "\n" . t('Test') . "\n";

/**
 * Doc block with some code tags.
 *
 * Some description and here comes the code:
 * @code
 *   $options = drupal_parse_url($_GET['destination']);
 *   $my_url = url($options['path'], $options);
 *   $my_link = l('Example link', $options['path'], $options);
 * @endcode
 *
 * Some more description here. And now the parameters.
 *
 * @param int $x
 *   Parameter comment here.
 */
function test1($x) {
}

/**
 * Variable amount of parameters is allowed with the "..." notation.
 *
 * Example:
 * @code
 *   test_invoke_all('node_view', $node, $view_mode);
 * @endcode
 *
 * @param string $hook
 *   The name of the hook to invoke.
 * @param ...
 *   Arguments to pass to the hook.
 */
function test_invoke_all($hook) {
}

// Test string concatenation.
$x = 'This string is very long and thus it can and should be concatenated.' . 'Othverwise the string will be very hard to maintain and or read';
$x = 'This string should be concatenated. Even if it is just a little bit ' . 'longer';
$x = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 . 'This is initially ' . 'short but since it has a lot of code before the real text it can be ' . 'concatenated';

// Requiring files conditionally is allowed.
if ($a == TRUE) {
  require_once 'good.tpl.php';
}

/**
 * This is not an implementation of hook_foobar().
 */
function hook_foobar() {
}

/**
 * Implements hook_foo().
 *
 * @link http://example.com/long-link-here-whatever Some long documentation link @endlink
 */
function mymodule_foo() {
}

/**
 * Implements hook_foo_BAR_ID_bar() for some_type_bar().
 */
function mymodule_foo_some_type_bar() {
}

/**
 * Implements hook_foo_bar() for foo_bar.tpl.php.
 */
function mymodule_foo_bar_phptemplate() {
}

/**
 * Implements hook_foo_bar() for foo-bar.html.twig.
 */
function mymodule_foo_bar_twig() {
}

/**
 * Implements drush_hook_foo_bar().
 */
function drush_mymodule_foo_bar() {
}

/**
 * Implements hook_foo_bar() for blocks.
 */
function mymodule_foo_bar_block() {
}

/**
 * Not documenting all parameters is allowed.
 *
 * @param Node $node
 *   The loaded node entity that we will use to do whatever.
 */
function mymodule_form_callback($form, &$form_state, Node $node) {
}
$x = 'Some markup text<br />';

// Inline if statements with ?: are allowed.
$x = $y == $z ? 23 : 42;

// Standard watchdog message.
watchdog('mymodule', 'Log message here.');

// For assigning by reference it is allowed that there is no space after the
// "=" oeprator.
$batch =& batch_get();

// Security issue: https://www.drupal.org/node/750148
preg_match('/.+/i', 'subject');
preg_match('/.+/imsuxADSUXJ', 'subject');
preg_filter('/.+/i', 'replacement', 'subject');
preg_replace('/.+/i', 'replacement', 'subject');

// Use a not so common delimiter.
preg_match('@.+@i', 'subject');
preg_match('@.+@imsuxADSUXJ', 'subject');
preg_filter('@.+@i', 'replacement', 'subject');
preg_replace('@.+@i', 'replacement', 'subject');
preg_match("/test(\\d+)/is", 'subject');

/**
 * Interfaces must have a comment block.
 */
interface MyWellNamedInterface {

}

// Correctly formed try/catch block.
try {
  do_something();
} catch (Exception $e) {
  scream();
}
$result = $x ?: FALSE;

/**
 * All classes need to have a docblock.
 */
class Foo implements FooInterface {

  /**
   * {@inheritdoc}
   */
  public function test() {

    /** @var \Drupal\node\NodeInterface $node */
    $node = $this->entity;

    /** @var \Drupal\node\NodeInterface[] $nodes */
    $nodes = foo();

    /** @var \Drupal\node\NodeInterface|\PHPUnit_Framework_MockObject_MockObject $node_mock */
    $node_mock = mock_node();

    /** @var \Drupal\SomeInterface4You $thing */
    $thing = thing();

    /** @var \Drupal\SomeInterface4You $test2 */
    $test2 = test2();
    return $node;
  }

  /**
   * {@inheritdoc}
   *
   * Some additional documentation here.
   */
  public function test2() {
  }

  /**
   * Return docs are allowed to use $this.
   *
   * @return $this
   *   This object for chaining method calls.
   */
  public function test3() {
    return $this;
  }

  /**
   * Returns the string representatuion of this object.
   */
  public function __toString() {
    return 'foo';
  }

  /**
   * Omitting the comment when returning $this is allowed.
   *
   * @return $this
   */
  public function test4() {
    return $this;
  }

  /**
   * Omitting the comment when returning static is allowed.
   *
   * @return static
   */
  public function test41() {
    return new static();
  }

  /**
   * Loads multiple string objects.
   *
   * @param array $conditions
   *   Any of the conditions used by dbStringSelect().
   * @param array $options
   *   Any of the options used by dbStringSelect().
   * @param string $class
   *   Class name to use for fetching returned objects.
   *
   * @return \Drupal\locale\StringInterface[]
   *   Array of objects of the class requested.
   */
  protected function dbStringLoad(array $conditions, array $options, $class) {
    $strings = array();
    $result = $this
      ->dbStringSelect($conditions, $options)
      ->execute();
    foreach ($result as $item) {

      /** @var \Drupal\locale\StringInterface $string */
      $string = new $class($item);
      $string
        ->setStorage($this);
      $strings[] = $string;
    }
    return $strings;
  }

  /**
   * Short array syntax is allowed.
   */
  public function getConfiguration() {
    return [
      'id' => $this
        ->getPluginId(),
    ] + $this->configuration;
  }

  /**
   * Not documenting a "throws" tag is allowed.
   *
   * This should not fail for errors with underscores in names as well.
   * The second version of this test with error name with underscores
   * is added below.
   *
   * @throws Exception
   */
  public function test6() {
    throw new Exception();
  }

  /**
   * Repeat of above test with error name with underscores.
   *
   * @throws \Twig_Error_Syntax
   */
  public function test7() {
    throw new Exception();
  }

}
t('Some long mulit-line 
  text is weird, but allowed.');

// Anonymous functions should not throw indentation errors here.
$test = array_walk($fragments, function (&$item) {
  if (strpos($item, '%') === 0) {
    $item = '%';
  }
});

/**
 * Doc tags are allowed to exceed 80 characters.
 *
 * @param \Drupal\very_long_module_name_i_am_inventing_here_trololololo\SuperManager $x
 *   The super duper manager comment goes here.
 * @param \Traversable $y
 *   Some PHP core class/interface.
 */
function test2(SuperManager $x, \Traversable $y) {
}

/**
 * Test comment.
 *
 * @throws \Drupal\locale\StringStorageException
 *   The exception description is here and should not cause an error.
 */
function test4() {
}

/**
 * Test chained method indentation which should not throw errors.
 */
function test5() {
  $mock
    ->expects($this
    ->any())
    ->method('findTranslation')
    ->will($this
    ->returnCallback(function ($argument) use ($translations) {
    if (isset($translations[$argument['language']][$argument['source']])) {
      return (object) array(
        'translation' => $translations[$argument['language']][$argument['source']],
      );
    }
    return TRUE;
  }));
}

/**
 * Array syntax with brackets is allowed in type hints.
 *
 * @param string[] $names
 *   An indexed array of names.
 */
function test6(array $names) {
}
list(, , $bundle) = entity_extract_ids('node', $entity);
l("<i class='icon icon-industrial-building'></i>", 'node/add/job', array(
  'attributes' => array(
    'title' => t('add job'),
  ),
  'html' => TRUE,
));

/**
 * Some short description.
 *
 * @todo TODOs are allowed here.
 *
 * @param string $x
 *   Some parameter.
 */
function test7($x) {
}

/**
 * @coversDefaultClass \Drupal\rules\Plugin\Condition\ListContains
 * @group rules_conditions
 */
class ListContainsTest extends RulesIntegrationTestBase {

}
$x = 'Some markup text with allowed HTML5 <br> tag';

/**
 * Provides a 'Delete any path alias' action.
 *
 * @todo: Add access callback information from Drupal 7.
 * @todo: Add group information from Drupal 7.
 *
 * @Action(
 *   id = "rules_path_alias_delete",
 *   label = @Translation("Delete any path alias"),
 *   context = {
 *     "alias" = @ContextDefinition("string",
 *       label = @Translation("Existing system path alias"),
 *       description = @Translation("Specifies the existing path alias you wish to delete, for example 'about/team'. Use a relative path and do not add a trailing slash.")
 *     )
 *   }
 * )
 */
class AliasDelete extends RulesActionBase implements ContainerFactoryPluginInterface {

}

/**
 * Some comment with exclamation mark!
 *
 * And the long description!
 *
 * @param int $x
 *   Exclamation mark allowed!
 *
 * @throws MyException
 *   Exclamation mark allowed!
 */
function test8($x) {
}

/**
 * Make sure that link tags are allowed in long descriptions.
 *
 * For forcing it to a boolean TRUE or FALSE please use
 * @link MenuItem::forceAccessCallbackTRUE @endlink() or
 * @link MenuItem::forceAccessCallbackFALSE @endlink() as you see fit.
 */
function test9() {
}

/**
 * Link tags in the long description before param tags are allowed.
 *
 * Visit also:
 * @link https://www.drupal.org/node/323101 Strings at well-known places: built-in menus, .. @endlink.
 *
 * @section more_info Further information
 *
 * - @link https://api.drupal.org/api/drupal/groups/8 All topics @endlink
 * - @link https://www.drupal.org/project/examples Examples project (sample modules) @endlink
 * - @link https://www.drupal.org/list-changes API change notices @endlink
 * - @link https://www.drupal.org/developing/api/8 Drupal 8 API longer references @endlink
 *
 * @param string $title
 *   The untranslated title of the menu item.
 */
function test10($title) {
}

/**
 * Some description.
 *
 * @todo Here is a very long link that exceeds 80 charaters on the next line:
 *   http://example.com/test/long/link/with/stuff/here/making/it/even/longer/now/so/that/it/shows
 */
function test11() {
}

/**
 * Parameter docs with a long nested list.
 *
 * @param string $a
 *   Lists are usually preceded by a line ending in a colon:
 *   - Item in the list.
 *   - Another item.
 *     - key: Sub-list with keys, first item.
 *     - key2: (optional) Second item with a key.
 *   - Back to the outer list. Sometimes list items are quite long, in which
 *     case you can wrap the text like this.
 *   - Last item in the outer list.
 *   Text that is outside of the list continues here.
 */
function test13($a) {
}

/**
 * Using an alias type hint but the fully qualified name in the docs.
 *
 * @param \Drupal\some_module\ExampleClass $a
 *   Example parameter.
 */
function test14(AliasedExampleClass $a) {
}

/**
 * Example annotation that exceeds 80 characters several times, but is valid.
 *
 * @ConfigEntityType(
 *   id = "rules_reaction_rule",
 *   label = @Translation("Reaction Rule"),
 *   handlers = {
 *     "storage" = "Drupal\rules\Entity\ReactionRuleStorage",
 *     "list_builder" = "Drupal\rules\Entity\Controller\RulesReactionListBuilder",
 *     "form" = {
 *        "add" = "\Drupal\rules\Entity\ReactionRuleAddForm",
 *        "edit" = "\Drupal\rules\Entity\ReactionRuleEditForm",
 *        "delete" = "\Drupal\Core\Entity\EntityDeleteForm"
 *      }
 *   },
 *   admin_permission = "administer rules",
 *   config_prefix = "reaction",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "status" = "status"
 *   },
 *   config_export = {
 *     "id",
 *     "label",
 *     "event",
 *     "module",
 *     "description",
 *     "tag",
 *     "core",
 *     "expression_id",
 *     "configuration",
 *   },
 *   links = {
 *     "collection" = "/admin/config/workflow/rules",
 *     "edit-form" = "/admin/config/workflow/rules/reactions/edit/{rules_reaction_rule}",
 *     "delete-form" = "/admin/config/workflow/rules/reactions/delete/{rules_reaction_rule}"
 *   }
 * )
 */
class ReactionRule extends ConfigEntityBase {

  /**
   * Config entities are allowed to have property names with underscores.
   *
   * @var string
   */
  protected $expression_id;

}

/**
 * Underscores are allowed in properties of config entity classes.
 */
class NodeType extends ConfigEntityBundleBase {

  /**
   * Default value of the 'Create new revision' checkbox of this node type.
   *
   * @var bool
   */
  protected $new_revision = TRUE;

}

/**
 * Test class.
 */
class OperatorTest {
  protected static $seenIds;

  /**
   * Test method.
   */
  public function test() {
    $id = $id . '--' . ++static::$seenIds[$id];
    return $id;
  }

}

// Namespaced function call is allowed because PHP 5.5 and lower do not support
// use statements for functions.
$default_config = [
  'verify' => TRUE,
  'timeout' => 30,
  'headers' => [
    'User-Agent' => 'Drupal/' . \Drupal::VERSION . ' (+https://www.drupal.org/) ' . \GuzzleHttp\default_user_agent(),
  ],
  'handler' => $stack,
];

// camelCase and snake_case variables are allowed.
$snake_case = 1;
$camelCase = 1;

// It should be possible to use a parenthesis in a comment without having the
// InlineCommentSniff complain. (About the the last character of the line.)
$comment = 'fine';

/**
 * Comments ending with parentheses.
 *
 * It should be possible to use a parenthesis in a comment without having the
 * DocCommentSniff complain. (About the the last character of the line.)
 *
 * @param string $foo
 *   A parameter comment is also allowed to end (with parenthesis)
 */
function test15($foo) {
}

/**
 * Variable arguments with type declared.
 *
 * Variable arguments with type declared should not result in an error
 * when no named argument is given in the param definition.
 *
 * @param string ...
 *   Variable number of string arguments.
 */
function test16() {
}
$access = $account
  ->hasPermission('translate configuration') && $mapper
  ->hasSchema() && $mapper
  ->hasTranslatable() && $source_language_access;

/**
 * Return with optional null and function with some void returns.
 *
 * When a function has an optional null as a return value then it should not
 * result in an error when there is a void return in the function.
 *
 * @param string $arg
 *   An argument.
 *
 * @return int|null
 *   Return has an optional null.
 */
function test17($arg) {
  if ($arg === 1) {
    return;
  }
  return 1;
}

/**
 * Ignore indentation of multi-line function declarations.
 */
function test18(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, CacheTagsInvalidatorInterface $cache_invalidator, ModuleHandlerInterface $module_handler, EntityFieldManagerInterface $entity_field_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
  return 0;
}

/**
 * Object operator indentation is fine like this.
 */
function is_table_empty($table_name, $database) {
  return !$database
    ->schema()
    ->tableExists($table_name) || !$database
    ->select($table_name)
    ->countQuery()
    ->range(0, 1)
    ->execute()
    ->fetchField();
}

/**
 * Another example of correct object operator indentation.
 */
function test19($key, $value, $connection) {
  $connection
    ->merge('foo')
    ->keys(array(
    'name' => $key,
    'collection' => 'collection',
  ))
    ->fields(array(
    'value' => $value,
  ))
    ->execute();
}

// Correct object operator indentation.
ContentLanguageSettings::create([
  'target_entity_type_id' => 'entity_test',
  'target_bundle' => 'some_bundle',
])
  ->setLanguageAlterable(TRUE)
  ->setDefaultLangcode('authors_default')
  ->save();

/**
 * Another example of correct operator indentation.
 */
function test20($link, $parents, $connection) {
  return $connection
    ->insert('book')
    ->fields(array(
    'nid' => $link['nid'],
    'bid' => $link['bid'],
    'pid' => $link['pid'],
    'weight' => $link['weight'],
  ) + $parents)
    ->execute();
}

/**
 * PHP 7 type hints are allowed.
 *
 * @param string $a
 *   Parameter one.
 * @param int $b
 *   Parameter two.
 */
function test21(string $a, int $b) {
}

/**
 * Implements hook_very_long_module_name_neverending_hook_name_that_is_a_long_cat_alter().
 */
function mymodule_very_long_module_name_neverending_hook_name_that_is_a_long_cat_alter() {
}

/**
 * @coversDefaultClass \Drupal\mymodule\Something
 */
class MyTest extends UnitTestBase {

  /**
   * @covers ::foo
   */
  public function testFoo() {
  }

}

/**
 * Numbers in types are allowed.
 *
 * @param \Drupal\x123_module\MyInterface $a
 *   Parameter type with numbers in it.
 */
function test22(MyInterface $a) {
}

/**
 * Using PHP 7 return types is allowed.
 *
 * @return \Drupal\mymodule\TestReturnType
 *   What we return.
 */
function test23() : TestReturnType {
  return foo();
}

/**
 * Test class.
 */
class Test2 {

  /**
   * Using PHP 7 return type hints is fine.
   *
   * @return ValidatorInterface[]
   *   The validators.
   */
  public function getValidators() : array {
    return [
      new PublishedNodesValidator(),
      new MinimumNodesValidator($this->nrOfArticles),
      new AccessibleOnCurrentDomainValidator($this->sectionService),
    ];
  }

}

/**
 * Another test.
 */
class Test3 {

  /**
   * Parameters described by reference are OK.
   *
   * @param array &$form
   *   The form array.
   * @param Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   A renderable array.
   */
  public function removeQueueItem(array &$form, FormStateInterface $form_state) {
    $trigger = $form_state
      ->getTriggeringElement();
    $i = $trigger['#parents'][1];
    $queues = $form_state
      ->getValue('watch_queues', []);
    $queues[$i]['to_remove'] = 1;
    $form_state
      ->setValue('watch_queues', $queues);
    $this
      ->rebuild($form_state, $form);
    drupal_set_message($this
      ->t('Item will be removed permanently when configuration is saved.'));
    return StatusMessages::renderMessages(NULL);
  }

  /**
   * Parameters described by reference are OK.
   *
   * @param Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param array &$old_form
   *   The old form build.
   *
   * @return array
   *   The newly built form.
   */
  protected function rebuild(FormStateInterface $form_state, array &$old_form) {
    $form_state
      ->setRebuild();
    $form = $this->formBuilder
      ->rebuildForm($this
      ->getFormId(), $form_state, $old_form);
    return $form;
  }

}

/**
 * Long annotation lines over 80 characters are ok.
 *
 * @WebformHandler(
 *   id = "email",
 *   label = @Translation("Email"),
 *   category = @Translation("Notification"),
 *   description = @Translation("Sends a webform submission via an email."),
 *   cardinality = \Drupal\webform\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\WebformHandlerInterface::RESULTS_PROCESSED,
 * )
 */
class EmailWebformHandler extends WebformHandlerBase implements WebformHandlerMessageInterface {

}

Functions

Namesort descending Description
drush_mymodule_foo_bar Implements drush_hook_foo_bar().
foo Allowed switch() statement in a function without breaks.
foo_bar Short description.
hook_foobar This is not an implementation of hook_foobar().
is_table_empty Object operator indentation is fine like this.
mymodule_foo Implements hook_foo().
mymodule_foo_bar_block Implements hook_foo_bar() for blocks.
mymodule_foo_bar_phptemplate Implements hook_foo_bar() for foo_bar.tpl.php.
mymodule_foo_bar_twig Implements hook_foo_bar() for foo-bar.html.twig.
mymodule_foo_some_type_bar Implements hook_foo_BAR_ID_bar() for some_type_bar().
mymodule_form_callback Not documenting all parameters is allowed.
mymodule_very_long_module_name_neverending_hook_name_that_is_a_long_cat_alter Implements hook_very_long_module_name_neverending_hook_name_that_is_a_long_cat_alter().
test1 Doc block with some code tags.
test10 Link tags in the long description before param tags are allowed.
test11 Some description.
test13 Parameter docs with a long nested list.
test14 Using an alias type hint but the fully qualified name in the docs.
test15 Comments ending with parentheses.
test16 Variable arguments with type declared.
test17 Return with optional null and function with some void returns.
test18 Ignore indentation of multi-line function declarations.
test19 Another example of correct object operator indentation.
test2 Doc tags are allowed to exceed 80 characters.
test20 Another example of correct operator indentation.
test21 PHP 7 type hints are allowed.
test22 Numbers in types are allowed.
test23 Using PHP 7 return types is allowed.
test3 Example of chained method invocations in a function.
test4 Test comment.
test5 Test chained method indentation which should not throw errors.
test6 Array syntax with brackets is allowed in type hints.
test7 Some short description.
test8 Some comment with exclamation mark!
test9 Make sure that link tags are allowed in long descriptions.
test_invoke_all Variable amount of parameters is allowed with the "..." notation.
test_test2 Nice allignment in functions.
_private_foo Enter description here ...

Constants

Namesort descending Description
FOO_BAR Doxygen comment style is allowed before define() statements.

Globals

Namesort descending Description
$argc

Classes

Namesort descending Description
AliasDelete Provides a 'Delete any path alias' action.
Bar Class declaration.
EmailWebformHandler Long annotation lines over 80 characters are ok.
Foo All classes need to have a docblock.
ListContainsTest @coversDefaultClass \Drupal\rules\Plugin\Condition\ListContains @group rules_conditions
MyExampleLog Nice alignment is allowed for assignments.
MyException It is allowed to have the closing "}" on the same line if the class is empty.
MyTest @coversDefaultClass \Drupal\mymodule\Something
NodeType Underscores are allowed in properties of config entity classes.
OperatorTest Test class.
ReactionRule Example annotation that exceeds 80 characters several times, but is valid.
Test2 Test class.
Test3 Another test.

Interfaces

Namesort descending Description
MyWellNamedInterface Interfaces must have a comment block.