Testor can be configured to execute a sanitization command before creating a backup.
For example:
sanitize:
command: 'drush sql:sanitize'
Drush by default do some basic sanitization and also can be extended.
Let write a custom command that deletes all users except user 1.
First, generate a custom command with Drush:
drush generate drush:command-file
It interactively asks for input. Input module name "my_sanitizer" and leave all other inputs default. Output should be like:
Welcome to dcf generator!
–––––––––––––––––––––––––––
Module machine name:
➤ my_sanitizer
Module name [My sanitizer]:
➤
Class [MySanitizerCommands]:
➤
Would you like to inject dependencies? [No]:
➤
The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
• /var/www/html/web/modules/custom/my_sanitizer/src/Drush/Commands/MySanitizerCommands.php
Now let make the generated command a sanitize plugin. Make it extend SanitizePluginInterface
(to help IDE generate the method stubs) and inject Connection
to the constructor:
/**
* A Drush commandfile.
*/
final class MySanitizerCommands extends DrushCommands implements SanitizePluginInterface
{
use AutowireTrait;
/**
* Constructs a MySanitizerCommands object.
*/
public function __construct(
private readonly Token $token,
protected Connection $database,
)
{
parent::__construct();
}
}
Now implement methods and add corresponding annotations. Finally, class looks like below:
/**
* A Drush commandfile.
*/
final class MySanitizerCommands extends DrushCommands implements SanitizePluginInterface
{
use AutowireTrait;
/**
* Constructs a MySanitizerCommands object.
*/
public function __construct(
private readonly Token $token,
protected Connection $database,
)
{
parent::__construct();
}
#[CLI\Hook(type: HookManager::POST_COMMAND_HOOK, target: SanitizeCommands::SANITIZE)]
public function sanitize($result, CommandData $commandData)
{
// TODO: Implement sanitize() method.
$result = $this->database->query('select uid from users where uid > 1')->fetchAll();
foreach ($result as $item) {
$this->deleteUser($item->uid);
}
}
#[CLI\Hook(type: HookManager::ON_EVENT, target: SanitizeCommands::CONFIRMS)]
public function messages(array &$messages, InputInterface $input)
{
$messages[] = 'Remove all users but user with id=1.';
}
/**
* Deletes a user programmatically.
*
* @param int $uid
* The user ID of the user to delete.
*/
protected function deleteUser($uid)
{
// Load the user entity by user ID.
$user = User::load($uid);
if ($user) {
// Delete the user entity directly.
$user->delete();
\Drupal::logger('custom_module')->notice('User account with UID @uid has been deleted.', ['@uid' => $uid]);
} else {
\Drupal::logger('custom_module')->error('User account with UID @uid does not exist.', ['@uid' => $uid]);
}
}
}
To enable our custom command, first enable the newly created module:
drush en my_sanitizer
Now, when executing
drush sql:sanitize
it should show the added message, and after confirmation perform sanitize.
Same is before creating a snapshot via testor. E.g:
testor snapshot:create --name check-sanitization