db.php

Classes

File

db/Provision/Service/db.php
View source
  1. <?php
  2. class Provision_Service_db extends Provision_Service {
  3. protected $service = 'db';
  4. /**
  5. * Register the db handler for sites, based on the db_server option.
  6. */
  7. static function subscribe_site($context) {
  8. $context->setProperty('db_server', '@server_master');
  9. $context->is_oid('db_server');
  10. $context->service_subscribe('db', $context->db_server->name);
  11. }
  12. static function option_documentation() {
  13. return array(
  14. 'master_db' => 'server with db: Master database connection info, {type}://{user}:{password}@{host}',
  15. );
  16. }
  17. function init_server() {
  18. parent::init_server();
  19. $this->server->setProperty('master_db');
  20. $this->creds = array_map('urldecode', parse_url($this->server->master_db));
  21. return TRUE;
  22. }
  23. /**
  24. * Verifies database connection and commands
  25. */
  26. function verify_server_cmd() {
  27. if ($this->connect()) {
  28. if ($this->can_create_database()) {
  29. drush_log(dt('Provision can create new databases.'), 'success');
  30. }
  31. else {
  32. drush_set_error('PROVISION_CREATE_DB_FAILED');
  33. }
  34. if ($this->can_grant_privileges()) {
  35. drush_log(dt('Provision can grant privileges on database users.'), 'success');;
  36. }
  37. else {
  38. drush_set_error('PROVISION_GRANT_DB_USER_FAILED');
  39. }
  40. } else {
  41. drush_set_error('PROVISION_CONNECT_DB_FAILED');
  42. }
  43. }
  44. /**
  45. * Find a viable database name, based on the site's uri.
  46. */
  47. function suggest_db_name() {
  48. $uri = $this->context->uri;
  49. $suggest_base = substr(str_replace(array('.', '-'), '' , preg_replace('/^www\./', '', $uri)), 0, 16);
  50. if (!$this->database_exists($suggest_base)) {
  51. return $suggest_base;
  52. }
  53. for ($i = 0; $i < 100; $i++) {
  54. $option = sprintf("%s_%d", substr($suggest_base, 0, 15 - strlen( (string) $i) ), $i);
  55. if (!$this->database_exists($option)) {
  56. return $option;
  57. }
  58. }
  59. drush_set_error('PROVISION_CREATE_DB_FAILED', dt("Could not find a free database names after 100 attempts"));
  60. return false;
  61. }
  62. /**
  63. * Generate a new mysql database and user account for the specified credentials
  64. */
  65. function create_site_database($creds = array()) {
  66. if (!sizeof($creds)) {
  67. $creds = $this->generate_site_credentials();
  68. }
  69. extract($creds);
  70. if (drush_get_error() || !$this->can_create_database()) {
  71. drush_set_error('PROVISION_CREATE_DB_FAILED');
  72. drush_log("Database could not be created.", 'error');
  73. return FALSE;
  74. }
  75. foreach ($this->grant_host_list() as $db_grant_host) {
  76. drush_log(dt("Granting privileges to %user@%client on %database", array('%user' => $db_user, '%client' => $db_grant_host, '%database' => $db_name)));
  77. if (!$this->grant($db_name, $db_user, $db_passwd, $db_grant_host)) {
  78. drush_set_error('PROVISION_CREATE_DB_FAILED', dt("Could not create database user @user", array('@user' => $db_user)));
  79. }
  80. }
  81. $this->create_database($db_name);
  82. $status = $this->database_exists($db_name);
  83. if ($status) {
  84. drush_log(dt('Created @name database', array("@name" => $db_name)), 'success');
  85. }
  86. else {
  87. drush_set_error('PROVISION_CREATE_DB_FAILED', dt("Could not create @name database", array("@name" => $db_name)));
  88. }
  89. return $status;
  90. }
  91. /**
  92. * Remove the database and user account for the supplied credentials
  93. */
  94. function destroy_site_database($creds = array()) {
  95. if (!sizeof($creds)) {
  96. $creds = $this->fetch_site_credentials();
  97. }
  98. extract($creds);
  99. if ( $this->database_exists($db_name) ) {
  100. drush_log(dt("Dropping database @dbname", array('@dbname' => $db_name)));
  101. if (!$this->drop_database($db_name)) {
  102. drush_log(dt("Failed to drop database @dbname", array('@dbname' => $db_name)), 'warning');
  103. }
  104. }
  105. if ( $this->database_exists($db_name) ) {
  106. drush_set_error('PROVISION_DROP_DB_FAILED');
  107. return FALSE;
  108. }
  109. foreach ($this->grant_host_list() as $db_grant_host) {
  110. drush_log(dt("Revoking privileges of %user@%client from %database", array('%user' => $db_user, '%client' => $db_grant_host, '%database' => $db_name)));
  111. if (!$this->revoke($db_name, $db_user, $db_grant_host)) {
  112. drush_log(dt("Failed to revoke user privileges"), 'warning');
  113. }
  114. }
  115. }
  116. function import_site_database($dump_file = null, $creds = array()) {
  117. if (is_null($dump_file)) {
  118. $dump_file = d()->site_path . '/database.sql';
  119. }
  120. if (!sizeof($creds)) {
  121. $creds = $this->fetch_site_credentials();
  122. }
  123. $exists = provision_file()->exists($dump_file)
  124. ->succeed('Found database dump at @path.')
  125. ->fail('No database dump was found at @path.', 'PROVISION_DB_DUMP_NOT_FOUND')
  126. ->status();
  127. if ($exists) {
  128. $readable = provision_file()->readable($dump_file)
  129. ->succeed('Database dump at @path is readable')
  130. ->fail('The database dump at @path could not be read.', 'PROVISION_DB_DUMP_NOT_READABLE')
  131. ->status();
  132. if ($readable) {
  133. $this->import_dump($dump_file, $creds);
  134. }
  135. }
  136. }
  137. function generate_site_credentials() {
  138. $creds = array();
  139. // replace with service type
  140. $db_type = drush_get_option('db_type', function_exists('mysqli_connect') ? 'mysqli' : 'mysql');
  141. // As of Drupal 7 there is no more mysqli type
  142. if (drush_drupal_major_version() >= 7) {
  143. $db_type = ($db_type == 'mysqli') ? 'mysql' : $db_type;
  144. }
  145. //TODO - this should not be here at all
  146. $creds['db_type'] = drush_set_option('db_type', $db_type, 'site');
  147. $creds['db_host'] = drush_set_option('db_host', $this->server->remote_host, 'site');
  148. $creds['db_port'] = drush_set_option('db_port', $this->server->db_port, 'site');
  149. $creds['db_passwd'] = drush_set_option('db_passwd', provision_password(), 'site');
  150. $creds['db_name'] = drush_set_option('db_name', $this->suggest_db_name(), 'site');
  151. $creds['db_user'] = drush_set_option('db_user', $creds['db_name'], 'site');
  152. return $creds;
  153. }
  154. function fetch_site_credentials() {
  155. $creds = array();
  156. $keys = array('db_type', 'db_port', 'db_user', 'db_name', 'db_host', 'db_passwd');
  157. foreach ($keys as $key) {
  158. $creds[$key] = drush_get_option($key, '', 'site');
  159. }
  160. return $creds;
  161. }
  162. function database_exists($name) {
  163. return FALSE;
  164. }
  165. function drop_database($name) {
  166. return FALSE;
  167. }
  168. function create_database($name) {
  169. return FALSE;
  170. }
  171. function can_create_database() {
  172. return FALSE;
  173. }
  174. function can_grant_privileges() {
  175. return FALSE;
  176. }
  177. function grant($name, $username, $password, $host = '') {
  178. return FALSE;
  179. }
  180. function revoke($name, $username, $host = '') {
  181. return FALSE;
  182. }
  183. function import_dump($dump_file, $creds) {
  184. return FALSE;
  185. }
  186. function generate_dump() {
  187. return FALSE;
  188. }
  189. /**
  190. * Return a list of hosts, as seen by the db server, which should be granted
  191. * access to the site database.
  192. */
  193. function grant_host_list() {
  194. return array_unique(array_map(array($this, 'grant_host'), $this->context->service('http')->grant_server_list()));
  195. }
  196. /**
  197. * Return a hostname suitable for database grants from a server object.
  198. */
  199. function grant_host(Provision_Context_server $server) {
  200. return $server->remote_host;
  201. }
  202. }