OSInet /
qa
| 1 | <?php |
||||
| 2 | |||||
| 3 | declare(strict_types = 1); |
||||
| 4 | |||||
| 5 | namespace Drupal\qa\Plugin\QaCheck\References; |
||||
| 6 | |||||
| 7 | use Drupal\Core\Database\Connection; |
||||
| 8 | use Drupal\qa\Pass; |
||||
| 9 | use Drupal\qa\Plugin\QaCheckBase; |
||||
| 10 | use Drupal\qa\Plugin\QaCheckInterface; |
||||
| 11 | use Drupal\qa\Result; |
||||
| 12 | use Symfony\Component\DependencyInjection\ContainerInterface; |
||||
| 13 | |||||
| 14 | /** |
||||
| 15 | * TaxonomyIndex checks for broken taxonomy_index references. |
||||
| 16 | * |
||||
| 17 | * It is not a generic reference integrity check, just a consistency chec for |
||||
| 18 | * the taxonomy_index table. |
||||
| 19 | * |
||||
| 20 | * @QaCheck( |
||||
| 21 | * id = "references.taxonomy_index", |
||||
| 22 | * label = @Translation("Taxonomy index"), |
||||
| 23 | * details = @Translation("This check finds references in the taxonomy_index. These have to be repaired, as they can cause incorrect content displays."), |
||||
| 24 | * usesBatch = false, |
||||
| 25 | * steps = 1, |
||||
| 26 | * ) |
||||
| 27 | */ |
||||
| 28 | class TaxonomyIndex extends QaCheckBase implements QaCheckInterface { |
||||
| 29 | |||||
| 30 | const NAME = "references." . self::TABLE; |
||||
| 31 | |||||
| 32 | const TABLE = 'taxonomy_index'; |
||||
| 33 | |||||
| 34 | const KEY_NODES = 'missingNodes'; |
||||
| 35 | const KEY_TERMS = 'missingTerms'; |
||||
| 36 | |||||
| 37 | /** |
||||
| 38 | * The database service. |
||||
| 39 | * |
||||
| 40 | * @var \Drupal\Core\Database\Connection |
||||
| 41 | */ |
||||
| 42 | protected $db; |
||||
| 43 | |||||
| 44 | /** |
||||
| 45 | * ContentOrphans constructor. |
||||
| 46 | * |
||||
| 47 | * @param array $configuration |
||||
| 48 | * The plugin configuration. |
||||
| 49 | * @param string $id |
||||
| 50 | * The plugin ID. |
||||
| 51 | * @param array $definition |
||||
| 52 | * The plugin definition. |
||||
| 53 | * @param \Drupal\qa\Plugin\QaCheck\References\Connection $db |
||||
|
0 ignored issues
–
show
|
|||||
| 54 | * The database service. |
||||
| 55 | */ |
||||
| 56 | public function __construct( |
||||
| 57 | array $configuration, |
||||
| 58 | string $id, |
||||
| 59 | array $definition, |
||||
| 60 | Connection $db |
||||
| 61 | ) { |
||||
| 62 | parent::__construct($configuration, $id, $definition); |
||||
| 63 | $this->db = $db; |
||||
| 64 | } |
||||
| 65 | |||||
| 66 | /** |
||||
| 67 | * {@inheritdoc} |
||||
| 68 | */ |
||||
| 69 | public static function create( |
||||
| 70 | ContainerInterface $container, |
||||
| 71 | array $configuration, |
||||
| 72 | $id, |
||||
| 73 | $definition |
||||
| 74 | ) { |
||||
| 75 | $db = $container->get('database'); |
||||
| 76 | return new static($configuration, $id, $definition, $db); |
||||
|
0 ignored issues
–
show
It seems like
$db can also be of type null; however, parameter $db of Drupal\qa\Plugin\QaCheck...omyIndex::__construct() does only seem to accept Drupal\Core\Database\Connection, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 77 | } |
||||
| 78 | |||||
| 79 | /** |
||||
| 80 | * Locate {taxonomy_index} entries linking to a missing term or node. |
||||
| 81 | * |
||||
| 82 | * @return \Drupal\qa\Result |
||||
| 83 | * The check result. |
||||
| 84 | */ |
||||
| 85 | public function checkIndex(): Result { |
||||
| 86 | $sql = <<<SQL |
||||
| 87 | SELECT ti.tid AS indexTid,ti.nid AS indexNid, |
||||
| 88 | nfd.nid, |
||||
| 89 | tfd.tid |
||||
| 90 | FROM {taxonomy_index} ti |
||||
| 91 | LEFT JOIN {taxonomy_term_field_data} tfd ON ti.tid = tfd.tid |
||||
| 92 | LEFT JOIN {node_field_data} nfd ON ti.nid = nfd.nid |
||||
| 93 | WHERE tfd.tid IS NULL |
||||
| 94 | OR nfd.nid IS NULL |
||||
| 95 | SQL; |
||||
| 96 | // No node access: we are scanning the whole database with full privileges. |
||||
| 97 | $q = $this->db->query($sql); |
||||
| 98 | $missing = [ |
||||
| 99 | self::KEY_TERMS => [], |
||||
| 100 | self::KEY_NODES => [], |
||||
| 101 | ]; |
||||
| 102 | foreach ($q->fetchAll() as $o) { |
||||
| 103 | if (is_null($o->tid)) { |
||||
| 104 | $missing[self::KEY_TERMS][] = [ |
||||
| 105 | 'nid' => (int) $o->indexNid, |
||||
| 106 | 'missingTid' => (int) $o->indexTid, |
||||
| 107 | ]; |
||||
| 108 | } |
||||
| 109 | if (is_null($o->nid)) { |
||||
| 110 | $missing[self::KEY_NODES][] = [ |
||||
| 111 | 'tid' => (int) $o->indexTid, |
||||
| 112 | 'missingNid' => (int) $o->indexNid, |
||||
| 113 | ]; |
||||
| 114 | } |
||||
| 115 | } |
||||
| 116 | sort($missing[self::KEY_TERMS]); |
||||
| 117 | sort($missing[self::KEY_NODES]); |
||||
| 118 | if (empty($missing[self::KEY_TERMS])) { |
||||
| 119 | unset($missing[self::KEY_TERMS]); |
||||
| 120 | } |
||||
| 121 | if (empty($missing[self::KEY_NODES])) { |
||||
| 122 | unset($missing[self::KEY_NODES]); |
||||
| 123 | } |
||||
| 124 | return new Result(self::TABLE, empty($missing), $missing); |
||||
| 125 | } |
||||
| 126 | |||||
| 127 | /** |
||||
| 128 | * {@inheritdoc} |
||||
| 129 | */ |
||||
| 130 | public function run(): Pass { |
||||
| 131 | $pass = parent::run(); |
||||
| 132 | $pass->record($this->checkIndex()); |
||||
| 133 | $pass->life->end(); |
||||
| 134 | return $pass; |
||||
| 135 | } |
||||
| 136 | |||||
| 137 | } |
||||
| 138 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths