0d8871ce64b87c68c853f3796c3559c944a3e919
[yaffs-website] / vendor / drush / drush / lib / Drush / Sql / SqlBase.php
1 <?php
2
3 namespace Drush\Sql;
4
5 use Drupal\Core\Database\Database;
6 use Drush\Log\LogLevel;
7 use Webmozart\PathUtil\Path;
8
9 class SqlBase {
10
11   // An Drupal style array containing specs for connecting to database.
12   public $db_spec;
13
14   // Default code appended to sql-query connections.
15   public $query_extra = '';
16
17   // The way you pass a sql file when issueing a query.
18   public $query_file = '<';
19
20   /**
21    * Typically, SqlBase objects are contructed via drush_sql_get_class().
22    */
23   public function __construct($db_spec = NULL) {
24     $this->db_spec = $db_spec;
25   }
26
27   /*
28    * Get the current $db_spec.
29    */
30   public function db_spec() {
31     return $this->db_spec;
32   }
33
34   /**
35    * The unix command used to connect to the database.
36    * @return string
37    */
38   public function command() {}
39
40   /**
41    * A string for connecting to a database.
42    *
43    * @param bool $hide_password
44    *  If TRUE, DBMS should try to hide password from process list.
45    *  On mysql, that means using --defaults-extra-file to supply the user+password.
46    *
47    * @return string
48    */
49   public function connect($hide_password = TRUE) {
50     return trim($this->command() . ' ' . $this->creds($hide_password) . ' ' . drush_get_option('extra', $this->query_extra));
51   }
52
53
54   /*
55    * Execute a SQL dump and return the path to the resulting dump file.
56    *
57    * @param string|bool @file
58    *   The path where the dump file should be stored. If TRUE, generate a path
59    *   based on usual backup directory and current date.
60    */
61   public function dump($file = '') {
62     $file_suffix = '';
63     $table_selection = $this->get_expanded_table_selection();
64     $file = $this->dumpFile($file);
65     $cmd = $this->dumpCmd($table_selection);
66     // Gzip the output from dump command(s) if requested.
67     if (drush_get_option('gzip')) {
68       $cmd .= ' | gzip -f';
69       $file_suffix .= '.gz';
70     }
71     if ($file) {
72       $file .= $file_suffix;
73       $cmd .= ' > ' . drush_escapeshellarg($file);
74     }
75
76     // Avoid the php memory of the $output array in drush_shell_exec().
77     if (!$return = drush_op_system($cmd)) {
78       if ($file) {
79         drush_log(dt('Database dump saved to !path', array('!path' => $file)), LogLevel::SUCCESS);
80         drush_backend_set_result($file);
81       }
82     }
83     else {
84       return drush_set_error('DRUSH_SQL_DUMP_FAIL', 'Database dump failed');
85     }
86   }
87
88   /*
89    * Build bash for dumping a database.
90    *
91    * @param array $table_selection
92    *   Supported keys: 'skip', 'structure', 'tables'.
93    * @return string
94    *   One or more mysqldump/pg_dump/sqlite3/etc statements that are ready for executing.
95    *   If multiple statements are needed, enclose in parenthesis.
96    */
97   public function dumpCmd($table_selection) {}
98
99   /*
100    * Generate a path to an output file for a SQL dump when needed.
101    *
102    * @param string|bool @file
103    *   If TRUE, generate a path based on usual backup directory and current date.
104    *   Otherwise, just return the path that was provided.
105    */
106   public function dumpFile($file) {
107     $database = $this->db_spec['database'];
108
109     // $file is passed in to us usually via --result-file.  If the user
110     // has set $options['result-file'] = TRUE, then we
111     // will generate an SQL dump file in the same backup
112     // directory that pm-updatecode uses.
113     if ($file) {
114       if ($file === TRUE) {
115         // User did not pass a specific value for --result-file. Make one.
116         $backup = drush_include_engine('version_control', 'backup');
117         $backup_dir = $backup->prepare_backup_dir($database);
118         if (empty($backup_dir)) {
119           $backup_dir = drush_find_tmp();
120         }
121         $file = Path::join($backup_dir, '@DATABASE_@DATE.sql');
122       }
123       $file = str_replace(array('@DATABASE', '@DATE'), array($database, gmdate('Ymd_His')), $file);
124     }
125     return $file;
126   }
127
128   /**
129    * Execute a SQL query.
130    *
131    * Note: This is an API function. Try to avoid using drush_get_option() and instead
132    * pass params in. If you don't want to query results to print during --debug then
133    * provide a $result_file whose value can be drush_bit_bucket().
134    *
135    * @param string $query
136    *   The SQL to be executed. Should be NULL if $input_file is provided.
137    * @param string $input_file
138    *   A path to a file containing the SQL to be executed.
139    * @param string $result_file
140    *   A path to save query results to. Can be drush_bit_bucket() if desired.
141    *
142    * @return
143    *   TRUE on success, FALSE on failure
144    */
145   public function query($query, $input_file = NULL, $result_file = '') {
146     $input_file_original = $input_file;
147     if ($input_file && drush_file_is_tarball($input_file)) {
148       if (drush_shell_exec('gzip -d %s', $input_file)) {
149         $input_file = trim($input_file, '.gz');
150       }
151       else {
152         return drush_set_error(dt('Failed to decompress input file.'));
153       }
154     }
155
156     // Save $query to a tmp file if needed. We will redirect it in.
157     if (!$input_file) {
158       $query = $this->query_prefix($query);
159       $query = $this->query_format($query);
160       $input_file = drush_save_data_to_temp_file($query);
161     }
162
163     $parts = array(
164       $this->command(),
165       $this->creds(),
166       $this->silent(), // This removes column header and various helpful things in mysql.
167       drush_get_option('extra', $this->query_extra),
168       $this->query_file,
169       drush_escapeshellarg($input_file),
170     );
171     $exec = implode(' ', $parts);
172
173     if ($result_file) {
174       $exec .= ' > '. drush_escapeshellarg($result_file);
175     }
176
177     // In --verbose mode, drush_shell_exec() will show the call to mysql/psql/sqlite,
178     // but the sql query itself is stored in a temp file and not displayed.
179     // We show the query when --debug is used and this function created the temp file.
180     if ((drush_get_context('DRUSH_DEBUG') || drush_get_context('DRUSH_SIMULATE')) && empty($input_file_original)) {
181       drush_log('sql-query: ' . $query, LogLevel::NOTICE);
182     }
183
184     $success = drush_shell_exec($exec);
185
186     if ($success && drush_get_option('file-delete')) {
187       drush_op('drush_delete_dir', $input_file);
188     }
189
190     return $success;
191   }
192
193   /*
194    * A string to add to the command when queries should not print their results.
195    */
196   public function silent() {}
197
198
199   public function query_prefix($query) {
200     // Inject table prefixes as needed.
201     if (drush_has_boostrapped(DRUSH_BOOTSTRAP_DRUPAL_DATABASE)) {
202       // Enable prefix processing which can be dangerous so off by default. See http://drupal.org/node/1219850.
203       if (drush_get_option('db-prefix')) {
204         if (drush_drupal_major_version() >= 7) {
205           $query = Database::getConnection()->prefixTables($query);
206         }
207         else {
208           $query = db_prefix_tables($query);
209         }
210       }
211     }
212     return $query;
213   }
214
215
216   public function query_format($query) {
217     return $query;
218   }
219
220   /**
221    * Drop specified database.
222    *
223    * @param array $tables
224    *   An array of table names
225    * @return boolean
226    *   True if successful, FALSE if failed.
227    */
228   public function drop($tables) {
229     $return = TRUE;
230     if ($tables) {
231       $sql = 'DROP TABLE '. implode(', ', $tables);
232       $return = $this->query($sql);
233     }
234     return $return;
235   }
236
237   /**
238    * Build a SQL string for dropping and creating a database.
239    *
240    * @param string dbname
241    *   The database name.
242    * @param boolean $quoted
243    *   Quote the database name. Mysql uses backticks to quote which can cause problems
244    *   in a Windows shell. Set TRUE if the CREATE is not running on the bash command line.
245    */
246   public function createdb_sql($dbname, $quoted = FALSE) {}
247
248   /**
249    * Create a new database.
250    *
251    * @param boolean $quoted
252    *   Quote the database name. Mysql uses backticks to quote which can cause problems
253    *   in a Windows shell. Set TRUE if the CREATE is not running on the bash command line.
254    * @return boolean
255    *   True if successful, FALSE otherwise.
256    */
257   public function createdb($quoted = FALSE) {
258     $dbname = $this->db_spec['database'];
259     $sql = $this->createdb_sql($dbname, $quoted);
260     // Adjust connection to allow for superuser creds if provided.
261     $this->su();
262     return $this->query($sql);
263   }
264
265   /**
266    * Drop all tables (if DB exists) or CREATE target database.
267    *
268    * return boolean
269    *   TRUE or FALSE depending on success.
270    */
271   public function drop_or_create() {
272     if ($this->db_exists()) {
273       return $this->drop($this->listTables());
274     }
275     else {
276       return $this->createdb();
277     }
278   }
279
280   /*
281    * Determine if the specified DB already exists.
282    *
283    * @return bool
284    */
285   public function db_exists() {}
286
287   public function delete() {}
288
289   /**
290    * Build a fragment connection parameters.
291    *
292    * @param bool $hide_password
293    *  If TRUE, DBMS should try to hide password from process list.
294    *  On mysql, that means using --defaults-extra-file to supply the user+password.
295    * @return string
296    */
297   public function creds($hide_password = TRUE) {}
298
299   /**
300    * The active database driver.
301    * @return string
302    */
303   public function scheme() {
304     return $this->db_spec['driver'];
305   }
306
307   /**
308    * Get a list of all table names and expand input that may contain
309    * wildcards (`*`) if necessary so that the array returned only contains valid
310    * table names i.e. actual tables that exist, without a wildcard.
311    *
312    * @return array
313    *   An array of tables with each table name in the appropriate
314    *   element of the array.
315    */
316   public function get_expanded_table_selection() {
317     $table_selection = drush_sql_get_table_selection();
318     // Get the existing table names in the specified database.
319     $db_tables = $this->listTables();
320     if (isset($table_selection['skip'])) {
321       $table_selection['skip'] = _drush_sql_expand_and_filter_tables($table_selection['skip'], $db_tables);
322     }
323     if (isset($table_selection['structure'])) {
324       $table_selection['structure'] = _drush_sql_expand_and_filter_tables($table_selection['structure'], $db_tables);
325     }
326     if (isset($table_selection['tables'])) {
327       $table_selection['tables'] = _drush_sql_expand_and_filter_tables($table_selection['tables'], $db_tables);
328     }
329     return $table_selection;
330   }
331
332   /**
333    * Extract the name of all existing tables in the given database.
334    *
335    * @return array
336    *   An array of table names which exist in the current database.
337    */
338   public function listTables() {}
339
340   /*
341    * Helper method to turn associative array into options with values.
342    *
343    * @return string
344    *   A bash fragment.
345    */
346   public function params_to_options($parameters) {
347     // Turn each parameter into a valid parameter string.
348     $parameter_strings = array();
349     foreach ($parameters as $key => $value) {
350       // Only escape the values, not the keys or the rest of the string.
351       $value = drush_escapeshellarg($value);
352       $parameter_strings[] = "--$key=$value";
353     }
354
355     // Join the parameters and return.
356     return implode(' ', $parameter_strings);
357   }
358
359   /**
360    * Adjust DB connection with superuser credentials if provided.
361    *
362    * The options 'db-su' and 'db-su-pw' will be retreived from the
363    * specified site alias record, if it exists and contains those items.
364    * If it does not, they will be fetched via drush_get_option.
365    *
366    * Note that in the context of sql-sync, the site alias record will
367    * be taken from the target alias (e.g. `drush sql-sync @source @target`),
368    * which will be overlayed with any options that begin with 'target-';
369    * therefore, the commandline options 'target-db-su' and 'target-db-su-pw'
370    * may also affect the operation of this function.
371    *
372    * @return null
373    */
374   public function su() {
375     $create_db_target = $this->db_spec;
376
377     $create_db_target['database'] = '';
378     $db_superuser = drush_get_option('db-su');
379     if (isset($db_superuser)) {
380       $create_db_target['username'] = $db_superuser;
381     }
382     $db_su_pw = drush_get_option('db-su-pw');
383     // If --db-su-pw is not provided and --db-su is, default to empty password.
384     // This way db cli command will take password from .my.cnf or .pgpass.
385     if (!empty($db_su_pw)) {
386       $create_db_target['password'] = $db_su_pw;
387     }
388     elseif (isset($db_superuser)) {
389       unset($create_db_target['password']);
390     }
391     $this->db_spec = $create_db_target;
392   }
393 }