Skip to content

Commit

Permalink
Stop using drush.services.yml in sql:sanitize plugins (#5902)
Browse files Browse the repository at this point in the history
  • Loading branch information
weitzman authored Mar 12, 2024
1 parent 1c01274 commit c6cee19
Showing 11 changed files with 50 additions and 61 deletions.
2 changes: 1 addition & 1 deletion docs/hooks.md
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ All commandfiles may implement methods that are called by Drush at various times

## Custom Hooks

Drush commands can define custom events that other command files can hook. You can find examples in [CacheCommands](https://github.com/drush-ops/drush/blob/12.x/src/Commands/core/CacheCommands.php) and [SanitizeCommands](https://github.com/drush-ops/drush/blob/12.x/src/Drupal/Commands/sql/SanitizeCommands.php)
Drush commands can define custom events that other command files can hook. You can find examples in [CacheCommands](https://github.com/drush-ops/drush/blob/13.x/src/Commands/core/CacheCommands.php) and [SanitizeCommands](https://github.com/drush-ops/drush/blob/13.x/src/Commands/sql/sanitize/SanitizeCommands.php)

First, the command must implement CustomEventAwareInterface and use CustomEventAwareTrait, as described in the [dependency injection](dependency-injection.md#inflection) documentation.

Original file line number Diff line number Diff line change
@@ -2,15 +2,17 @@

declare(strict_types=1);

namespace Drush\Drupal\Commands\sql;
namespace Drush\Commands\sql\sanitize;

use Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface;
use Consolidation\AnnotatedCommand\Events\CustomEventAwareTrait;
use Drush\Attributes as CLI;
use Drush\Boot\DrupalBootLevels;
use Drush\Commands\core\DocsCommands;
use Drush\Commands\DrushCommands;
use Drush\Exceptions\UserAbortException;

#[CLI\Bootstrap(level: DrupalBootLevels::FULL)]
final class SanitizeCommands extends DrushCommands implements CustomEventAwareInterface
{
use CustomEventAwareTrait;
@@ -26,7 +28,7 @@ final class SanitizeCommands extends DrushCommands implements CustomEventAwareIn
* - `#[CLI\Hook(type: HookManager::ON_EVENT, target: SanitizeCommands::CONFIRMS)]`. Display summary to user before confirmation.
* - `#[CLI\Hook(type: HookManager::POST_COMMAND_HOOK, target: SanitizeCommands::SANITIZE)]`. Run queries or call APIs to perform sanitizing
*
* Several working commandfiles may be found at https://github.com/drush-ops/drush/tree/12.x/src/Drupal/Commands/sql
* Several working commandfiles may be found at https://github.com/drush-ops/drush/tree/13.x/src/Commands/sql/sanitize
*/
#[CLI\Command(name: self::SANITIZE, aliases: ['sqlsan','sql-sanitize'])]
#[CLI\Usage(name: 'drush sql:sanitize --sanitize-password=no', description: 'Sanitize database without modifying any passwords.')]
@@ -36,7 +38,7 @@ public function sanitize(): void
{
/**
* In order to present only one prompt, collect all confirmations from
* commandfiles up front. sql-sanitize plugins are commandfiles that implement
* commandfiles up front. sql:sanitize plugins are commandfiles that implement
* \Drush\Commands\sql\SanitizePluginInterface
*/
$messages = [];
@@ -54,6 +56,6 @@ public function sanitize(): void
}

// All sanitize operations defined in post-command hooks, including Drush
// core sanitize routines. See \Drush\Commands\sql\SanitizePluginInterface.
// core sanitize routines. See \Drush\Commands\sql\sanitize\SanitizePluginInterface.
}
}
Original file line number Diff line number Diff line change
@@ -2,33 +2,35 @@

declare(strict_types=1);

namespace Drush\Drupal\Commands\sql;
namespace Drush\Commands\sql\sanitize;

use Consolidation\AnnotatedCommand\CommandData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Drupal\Core\Database\Connection;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drush\Attributes as CLI;
use Drush\Boot\DrupalBootLevels;
use Drush\Commands\AutowireTrait;
use Drush\Commands\DrushCommands;
use Drush\Drush;
use Symfony\Component\Console\Input\InputInterface;

/**
* This class is a good example of a sql-sanitize plugin.
* This class is a good example of a sql:sanitize plugin.
*/
final class SanitizeCommentsCommands extends DrushCommands implements SanitizePluginInterface
{
use AutowireTrait;

public function __construct(
protected Connection $database,
protected ModuleHandlerInterface $moduleHandler
) {
parent::__construct();
}

/**
* Sanitize comment names from the DB.
*/
#[CLI\Hook(type: HookManager::POST_COMMAND_HOOK, target: 'sql-sanitize')]
#[CLI\Hook(type: HookManager::POST_COMMAND_HOOK, target: SanitizeCommands::SANITIZE)]
public function sanitize($result, CommandData $commandData): void
{
if ($this->applies()) {
@@ -63,7 +65,6 @@ public function messages(&$messages, InputInterface $input): void

protected function applies()
{
Drush::bootstrapManager()->doBootstrap(DrupalBootLevels::FULL);
return $this->moduleHandler->moduleExists('comment');
}
}
Original file line number Diff line number Diff line change
@@ -2,10 +2,10 @@

declare(strict_types=1);

namespace Drush\Drupal\Commands\sql;
namespace Drush\Commands\sql\sanitize;

use Consolidation\AnnotatedCommand\CommandData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Drush\Drupal\Commands\sql\Exit;
use Symfony\Component\Console\Input\InputInterface;

/**
Original file line number Diff line number Diff line change
@@ -2,22 +2,26 @@

declare(strict_types=1);

namespace Drush\Drupal\Commands\sql;
namespace Drush\Commands\sql\sanitize;

use Consolidation\AnnotatedCommand\CommandData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Drupal\Core\Database\Connection;
use Drush\Attributes as CLI;
use Drush\Commands\AutowireTrait;
use Drush\Commands\DrushCommands;
use Drupal\Core\Database\Connection;
use Symfony\Component\Console\Input\InputInterface;

/**
* This class is a good example of how to build a sql-sanitize plugin.
* This class is a good example of how to build a sql:sanitize plugin.
*/
final class SanitizeSessionsCommands extends DrushCommands implements SanitizePluginInterface
{
use AutowireTrait;

public function __construct(protected Connection $database)
{
parent::__construct();
}

/**
Original file line number Diff line number Diff line change
@@ -2,26 +2,30 @@

declare(strict_types=1);

namespace Drush\Drupal\Commands\sql;
namespace Drush\Commands\sql\sanitize;

use Consolidation\AnnotatedCommand\CommandData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drush\Attributes as CLI;
use Drush\Commands\AutowireTrait;
use Drush\Commands\DrushCommands;
use Symfony\Component\Console\Input\InputInterface;

/**
* This class is a good example of how to build a sql-sanitize plugin.
* This class is a good example of how to build a sql:sanitize plugin.
*/
final class SanitizeUserFieldsCommands extends DrushCommands implements SanitizePluginInterface
{
use AutowireTrait;

public function __construct(
protected \Drupal\Core\Database\Connection $database,
protected EntityFieldManagerInterface $entityFieldManager,
protected EntityTypeManagerInterface $entityTypeManager
) {
parent::__construct();
}

/**
Original file line number Diff line number Diff line change
@@ -2,33 +2,37 @@

declare(strict_types=1);

namespace Drush\Drupal\Commands\sql;
namespace Drush\Commands\sql\sanitize;

use Consolidation\AnnotatedCommand\CommandData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Password\PasswordInterface;
use Drush\Attributes as CLI;
use Drush\Commands\AutowireTrait;
use Drush\Commands\DrushCommands;
use Drush\Sql\SqlBase;
use Drush\Utils\StringUtils;
use Symfony\Component\Console\Input\InputInterface;

/**
* A sql-sanitize plugin.
* A sql:sanitize plugin.
*/
final class SanitizeUserTableCommands extends DrushCommands implements SanitizePluginInterface
{
use AutowireTrait;

public function __construct(
protected \Drupal\Core\Database\Connection $database,
protected PasswordInterface $passwordHasher,
protected EntityTypeManagerInterface $entityTypeManager
) {
parent::__construct();
}

/**
* Sanitize emails and passwords. This also an example of how to write a
* database sanitizer for sql-sync.
* database sanitizer for sql:sync.
*/
#[CLI\Hook(type: HookManager::POST_COMMAND_HOOK, target: SanitizeCommands::SANITIZE)]
public function sanitize($result, CommandData $commandData): void
26 changes: 0 additions & 26 deletions src/Drupal/Commands/sql/drush.services.yml

This file was deleted.

9 changes: 2 additions & 7 deletions src/Runtime/LegacyServiceFinder.php
Original file line number Diff line number Diff line change
@@ -4,12 +4,9 @@

namespace Drush\Runtime;

use Drush\Log\Logger;
use Drush\Drush;
use Symfony\Component\Console\Application;
use League\Container\Container as DrushContainer;
use Drush\Config\DrushConfig;
use Composer\Semver\Semver;
use Drush\Config\DrushConfig;
use Drush\Drush;

/**
* Find drush.services.yml files.
@@ -46,8 +43,6 @@ public function getDrushServiceFiles(): array
*/
protected function discoverDrushServiceProviders()
{
$this->addDrushServiceProvider("_drush__sql", $this->drushConfig->get('drush.base-dir') . '/src/Drupal/Commands/sql/drush.services.yml');

// Add Drush services from all modules
$module_filenames = $this->getModuleFileNames();
// Load each module's serviceProvider class.
13 changes: 9 additions & 4 deletions src/Runtime/ServiceManager.php
Original file line number Diff line number Diff line change
@@ -368,25 +368,30 @@ protected function hasStaticCreateFactory(string $class): bool
/**
* Does the provided class have a Bootstrap Attribute, indicating early loading.
*/
protected function hasBootStrapAttributeNone(string $class): bool
protected function bootStrapAttributeValue(string $class): ?int
{
try {
$reflection = new \ReflectionClass($class);
if ($attributes = $reflection->getAttributes(Bootstrap::class)) {
$bootstrap = $attributes[0]->newInstance();
return $bootstrap->level === DrupalBootLevels::NONE;
return $bootstrap->level;
}
} catch (\ReflectionException $e) {
}
return false;
return null;
}

/**
* Check whether a command class requires Drupal bootstrap.
*/
protected function requiresBootstrap(string $class): bool
{
return $this->hasStaticCreateFactory($class) && !$this->hasBootStrapAttributeNone($class);
if ($this->bootStrapAttributeValue($class) === DrupalBootLevels::FULL) {
return true;
} elseif ($this->bootStrapAttributeValue($class) === DrupalBootLevels::NONE) {
return false;
}
return $this->hasStaticCreateFactory($class);
}

/**
6 changes: 3 additions & 3 deletions tests/functional/SqlSyncTest.php
Original file line number Diff line number Diff line change
@@ -5,11 +5,11 @@
namespace Unish;

use Drush\Commands\core\PhpCommands;
use Drush\Commands\sql\SqlCommands;
use Drush\Commands\sql\SqlSyncCommands;
use Drush\Commands\core\UserCommands;
use Drush\Commands\pm\PmCommands;
use Drush\Drupal\Commands\sql\SanitizeCommands;
use Drush\Commands\sql\sanitize\SanitizeCommands;
use Drush\Commands\sql\SqlCommands;
use Drush\Commands\sql\SqlSyncCommands;

/**
* @group slow

0 comments on commit c6cee19

Please sign in to comment.