Permalink
Browse files

Refactor sql-sync extensions (#2586)

New sanitizers should be command files which implement \Drush\Commands\sql\SqlSanitizePluginInterface. You may use any Drupal API you please, instead of just returning SQL.
  • Loading branch information...
1 parent e6a67c0 commit 66c433a6cad6904592267b115bb82e10d931bd26 @weitzman weitzman committed on GitHub Feb 4, 2017
@@ -6,106 +6,6 @@
*/
/**
- * Implements hook_drush_help_alter().
- */
-function sql_drush_help_alter(&$command) {
- // Drupal 7+ only options.
- if (drush_drupal_major_version() >= 7) {
- if ($command['commandfile'] == 'sql') {
- unset($command['options']['target']['hidden']);
- }
- }
-}
-
-/**
- * Safely bootstrap Drupal to the point where we can
- * access the database configuration.
- */
-function drush_sql_bootstrap_database_configuration() {
- // Under Drupal 7, if the database is configured but empty, then
- // DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION will throw an exception.
- // If this happens, we'll just catch it and continue.
- // TODO: Fix this in the bootstrap, per http://drupal.org/node/1996004
- try {
- drush_bootstrap_max(DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION);
- }
- catch (Exception $e) {
- }
-}
-
-/**
- * Check whether further bootstrap is needed. If so, do it.
- */
-function drush_sql_bootstrap_further() {
- if (!drush_get_option(array('db-url', 'db-spec'))) {
- drush_sql_bootstrap_database_configuration();
- }
-}
-
-// @todo Remove once sql-sync and archive-dump are using \Drush\Commands\OptionsCommands::optionsetTableSelection
-function drush_sql_get_table_selection_options() {
- return array(
- 'skip-tables-key' => 'A key in the $skip_tables array. @see example.drushrc.php. Optional.',
- 'structure-tables-key' => 'A key in the $structure_tables array. @see example.drushrc.php. Optional.',
- 'tables-key' => 'A key in the $tables array. Optional.',
- 'skip-tables-list' => 'A comma-separated list of tables to exclude completely. Optional.',
- 'structure-tables-list' => 'A comma-separated list of tables to include for structure, but not data. Optional.',
- 'tables-list' => 'A comma-separated list of tables to transfer. Optional.',
- );
-}
-
-/**
- * Call from a pre-sql-sync hook to register an sql
- * query to be executed in the post-sql-sync hook.
- * @see drush_sql_pre_sql_sync() and @see drush_sql_post_sql_sync().
- *
- * @param $id
- * String containing an identifier representing this
- * operation. This id is not actually used at the
- * moment, it is just used to fufill the contract
- * of drush contexts.
- * @param $message
- * String with the confirmation message that describes
- * to the user what the post-sync operation is going
- * to do. This confirmation message is printed out
- * just before the user is asked whether or not the
- * sql-sync operation should be continued.
- * @param $query
- * String containing the sql query to execute. If no
- * query is provided, then the confirmation message will
- * be displayed to the user, but no action will be taken
- * in the post-sync hook. This is useful for drush modules
- * that wish to provide their own post-sync hooks to fix
- * up the target database in other ways (e.g. through
- * Drupal APIs).
- */
-function drush_sql_register_post_sync_op($id, $message, $query = NULL) {
- $options = drush_get_context('post-sync-ops');
-
- $options[$id] = array('message' => $message, 'query' => $query);
-
- drush_set_context('post-sync-ops', $options);
-}
-
-/**
- * Builds a confirmation message for all post-sync operations.
- *
- * @return string
- * All post-sync operation messages concatenated together.
- */
-function _drush_sql_get_post_sync_messages() {
- $messages = '';
- $operations = drush_get_context('post-sync-ops');
- if (!empty($operations)) {
- $messages = dt('The following operations will be done on the target database:') . "\n";
-
- $bullets = array_column($operations, 'message');
- $messages .= " * " . implode("\n * ", $bullets) . "\n";
- }
- return $messages;
-}
-
-/**
* Wrapper for drush_get_class; instantiates an driver-specific instance
* of SqlBase class.
*
@@ -157,100 +57,3 @@ function drush_sql_get_class($db_spec = NULL) {
function drush_sql_get_version() {
return drush_get_class('Drush\Sql\Sql', array(), array(drush_drupal_major_version())) ?: NULL;
}
-
-/**
- * Implements hook_drush_sql_sync_sanitize().
- *
- * Sanitize usernames, passwords, and sessions when the --sanitize option is used.
- * It is also an example of how to write a database sanitizer for sql sync.
- *
- * To write your own sync hook function, define mymodule_drush_sql_sync_sanitize()
- * in mymodule.drush.inc and follow the form of this function to add your own
- * database sanitization operations via the register post-sync op function;
- * @see drush_sql_register_post_sync_op(). This is the only thing that the
- * sync hook function needs to do; sql-sync takes care of the rest.
- *
- * The function below has a lot of logic to process user preferences and
- * generate the correct SQL regardless of whether Postgres, Mysql,
- * Drupal 6/7/8 is in use. A simpler sanitize function that
- * always used default values and only worked with Drupal 6 + mysql
- * appears in the drush.api.php. @see hook_drush_sql_sync_sanitize().
- */
-function sql_drush_sql_sync_sanitize($site) {
- $site_settings = drush_sitealias_get_record($site);
- $databases = sitealias_get_databases_from_record($site_settings);
- $major_version = drush_drupal_major_version();
- $wrap_table_name = (bool) drush_get_option('db-prefix');
- $user_table_updates = array();
- $message_list = array();
-
- // Sanitize passwords.
- $newpassword = drush_get_option(array('sanitize-password', 'destination-sanitize-password'), 'password');
- if ($newpassword != 'no' && $newpassword !== 0) {
- $pw_op = "";
-
- // In Drupal 6, passwords are hashed via the MD5 algorithm.
- if ($major_version == 6) {
- $pw_op = "MD5('$newpassword')";
- }
- // In Drupal 7, passwords are hashed via a more complex algorithm,
- // available via the user_hash_password function.
- elseif ($major_version == 7) {
- $core = DRUSH_DRUPAL_CORE;
- include_once $core . '/includes/password.inc';
- include_once $core . '/includes/bootstrap.inc';
- $hash = user_hash_password($newpassword);
- $pw_op = "'$hash'";
- }
- else {
- // D8+. Mimic Drupal's /scripts/password-hash.sh
- drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_FULL);
- $password_hasher = \Drupal::service('password');
- $hash = $password_hasher->hash($newpassword);
- $pw_op = "'$hash'";
- }
- if (!empty($pw_op)) {
- $user_table_updates[] = "pass = $pw_op";
- $message_list[] = "passwords";
- }
- }
-
- // Sanitize email addresses.
- $newemail = drush_get_option(array('sanitize-email', 'destination-sanitize-email'), 'user+%uid@localhost.localdomain');
- if ($newemail != 'no' && $newemail !== 0) {
- if (strpos($newemail, '%') !== FALSE) {
- // We need a different sanitization query for Postgres and Mysql.
-
- $db_driver = $databases['default']['default']['driver'];
- if ($db_driver == 'pgsql') {
- $email_map = array('%uid' => "' || uid || '", '%mail' => "' || replace(mail, '@', '_') || '", '%name' => "' || replace(name, ' ', '_') || '");
- $newmail = "'" . str_replace(array_keys($email_map), array_values($email_map), $newemail) . "'";
- }
- elseif ($db_driver == 'mssql') {
- $email_map = array('%uid' => "' + uid + '", '%mail' => "' + replace(mail, '@', '_') + '", '%name' => "' + replace(name, ' ', '_') + '");
- $newmail = "'" . str_replace(array_keys($email_map), array_values($email_map), $newemail) . "'";
- }
- else {
- $email_map = array('%uid' => "', uid, '", '%mail' => "', replace(mail, '@', '_'), '", '%name' => "', replace(name, ' ', '_'), '");
- $newmail = "concat('" . str_replace(array_keys($email_map), array_values($email_map), $newemail) . "')";
- }
- $user_table_updates[] = "mail = $newmail, init = $newmail";
- }
- else {
- $user_table_updates[] = "mail = '$newemail', init = '$newemail'";
- }
- $message_list[] = 'email addresses';
- }
-
- if (!empty($user_table_updates)) {
- $table = $major_version >= 8 ? 'users_field_data' : 'users';
- if ($wrap_table_name) {
- $table = "{{$table}}";
- }
- $sanitize_query = "UPDATE {$table} SET " . implode(', ', $user_table_updates) . " WHERE uid > 0;";
- drush_sql_register_post_sync_op('user-email', dt('Reset !message in !table table', array('!message' => implode(' and ', $message_list), '!table' => $table)), $sanitize_query);
- }
-
- $sanitizer = new \Drush\Commands\core\SanitizeCommands();
- $sanitizer->doSanitize($major_version);
-}
View
@@ -272,18 +272,14 @@ function drush_hook_pre_pm_enable() {
}
/**
- * Sql-sync sanitization example.
+ * Sql-sanitize example.
*
- * This is equivalent to the built-in --sanitize option of sql-sync, but
- * simplified to only work with default values on Drupal 6 + mysql.
+ * These plugins sanitize the DB, usually removing personal information.
*
- * @see sql_drush_sql_sync_sanitize()
+ * @see \Drush\Commands\sql\SqlSanitizePluginInterface
*/
-function hook_drush_sql_sync_sanitize($source) {
- $table = drush_get_option('db-prefix') ? '{users}' : 'users';
- drush_sql_register_post_sync_op('my-sanitize-id',
- dt('Reset passwords and email addresses in user table.'),
- "UPDATE $table SET pass = MD5('password'), mail = concat('user+', uid, '@localhost') WHERE uid > 0;");
+function sanitize() {}
+function messages() {}
}
/**
@@ -316,90 +312,6 @@ function hook_drush_cache_clear(&$types, $include_bootstrapped_types) {
}
/**
- * Inform drush about one or more engine types.
- *
- * This hook allow to declare available engine types, the cli option to select
- * between engine implementatins, which one to use by default, global options
- * and other parameters. Commands may override this info when declaring the
- * engines they use.
- *
- * @return array
- * An array whose keys are engine type names and whose values describe
- * the characteristics of the engine type in relation to command definitions:
- *
- * - description: The engine type description.
- * - topic: If specified, the name of the topic command that will
- * display the automatically generated topic for this engine.
- * - topic-file: If specified, the path to the file that will be
- * displayed at the head of the automatically generated topic for
- * this engine. This path is relative to the Drush root directory;
- * non-core commandfiles should therefore use:
- * 'topic-file' => dirname(__FILE__) . '/mytopic.html';
- * - topics: If set, contains a list of topics that should be added to
- * the "Topics" section of any command that uses this engine. Note
- * that if 'topic' is set, it will automatically be added to the topics
- * list, and therefore does not need to also be listed here.
- * - option: The command line option to choose an implementation for
- * this engine type.
- * FALSE means there's no option. That is, the engine type is for internal
- * usage of the command and thus an implementation is not selectable.
- * - default: The default implementation to use by the engine type.
- * - options: Engine options common to all implementations.
- * - add-options-to-command: If there's a single implementation for this
- * engine type, add its options as command level options.
- * - combine-help: If there are multiple implementations for this engine
- * type, then instead of adding multiple help items in the form of
- * --engine-option=engine-type [description], instead combine all help
- * options into a single --engine-option that lists the different possible
- * values that can be used.
- *
- * @see drush_get_engine_types_info()
- * @see pm_drush_engine_type_info()
- */
-function hook_drush_engine_type_info() {
- return array(
- 'dessert' => array(
- 'description' => 'Choose a dessert while the sandwich is baked.',
- 'option' => 'dessert',
- 'default' => 'ice-cream',
- 'options' => 'sweetness',
- 'add-options-to-command' => FALSE,
- ),
- );
-}
-
-/**
- * Inform drush about one or more engines implementing a given engine type.
- *
- * - description: The engine implementation's description.
- * - implemented-by: The engine that actually implements this engine.
- * This is useful to allow the implementation of similar engines
- * in the reference one.
- * Defaults to the engine type key (e.g. 'ice-cream').
- * - verbose-only: The engine implementation will only appear in help
- * output in --verbose mode.
- *
- * This hook allow to declare implementations for an engine type.
- *
- * @see pm_drush_engine_package_handler()
- * @see pm_drush_engine_version_control()
- */
-function hook_drush_engine_ENGINE_TYPE() {
- return array(
- 'ice-cream' => array(
- 'description' => 'Feature rich ice-cream with all kind of additives.',
- 'options' => array(
- 'flavour' => 'Choose your favorite flavour',
- ),
- ),
- 'frozen-yogurt' => array(
- 'description' => 'Frozen dairy dessert made with yogurt instead of milk and cream.',
- 'implemented-by' => 'ice-cream',
- ),
- );
-}
-
-/**
* Alter the order that hooks are invoked.
*
* When implementing a given hook we may need to ensure it is invoked before
View
@@ -166,21 +166,3 @@ function _drush_drupal_parse_info_file($data, $merge_item = NULL) {
function drush_cid_install_profile() {
return drush_get_cid('install_profile', array(), array(drush_get_context('DRUSH_SELECTED_DRUPAL_SITE_CONF_PATH')));
}
-
-/*
- * An array of options shared by sql-sanitize and sql-sync commands.
- */
-function drupal_sanitize_options() {
- return array(
- 'sanitize-password' => array(
- 'description' => 'The password to assign to all accounts in the sanitization operation, or "no" to keep passwords unchanged.',
- 'example-value' => 'password',
- 'value' => 'required',
- ),
- 'sanitize-email' => array(
- 'description' => 'The pattern for test email addresses in the sanitization operation, or "no" to keep email addresses unchanged. May contain replacement patterns %uid, %mail or %name.',
- 'example-value' => 'user+%uid@localhost',
- 'value' => 'required',
- ),
- );
-}
Oops, something went wrong.

0 comments on commit 66c433a

Please sign in to comment.