ai_upgrade_assistant-0.2.0-alpha2/src/Service/NodeVisitor/DeprecatedTraitVisitor.php
src/Service/NodeVisitor/DeprecatedTraitVisitor.php
<?php
namespace Drupal\ai_upgrade_assistant\Service\NodeVisitor;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
/**
* Node visitor that detects deprecated trait usage.
*/
class DeprecatedTraitVisitor extends NodeVisitorAbstract {
/**
* List of findings.
*
* @var array
*/
protected $findings = [];
/**
* List of deprecated traits and their replacements.
*
* @var array
*/
protected $deprecatedTraits = [
// Core traits
'Drupal\Core\Entity\EntityNG' => [
'replacement' => 'Drupal\Core\Entity\RevisionableContentEntityBase',
'version' => '8.0.0',
'critical' => true,
],
'Drupal\Core\Config\Entity\ThirdPartySettingsTrait' => [
'replacement' => 'Drupal\Core\Config\Entity\ThirdPartySettingsInterface',
'version' => '10.0.0',
'critical' => false,
'note' => 'Consider implementing the interface directly',
],
// Form traits
'Drupal\Core\Form\FormBuilderTrait' => [
'replacement' => 'Drupal\Core\Form\FormBuilderInterface',
'version' => '10.0.0',
'critical' => false,
'note' => 'Use dependency injection instead',
],
// Entity traits
'Drupal\Core\Entity\EntityManagerTrait' => [
'replacement' => 'Drupal\Core\Entity\EntityTypeManagerInterface',
'version' => '8.0.0',
'critical' => true,
'note' => 'EntityManager service is deprecated',
],
'Drupal\Core\Entity\EntityTypeBundleInfoTrait' => [
'replacement' => 'Drupal\Core\Entity\EntityTypeBundleInfoInterface',
'version' => '10.0.0',
'critical' => false,
'note' => 'Use dependency injection instead',
],
// Plugin traits
'Drupal\Core\Plugin\PluginFormFactoryTrait' => [
'replacement' => 'Drupal\Core\Plugin\PluginFormFactoryInterface',
'version' => '10.0.0',
'critical' => false,
'note' => 'Use dependency injection instead',
],
// Cache traits
'Drupal\Core\Cache\CacheBackendTrait' => [
'replacement' => 'Drupal\Core\Cache\CacheBackendInterface',
'version' => '10.0.0',
'critical' => false,
'note' => 'Use dependency injection instead',
],
// Database traits
'Drupal\Core\Database\Connection\ConnectionTrait' => [
'replacement' => 'Drupal\Core\Database\Connection',
'version' => '10.0.0',
'critical' => false,
'note' => 'Extend Connection class directly',
],
];
/**
* List of traits requiring special attention in Drupal 11.
*
* @var array
*/
protected $drupal11Traits = [
'Drupal\Core\Entity\RevisionableInterface' => [
'changes' => [
'New methods for revision metadata',
'Enhanced revision log handling',
],
'example' => 'implement getRevisionLogMessage() method',
],
'Drupal\Core\Config\Entity\ConfigEntityInterface' => [
'changes' => [
'New validation methods',
'Enhanced dependency handling',
],
'example' => 'implement calculateDependencies() method',
],
];
/**
* {@inheritdoc}
*/
public function enterNode(Node $node) {
if ($node instanceof Node\Stmt\TraitUse) {
foreach ($node->traits as $trait) {
$traitName = $trait->toString();
$finding = [
'type' => 'trait_use',
'trait' => $traitName,
'line' => $node->getLine(),
'file' => $node->getAttribute('file'),
];
// Check for deprecated traits
if (isset($this->deprecatedTraits[$traitName])) {
$finding['deprecated'] = true;
$finding['replacement'] = $this->deprecatedTraits[$traitName]['replacement'];
$finding['version'] = $this->deprecatedTraits[$traitName]['version'];
$finding['critical'] = $this->deprecatedTraits[$traitName]['critical'];
if (isset($this->deprecatedTraits[$traitName]['note'])) {
$finding['note'] = $this->deprecatedTraits[$traitName]['note'];
}
}
// Check for Drupal 11 changes
if (isset($this->drupal11Traits[$traitName])) {
$finding['drupal11_changes'] = $this->drupal11Traits[$traitName];
}
// Check for trait adaptations
if ($node->adaptations) {
$finding['has_adaptations'] = true;
$adaptations = [];
foreach ($node->adaptations as $adaptation) {
if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) {
$adaptations[] = [
'type' => 'alias',
'method' => $adaptation->method->toString(),
'alias' => $adaptation->newName ? $adaptation->newName->toString() : null,
'visibility' => $adaptation->newModifier,
];
}
elseif ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Precedence) {
$adaptations[] = [
'type' => 'precedence',
'method' => $adaptation->method->toString(),
'insteadof' => array_map(function($trait) {
return $trait->toString();
}, $adaptation->insteadof),
];
}
}
$finding['adaptations'] = $adaptations;
}
$this->findings[] = $finding;
}
}
}
/**
* Gets the findings.
*
* @return array
* Array of findings.
*/
public function getFindings() {
return $this->findings;
}
/**
* Resets the findings.
*/
public function reset() {
$this->findings = [];
}
}
