Skip to content

Commit

Permalink
Fix up makeEntitiesAvailableWithShortClassNames for php:cli (#6221)
Browse files Browse the repository at this point in the history
* Fix up makeEntitiesAvailableWithShortClassNames

* also add __construct changes

* Comment the new code

* Add bundle classes

* Add a usage example

* formatting
  • Loading branch information
chx authored Feb 7, 2025
1 parent b6df26b commit 1cac634
Showing 1 changed file with 36 additions and 13 deletions.
49 changes: 36 additions & 13 deletions src/Commands/core/CliCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
use Drupal\Core\Config\ConfigBase;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drush\Attributes as CLI;
Expand All @@ -34,7 +36,9 @@ final class CliCommands extends DrushCommands
const PHP = 'php:cli';

public function __construct(
protected EntityTypeManagerInterface $entityTypeManager
protected EntityTypeManagerInterface $entityTypeManager,
protected EntityTypeRepositoryInterface $entityTypeRepository,
protected EntityTypeBundleInfoInterface $entityTypeBundleInfo
) {
parent::__construct();
}
Expand All @@ -59,6 +63,7 @@ public function docs(): void
#[CLI\Option(name: 'cwd', description: 'A directory to change to before launching the shell. Default is the project root directory')]
#[CLI\Topics(topics: [self::DOCS_REPL])]
#[CLI\Usage(name: '$node = Node::load(1)', description: 'Entity classes are available without their namespace. For example, Node::load(1) works instead of Drupal\Node\entity\Node::load(1).')]
#[CLI\Usage(name: '$node = NodeArticle::load(1)', description: 'Entity bundles classes are also available without their namespace. For example, NodeArticle::load(1) works instead of Drupal\node_article\entity\NodeArticle::load(1).')]
#[CLI\Usage(name: '$paragraph = Paragraph::loadRevision(1)', description: 'Also, a loadRevision static method is made available for easier load of revisions.')]
#[CLI\Bootstrap(level: DrupalBootLevels::FULL)]
public function cli(array $options = ['version-history' => false, 'cwd' => self::REQ]): void
Expand Down Expand Up @@ -309,25 +314,43 @@ protected function getPhpKeywords(): array

public function makeEntitiesAvailableWithShortClassNames(): void
{
foreach ($this->entityTypeManager->getDefinitions() as $definition) {
$class = $definition->getClass();
$reflectionClass = new \ReflectionClass($class);
$parts = explode('\\', $class);
$end = end($parts);
// https://github.com/drush-ops/drush/pull/5729, https://github.com/drush-ops/drush/issues/5730
// and https://github.com/drush-ops/drush/issues/5899.
if ($reflectionClass->isFinal() || $reflectionClass->isAbstract() || class_exists($end)) {
continue;
// The entity type repository stores a map from class name to entity
// type id, sneak our short classes in there.
$classNameEntityTypeMapReflection = (new \ReflectionObject($this->entityTypeRepository))->getProperty('classNameEntityTypeMap');
$classNameEntityTypeMap = $classNameEntityTypeMapReflection->getValue($this->entityTypeRepository);
foreach ($this->entityTypeManager->getDefinitions() as $entityTypeId => $definition) {
$classNameEntityTypeMap = $this->createShortClassForEntityClass($definition->getClass(), $entityTypeId, $classNameEntityTypeMap);
foreach ($this->entityTypeBundleInfo->getAllBundleInfo() as $bundles) {
foreach ($bundles as $info) {
if (isset($info['class'])) {
$classNameEntityTypeMap = $this->createShortClassForEntityClass($info['class'], $entityTypeId, $classNameEntityTypeMap);
}
}
}
// Make it possible to easily load revisions.
eval(sprintf('class %s extends %s {
}
$classNameEntityTypeMapReflection->setValue($this->entityTypeRepository, $classNameEntityTypeMap);
}

public function createShortClassForEntityClass(string $class, string $entityTypeId, array $classNameEntityTypeMap): array
{
$reflectionClass = new \ReflectionClass($class);
$parts = explode('\\', $class);
$end = end($parts);
// https://github.com/drush-ops/drush/pull/5729, https://github.com/drush-ops/drush/issues/5730
// and https://github.com/drush-ops/drush/issues/5899.
if ($reflectionClass->isFinal() || $reflectionClass->isAbstract() || class_exists($end)) {
return $classNameEntityTypeMap;
}
$classNameEntityTypeMap[$end] = $entityTypeId;
// Make it possible to easily load revisions.
eval(sprintf('class %s extends %s {
public static function loadRevision($id) {
$entity_type_repository = \Drupal::service("entity_type.repository");
$entity_type_manager = \Drupal::entityTypeManager();
$storage = $entity_type_manager->getStorage($entity_type_repository->getEntityTypeFromClass(static::class));
return $storage->loadRevision($id);
}
}', $end, $class));
}
return $classNameEntityTypeMap;
}
}

0 comments on commit 1cac634

Please # to comment.