wordpress-deploy 1.0.0.alpha2 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -1
- data/Guardfile +1 -16
- data/README.md +56 -0
- data/lib/wordpress_deploy.rb +43 -9
- data/lib/wordpress_deploy/cli/helpers.rb +6 -3
- data/lib/wordpress_deploy/cli/utility.rb +56 -33
- data/lib/wordpress_deploy/config.rb +77 -0
- data/lib/wordpress_deploy/database/mysql.rb +281 -20
- data/lib/wordpress_deploy/environment.rb +85 -43
- data/lib/wordpress_deploy/environments.rb +89 -0
- data/lib/wordpress_deploy/logger.rb +3 -3
- data/lib/wordpress_deploy/{transfer_protocols → storage}/ftp.rb +52 -116
- data/lib/wordpress_deploy/storage/local.rb +12 -0
- data/lib/wordpress_deploy/version.rb +1 -1
- data/lib/wordpress_deploy/wordpress/salts.rb +68 -0
- data/spec/data/blue.rb +52 -0
- data/spec/data/development.rb +49 -0
- data/spec/data/green.rb +52 -0
- data/spec/data/production.rb +52 -0
- data/spec/data/red.rb +52 -0
- data/spec/data/wp-config.php +90 -0
- data/spec/spec_helper.rb +16 -5
- data/spec/wordpress_deploy/cli/utility_spec.rb +48 -0
- data/spec/{environment_spec.rb → wordpress_deploy/config_spec.rb} +9 -7
- data/spec/wordpress_deploy/database/mysql_spec.rb +147 -0
- data/spec/wordpress_deploy/environment_spec.rb +96 -0
- data/spec/wordpress_deploy/environments_spec.rb +65 -0
- data/spec/wordpress_deploy/storage/ftp_spec.rb +58 -0
- data/spec/wordpress_deploy/storage/local_spec.rb +0 -0
- data/spec/wordpress_deploy/wordpress/salts_spec.rb +70 -0
- data/{spec/data/wp-config-sample.php → templates/wp-config.erb} +17 -17
- data/wordpress_deploy.gemspec +7 -6
- metadata +64 -30
- data/Gemfile.lock +0 -83
- data/lib/wordpress_deploy/wordpress/configuration.rb +0 -196
- data/spec/data/ftp.yml +0 -4
- data/spec/data/wp-config.yml +0 -128
- data/spec/database/mysql_spec.rb +0 -93
- data/spec/transfer_protocols/ftp_spec.rb +0 -193
- data/spec/wordpress/configuration_spec.rb +0 -202
data/.gitignore
CHANGED
@@ -12,6 +12,8 @@ test/tmp
|
|
12
12
|
test/version_tmp
|
13
13
|
tmp
|
14
14
|
|
15
|
+
*.swp
|
16
|
+
|
15
17
|
# YARD artifacts
|
16
18
|
.yardoc
|
17
19
|
_yardoc
|
@@ -20,8 +22,12 @@ doc/
|
|
20
22
|
# Mac files
|
21
23
|
.DS_Store
|
22
24
|
|
25
|
+
# Development gems
|
26
|
+
Gemfile.lock
|
27
|
+
|
23
28
|
# Spec data made during tests
|
24
|
-
spec/data
|
29
|
+
spec/data/*.sql
|
25
30
|
*.log
|
26
31
|
config/
|
27
32
|
site/
|
33
|
+
sql/
|
data/Guardfile
CHANGED
@@ -3,22 +3,7 @@
|
|
3
3
|
|
4
4
|
guard 'rspec', :version => 2 do
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
6
|
-
watch(%r{^lib/
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
7
7
|
watch('spec/spec_helper.rb') { "spec" }
|
8
|
-
|
9
|
-
# Rails example
|
10
|
-
#watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
-
#watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
-
#watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
-
#watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
-
#watch('config/routes.rb') { "spec/routing" }
|
15
|
-
#watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
-
|
17
|
-
# Capybara request specs
|
18
|
-
#watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
19
|
-
|
20
|
-
# Turnip features and steps
|
21
|
-
#watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
-
#watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
8
|
end
|
24
9
|
|
data/README.md
CHANGED
@@ -35,3 +35,59 @@ Usage
|
|
35
35
|
-----
|
36
36
|
|
37
37
|
wp-deploy help
|
38
|
+
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
##
|
42
|
+
# This is an example of a default WordpressDeploy configuration file. The
|
43
|
+
# values here are examples to show you what to do.
|
44
|
+
WordpressDeploy::Environment.new(:red) do
|
45
|
+
|
46
|
+
base_url "localhost"
|
47
|
+
|
48
|
+
##
|
49
|
+
# Connection and settings for the MySQL database that wordpress
|
50
|
+
# connects to
|
51
|
+
database do
|
52
|
+
name "red"
|
53
|
+
user "red_user"
|
54
|
+
password "Bun__huPEMeBreM6tebRAp@eguzuQExe"
|
55
|
+
host "hanerutherford.biz"
|
56
|
+
charset "utf8"
|
57
|
+
collate ""
|
58
|
+
|
59
|
+
##
|
60
|
+
# If this parameter is not defined wp_
|
61
|
+
# is assumed.
|
62
|
+
table_prefix "wp_";
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Authentication Unique Keys and Salts
|
67
|
+
# https://api.wordpress.org/secret-key/1.1/salt/
|
68
|
+
# If no salts are supplied they will be generated automatically
|
69
|
+
#
|
70
|
+
# NOTE This entire block is optional
|
71
|
+
salts do
|
72
|
+
auth_key '*oH{(q=`tIzdNJKUk$XfHNNjKd$W=f$S`CtD.,;x0R}$/A,}]!+q0>>QfB#.Bsw]'
|
73
|
+
secure_auth_key '{yg|7Q*j-?$%`b|Z!+5U,pvM,eA0+$/ruprp.mO[;|fExU:n0,-!at0+3UY@;h`X'
|
74
|
+
logged_in_key 'k]N 9I<-rZq#k Xg)IPhv$E*ktbD7Z_AtI){U;(P;0r#LJlYncEr%8v9tG`>BHU+'
|
75
|
+
nonce_key ' /w9->::-YB Xa#lf%TPH+cIf?]Ru4OfKGF2h8PHsa)2,n-~kRJ<[slUg<GZ Asx'
|
76
|
+
auth_salt 'VYwGGP,#|9P[5RCUTdv2c8)`^{dotU0fWrU`JE9qq^n=F4//e)fCs<HF6sd>~yjW'
|
77
|
+
secure_auth_salt 'ok}@vSs=n6%_%UCO|&[?Jc;,-,.#Q3}zR4ej%IoAL7RavTN/Xe,UrQ4)p}onRie0'
|
78
|
+
logged_in_salt 'Z!,C*:Q_I9A`[pJm-b0Z/(Gm2qvK8>0~| T&)lM+sxG.OdEmgHbAGF&(^>2.rDGW'
|
79
|
+
nonce_salt 'ay)${bFV=F1KH[`NZ+W+Zk?Hc:@}jN}Ec)+Zn[F1fyP,mwi|@tk/(1hdp[G2F%os'
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Block defines the settings for the transfer of files
|
84
|
+
# to this configuration.
|
85
|
+
transfer :Ftp do
|
86
|
+
host "ftp.hanerutherford.biz"
|
87
|
+
user "red_user"
|
88
|
+
password "Bun__huPEMeBreM6tebRAp@eguzuQExe"
|
89
|
+
destination "/html"
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
```
|
data/lib/wordpress_deploy.rb
CHANGED
@@ -1,16 +1,49 @@
|
|
1
1
|
require "thor"
|
2
2
|
require "open3"
|
3
3
|
require "fileutils"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
class Hash
|
7
|
+
|
8
|
+
def find_and_replace!(find, replace)
|
9
|
+
RecursiveReplace.find_and_replace!(find, replace, self)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class RecursiveReplace
|
15
|
+
|
16
|
+
def self.find_and_replace!(find, replace, obj)
|
17
|
+
m = "find_and_replace_#{obj.class}!"
|
18
|
+
send(m, find, replace, obj) if respond_to? m, true
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def self.find_and_replace_Hash!(find, replace, hash)
|
24
|
+
hash.each { |k,v| find_and_replace!(find, replace, v) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.find_and_replace_Array!(find, replace, arr)
|
28
|
+
arr.each { |x| find_and_replace!(find, replace, x) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.find_and_replace_String!(find, replace, str)
|
32
|
+
str.gsub!(/#{find}/, replace)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
4
36
|
|
5
37
|
module WordpressDeploy
|
6
38
|
##
|
7
39
|
# WordpressDeploy's internal paths
|
8
40
|
#
|
9
|
-
LIBRARY_PATH
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
41
|
+
LIBRARY_PATH = File.join(File.dirname(__FILE__), 'wordpress_deploy')
|
42
|
+
TEMPLATE_PATH = File.join(File.dirname(__FILE__), '..', 'templates')
|
43
|
+
CLI_PATH = File.join(LIBRARY_PATH, 'cli')
|
44
|
+
WORDPRESS_PATH = File.join(LIBRARY_PATH, 'wordpress')
|
45
|
+
STORAGE_PATH = File.join(LIBRARY_PATH, 'storage')
|
46
|
+
DATABASE_PATH = File.join(LIBRARY_PATH, 'database')
|
14
47
|
|
15
48
|
module Cli
|
16
49
|
autoload :Helpers, File.join(CLI_PATH, 'helpers')
|
@@ -18,18 +51,19 @@ module WordpressDeploy
|
|
18
51
|
end
|
19
52
|
|
20
53
|
module Wordpress
|
21
|
-
autoload :
|
54
|
+
autoload :Salts, File.join(WORDPRESS_PATH, 'salts')
|
22
55
|
end
|
23
56
|
|
24
|
-
module
|
25
|
-
autoload :Ftp,
|
57
|
+
module Storage
|
58
|
+
autoload :Ftp, File.join(STORAGE_PATH, 'ftp')
|
59
|
+
autoload :Local, File.join(STORAGE_PATH, 'local')
|
26
60
|
end
|
27
61
|
|
28
62
|
module Database
|
29
63
|
autoload :MySql, File.join(DATABASE_PATH, 'mysql')
|
30
64
|
end
|
31
65
|
|
32
|
-
%w{version logger errors environment}.each do |klass|
|
66
|
+
%w{version logger errors config environments environment}.each do |klass|
|
33
67
|
require File.join(LIBRARY_PATH, klass)
|
34
68
|
end
|
35
69
|
end
|
@@ -14,7 +14,7 @@ module WordpressDeploy
|
|
14
14
|
# If the command fails to execute, or returns a non-zero exit status
|
15
15
|
# an Error will be raised.
|
16
16
|
#
|
17
|
-
# Returns
|
17
|
+
# Returns STDOUT
|
18
18
|
def run(command)
|
19
19
|
name = command_name(command)
|
20
20
|
Logger.debug "Running system utility '#{ name }'..."
|
@@ -47,7 +47,7 @@ module WordpressDeploy
|
|
47
47
|
)
|
48
48
|
end
|
49
49
|
|
50
|
-
return
|
50
|
+
return out
|
51
51
|
else
|
52
52
|
raise Errors::Cli::SystemCallError, <<-EOS
|
53
53
|
'#{ name }' Failed on #{ RUBY_PLATFORM }
|
@@ -69,7 +69,10 @@ module WordpressDeploy
|
|
69
69
|
raise Errors::Cli::UtilityNotFoundError,
|
70
70
|
'Utility Name Empty' if name.empty?
|
71
71
|
|
72
|
+
# Return the utility immediately if it has already been found
|
72
73
|
path = UTILITY[name]
|
74
|
+
return path unless path.nil?
|
75
|
+
|
73
76
|
err, ps = '', nil
|
74
77
|
Open3.popen3 "which #{name}" do |stdin, stdout, stderr, wait_thr|
|
75
78
|
stdin.close
|
@@ -78,7 +81,7 @@ module WordpressDeploy
|
|
78
81
|
|
79
82
|
# Process::Status object returned
|
80
83
|
ps = wait_thr.value
|
81
|
-
end
|
84
|
+
end
|
82
85
|
|
83
86
|
if !ps.nil? && ps.success?
|
84
87
|
UTILITY[name] = path
|
@@ -9,24 +9,26 @@ module WordpressDeploy
|
|
9
9
|
# These options apply to all commands
|
10
10
|
class_option :root_dir, type: :string, default: '', aliases: '-r'
|
11
11
|
class_option :wp_dir, type: :string, default: '', aliases: '-w'
|
12
|
-
class_option :
|
12
|
+
class_option :config_dir, type: :string, default: '', aliases: '-c'
|
13
|
+
class_option :sql_dir, type: :string, default: '', aliases: '-s'
|
13
14
|
class_option :verbose, type: :boolean, default: false, aliases: '-v'
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
def generate
|
18
|
-
##
|
16
|
+
desc "config ENVIRONMENT", "Generate the wp-config.php file for the specified environment."
|
17
|
+
def config(environment)
|
19
18
|
# Set Logger into verbose mode (if the user requested it)
|
20
19
|
Logger.verbose = options[:verbose]
|
21
20
|
|
22
21
|
# Set environment options
|
23
|
-
|
22
|
+
Config.set_options options
|
23
|
+
|
24
|
+
# Load ALL the available environments
|
25
|
+
WordpressDeploy::Environments.load
|
24
26
|
|
25
|
-
#
|
26
|
-
|
27
|
+
# Get the Environment the user requested
|
28
|
+
env = WordpressDeploy::Environments.find environment.to_sym
|
27
29
|
|
28
30
|
# Save the configuration file
|
29
|
-
|
31
|
+
env.save_wp_config
|
30
32
|
rescue => err
|
31
33
|
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
32
34
|
|
@@ -34,62 +36,83 @@ module WordpressDeploy
|
|
34
36
|
exit(1)
|
35
37
|
end
|
36
38
|
|
37
|
-
desc "deploy",
|
38
|
-
|
39
|
-
|
39
|
+
desc "deploy FROM TO", <<-EOS
|
40
|
+
Deploy Wordpress onto the TO environment.
|
41
|
+
|
42
|
+
This is achieved by first generating the appropriate wp-config.php file for the
|
43
|
+
desired environment. This wp-config.php, along with all other files within the
|
44
|
+
wp_dir, are then transmitted to the configured TO environment.
|
45
|
+
|
46
|
+
Next, the FROM database is backed up into the sql_dir, and then sent to the
|
47
|
+
configured TO environment. Finally, all records in the TO database are scrubbed
|
48
|
+
to be relative to the new hostname configured for the environment (this
|
49
|
+
includes PHP serialized strings).
|
50
|
+
EOS
|
51
|
+
def deploy(from, to)
|
40
52
|
# Set Logger into verbose mode (if the user requested it)
|
41
53
|
Logger.verbose = options[:verbose]
|
42
54
|
|
43
55
|
# Set environment options
|
44
|
-
|
56
|
+
Config.set_options options
|
45
57
|
|
46
|
-
#
|
47
|
-
|
58
|
+
# Load ALL the available environments
|
59
|
+
WordpressDeploy::Environments.load
|
48
60
|
|
49
|
-
#
|
50
|
-
|
61
|
+
# Get the Environment the user requested
|
62
|
+
from = WordpressDeploy::Environments.find from.to_sym
|
63
|
+
to = WordpressDeploy::Environments.find to.to_sym
|
51
64
|
|
52
65
|
rescue => err
|
53
66
|
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
54
67
|
|
55
68
|
# Exit with an error
|
56
69
|
exit(1)
|
57
|
-
ensure
|
58
|
-
puts "Closing connection.".colorize(color: :red, background: :yellow) if ftp_client.close
|
59
70
|
end
|
60
71
|
|
61
|
-
desc "backup", "
|
62
|
-
def backup
|
63
|
-
##
|
72
|
+
desc "backup ENVIRONMENT", "Call mysqldump on the database specified by ENVIRONMENT"
|
73
|
+
def backup(environment)
|
64
74
|
# Set Logger into verbose mode (if the user requested it)
|
65
75
|
Logger.verbose = options[:verbose]
|
66
76
|
|
67
77
|
# Set environment options
|
68
|
-
|
78
|
+
Config.set_options options
|
79
|
+
|
80
|
+
# Load ALL the available environments
|
81
|
+
WordpressDeploy::Environments.load
|
69
82
|
|
70
|
-
#
|
71
|
-
|
83
|
+
# Get the Environment the user requested
|
84
|
+
env = WordpressDeploy::Environments.find environment.to_sym
|
72
85
|
|
73
|
-
#
|
74
|
-
|
86
|
+
# Backup the database to the sql_dir
|
87
|
+
env.database.save!
|
75
88
|
|
76
89
|
rescue => err
|
77
90
|
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
78
91
|
|
79
92
|
# Exit with an error
|
80
93
|
exit(1)
|
81
|
-
ensure
|
82
|
-
puts "Closing connection.".colorize(color: :red, background: :yellow) if ftp_client.close
|
83
94
|
end
|
84
95
|
|
85
|
-
desc "
|
86
|
-
def
|
87
|
-
##
|
96
|
+
desc "transmit ENVIRONMENT", "Transmit the files in wp_dir"
|
97
|
+
def transmit(environment)
|
88
98
|
# Set Logger into verbose mode (if the user requested it)
|
89
99
|
Logger.verbose = options[:verbose]
|
90
100
|
|
91
101
|
# Set environment options
|
92
|
-
|
102
|
+
Config.set_options options
|
103
|
+
|
104
|
+
# Load ALL the available environments
|
105
|
+
WordpressDeploy::Environments.load
|
106
|
+
|
107
|
+
# Get the Environment the user requested
|
108
|
+
env = WordpressDeploy::Environments.find environment.to_sym
|
109
|
+
|
110
|
+
# Save the configuration file
|
111
|
+
env.save_wp_config
|
112
|
+
|
113
|
+
# Send the files in wp_dir
|
114
|
+
env.transfer.transmit!
|
115
|
+
|
93
116
|
rescue => err
|
94
117
|
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
95
118
|
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module WordpressDeploy
|
2
|
+
##
|
3
|
+
# Config defines all of the locations of input and
|
4
|
+
# output files. Specifically, the locations of the test
|
5
|
+
# definitions, the locations of the test results, and
|
6
|
+
# the locations of the build applications.
|
7
|
+
module Config
|
8
|
+
|
9
|
+
##
|
10
|
+
# Setup required paths based on the given options
|
11
|
+
def self.set_options(options = {})
|
12
|
+
options.each do |option, value|
|
13
|
+
method = "#{option}="
|
14
|
+
send(method, value) if respond_to? method and !value.empty?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.logging=(new_log)
|
19
|
+
# Only set @@logging if new_log is a boolean
|
20
|
+
if !!new_log == new_log
|
21
|
+
@@logging = new_log
|
22
|
+
else
|
23
|
+
@@logging = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.logging?
|
28
|
+
@@logging ||= false
|
29
|
+
@@logging
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.root_dir=(new_root)
|
33
|
+
@@root_dir = new_root
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.root_dir
|
37
|
+
@@root_dir ||= Dir.pwd
|
38
|
+
File.expand_path @@root_dir
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.config_dir=(new_config_dir)
|
42
|
+
@@config_dir = new_config_dir
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.config_dir
|
46
|
+
@@config_dir ||= "config"
|
47
|
+
File.expand_path File.join(root_dir, @@config_dir)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.wp_dir=(new_wp_dir)
|
51
|
+
@@wp_dir = new_wp_dir
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.wp_dir
|
55
|
+
@@wp_dir ||= "site"
|
56
|
+
File.expand_path File.join(root_dir, @@wp_dir)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.sql_dir=(new_sql_dir)
|
60
|
+
@@sql_dir = new_sql_dir
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.sql_dir
|
64
|
+
@@sql_dir ||= "sql"
|
65
|
+
File.expand_path File.join(root_dir, @@sql_dir)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.log_file
|
69
|
+
@@log_file ||= "#{Time.now.strftime("%Y_%m_%d_%H_%M_%S")}.log"
|
70
|
+
File.expand_path File.join(root_dir, @@log_file)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.clean!
|
74
|
+
FileUtils.rm Dir.glob(File.join(root_dir, "*.log"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'tempfile'
|
2
|
+
require 'mysql2'
|
3
|
+
require 'php_serialize'
|
2
4
|
|
3
5
|
module WordpressDeploy
|
4
6
|
module Database
|
@@ -6,37 +8,296 @@ module WordpressDeploy
|
|
6
8
|
class MySql
|
7
9
|
include WordpressDeploy::Cli::Helpers
|
8
10
|
|
9
|
-
attr_reader :configuration
|
10
|
-
|
11
11
|
def initialize
|
12
|
-
@
|
12
|
+
@user ||= "root"
|
13
|
+
@password ||= ""
|
14
|
+
|
15
|
+
@host ||= "localhost"
|
16
|
+
@port ||= 3306
|
17
|
+
@socket ||= ""
|
18
|
+
@name ||= "wordpress"
|
19
|
+
|
20
|
+
@has_port ||= true
|
21
|
+
@has_socket ||= false
|
13
22
|
end
|
14
23
|
|
15
|
-
|
16
|
-
|
24
|
+
##
|
25
|
+
# Name of the database (DB_NAME)
|
26
|
+
def name(new_name = nil)
|
27
|
+
@name = new_name.to_s unless new_name.nil?
|
28
|
+
@name
|
17
29
|
end
|
18
30
|
|
19
|
-
|
20
|
-
|
31
|
+
##
|
32
|
+
# User credentials for the specified database
|
33
|
+
def user(new_user = nil)
|
34
|
+
@user = new_user.to_s unless new_user.nil?
|
35
|
+
@user
|
21
36
|
end
|
22
37
|
|
23
|
-
|
38
|
+
##
|
39
|
+
# Password credentials for the specified database
|
40
|
+
def password(new_password = nil)
|
41
|
+
@password = new_password.to_s unless new_password.nil?
|
42
|
+
@password
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Get just the hostname from DB_HOST. Only different from
|
47
|
+
# DB_HOST if DB_HOST has a socket or a port number in it.
|
48
|
+
def host(new_host = nil)
|
49
|
+
unless new_host.nil?
|
50
|
+
match = /(?<host>.*?)(?=:|\z)(:(?<socket>\/.*)|:(?<port>\d+))?/.match(new_host.to_s)
|
51
|
+
@host = match[:host].to_s unless match[:host].nil?
|
52
|
+
|
53
|
+
# Set the socket information
|
54
|
+
if @has_socket = !match[:socket].nil?
|
55
|
+
@has_socket = true
|
56
|
+
@socket = match[:socket]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set the port information
|
60
|
+
unless match[:port].nil?
|
61
|
+
@port = match[:port].to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
# Has port is true; unless a socket was set
|
65
|
+
@has_port = !@has_socket
|
66
|
+
end
|
67
|
+
|
68
|
+
# return the host
|
69
|
+
@host
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# This value should be able to be plugged directly into
|
74
|
+
# DB_HOST int he wp-config.php file.
|
75
|
+
def wp_host
|
76
|
+
extra = nil
|
77
|
+
extra = ":#{socket}" if socket?
|
78
|
+
extra = ":#{port}" if port?
|
79
|
+
"#{host}#{extra}"
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Extract just the port number from the DB_HOST
|
84
|
+
# configuration file. Or return the default port of 3306.
|
85
|
+
def port
|
86
|
+
@port
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Does DB_HOST contain a port number? (it does if one was
|
91
|
+
# specified and it does not equal 3306; the default MySQL
|
92
|
+
# port number.
|
93
|
+
def port?
|
94
|
+
@has_port && port != 3306
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Extract just the socket part from the DB_HOST
|
99
|
+
# configuration file. Or return an empty string if none.
|
100
|
+
def socket
|
101
|
+
@socket
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Does DB_HOST contain a socket path?
|
106
|
+
def socket?
|
107
|
+
@has_socket
|
108
|
+
end
|
109
|
+
|
110
|
+
def charset(new_charset = nil)
|
111
|
+
@charset = new_charset.to_s unless new_charset.nil?
|
112
|
+
@charset
|
113
|
+
end
|
24
114
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
password = configuration.DB_PASSWORD
|
30
|
-
db_name = configuration.DB_NAME
|
115
|
+
def collate(new_collate = nil)
|
116
|
+
@collate = new_collate.to_s unless new_collate.nil?
|
117
|
+
@collate
|
118
|
+
end
|
31
119
|
|
32
|
-
|
120
|
+
def table_prefix(new_prefix = nil)
|
121
|
+
@prefix = new_prefix.to_s unless new_prefix.nil?
|
122
|
+
@prefix
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# The file that the instance would save to if
|
127
|
+
# save is called.
|
128
|
+
def file
|
129
|
+
File.join(Config.sql_dir, "#{name}.sql")
|
33
130
|
end
|
34
131
|
|
35
132
|
##
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
133
|
+
# Save the database to a file locally.
|
134
|
+
#
|
135
|
+
# The database will be output into #file.
|
136
|
+
def save!
|
137
|
+
# Get the output from MySQL Dump
|
138
|
+
cmd = mysqldump
|
139
|
+
dump_str = run cmd
|
140
|
+
|
141
|
+
# Open the supplied file; or create a temporary one
|
142
|
+
file_io = File.new(file, 'w')
|
143
|
+
|
144
|
+
# Start writing to file
|
145
|
+
file_io.write(dump_str)
|
146
|
+
|
147
|
+
true
|
148
|
+
ensure
|
149
|
+
file_io.close unless file_io.nil?
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
#
|
154
|
+
def send!(to_config_name)
|
155
|
+
# Check to see if there is a SQL file
|
156
|
+
if File.exists? file
|
157
|
+
# Create the 'to' configuration
|
158
|
+
mysql = self.class.new(to_config_name)
|
159
|
+
|
160
|
+
# Open the source sql file for reading
|
161
|
+
tmp_file = Tempfile.new(["#{to_config_name}", '.sql'])
|
162
|
+
|
163
|
+
# Write sql to tmpfile while changing the
|
164
|
+
# the CREATE DATABASE and USE commands to make sense for
|
165
|
+
# the 'to' configuration
|
166
|
+
sql_dump = File.read(file)
|
167
|
+
sql_dump.gsub!(/^USE\ `#{self.DB_NAME}`/, "USE `#{mysql.DB_NAME}`")
|
168
|
+
tmp_file.puts sql_dump
|
169
|
+
|
170
|
+
# Get the MySQL load command
|
171
|
+
cmd = mysqlload to_config_name, tmp_file.path
|
172
|
+
|
173
|
+
# Run the mysql command to load the mysqldump into
|
174
|
+
# the destination mysql instance
|
175
|
+
run cmd
|
176
|
+
end
|
177
|
+
ensure
|
178
|
+
# Delete the temp file unless it was never made
|
179
|
+
tmp_file.unlink unless tmp_file.nil?
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
#
|
184
|
+
def migrate!(to_config_name)
|
185
|
+
mysql = self.class.new(to_config_name)
|
186
|
+
|
187
|
+
client = Mysql2::Client.new(
|
188
|
+
:host => mysql.db_hostname,
|
189
|
+
:username => mysql.DB_USER,
|
190
|
+
:password => mysql.DB_PASSWORD,
|
191
|
+
:port => mysql.db_port,
|
192
|
+
:database => mysql.DB_NAME,
|
193
|
+
#:socket = '/path/to/mysql.sock',
|
194
|
+
:encoding => mysql.DB_CHARSET
|
195
|
+
)
|
196
|
+
|
197
|
+
value_to_find = "localhost/~lindsey/huntsvillecrawfishboil.com"
|
198
|
+
value_to_replace = "huntsvillecrawfishboil.com"
|
199
|
+
escaped_value_to_find = client.escape(value_to_find)
|
200
|
+
|
201
|
+
# wp_options option_value
|
202
|
+
sql = <<-EOS
|
203
|
+
SELECT `option_id`, `option_value`
|
204
|
+
FROM `wp_options`
|
205
|
+
WHERE `option_value` REGEXP '#{escaped_value_to_find}';
|
206
|
+
EOS
|
207
|
+
wp_options = client.query(sql)
|
208
|
+
wp_options.each do |row|
|
209
|
+
row.each do |key, value|
|
210
|
+
if PHP.serialized?(value)
|
211
|
+
ruby_php = PHP.unserialize(value)
|
212
|
+
ruby_php.find_and_replace!(value_to_find, value_to_replace)
|
213
|
+
value.replace PHP.serialize(ruby_php)
|
214
|
+
else
|
215
|
+
value.gsub!(/#{value_to_find}/, value_to_replace) if value.instance_of? String
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Update the database
|
220
|
+
sql = <<-EOD
|
221
|
+
UPDATE `wp_options`
|
222
|
+
SET `option_value`='#{client.escape(row['option_value'])}'
|
223
|
+
WHERE `option_id` = #{row['option_id']};
|
224
|
+
EOD
|
225
|
+
Logger.debug sql
|
226
|
+
client.query(sql)
|
227
|
+
end
|
228
|
+
|
229
|
+
# wp_posts post_content, guid
|
230
|
+
sql = <<-EOS
|
231
|
+
SELECT `ID`, `post_content`, `guid`
|
232
|
+
FROM `wp_posts`
|
233
|
+
WHERE `post_content` REGEXP '#{escaped_value_to_find}'
|
234
|
+
AND `guid` REGEXP '#{escaped_value_to_find}';
|
235
|
+
EOS
|
236
|
+
wp_posts = client.query(sql)
|
237
|
+
wp_posts.each do |row|
|
238
|
+
row.each do |key, value|
|
239
|
+
if PHP.serialized?(value)
|
240
|
+
ruby_php = PHP.unserialize(value)
|
241
|
+
ruby_php.find_and_replace!(value_to_find, value_to_replace)
|
242
|
+
value.replace PHP.serialize(ruby_php)
|
243
|
+
else
|
244
|
+
value.gsub!(/#{value_to_find}/, value_to_replace) if value.instance_of? String
|
245
|
+
end
|
246
|
+
end
|
247
|
+
sql = <<-EOD
|
248
|
+
UPDATE `wp_posts`
|
249
|
+
SET `post_content` = '#{client.escape(row['post_content'])}',
|
250
|
+
`guid` = '#{client.escape(row['guid'])}'
|
251
|
+
WHERE `ID` = #{row['ID']};
|
252
|
+
EOD
|
253
|
+
Logger.debug sql
|
254
|
+
client.query(sql)
|
255
|
+
end
|
256
|
+
|
257
|
+
# wp_postmeta
|
258
|
+
sql = <<-EOS
|
259
|
+
SELECT `meta_id`, `meta_value`
|
260
|
+
FROM `wp_postmeta`
|
261
|
+
WHERE `meta_value` REGEXP '#{escaped_value_to_find}';
|
262
|
+
EOS
|
263
|
+
wp_postmeta = client.query(sql)
|
264
|
+
wp_postmeta.each do |row|
|
265
|
+
row.each do |key, value|
|
266
|
+
if PHP.serialized?(value)
|
267
|
+
ruby_php = PHP.unserialize(value)
|
268
|
+
ruby_php.find_and_replace!(value_to_find, value_to_replace)
|
269
|
+
value.replace PHP.serialize(ruby_php)
|
270
|
+
else
|
271
|
+
value.gsub!(/#{value_to_find}/, value_to_replace) if value.instance_of? String
|
272
|
+
end
|
273
|
+
end
|
274
|
+
sql = <<-EOD
|
275
|
+
UPDATE `wp_postmeta`
|
276
|
+
SET `meta_value` = '#{client.escape(row['meta_value'])}'
|
277
|
+
WHERE `meta_id` = #{row['meta_id']};
|
278
|
+
EOD
|
279
|
+
Logger.debug sql
|
280
|
+
client.query(sql)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
|
286
|
+
def mysqldump
|
287
|
+
arguments = "-P \"#{port}\" -h \"#{host}\" -u \"#{user}\" -p\"#{password}\" -B \"#{name}\""
|
288
|
+
"#{utility("mysqldump")} #{arguments}"
|
289
|
+
end
|
290
|
+
|
291
|
+
def mysqlload(config_name, file_name)
|
292
|
+
mysql = self.class.new config_name
|
293
|
+
arg_port = mysql.db_port
|
294
|
+
arg_host = mysql.db_hostname
|
295
|
+
arg_user = mysql.DB_USER
|
296
|
+
arg_pass = mysql.DB_PASSWORD
|
297
|
+
arg_name = mysql.DB_NAME
|
298
|
+
arguments = "-P \"#{arg_port}\" -u \"#{arg_user}\" -h \"#{arg_host}\" -p\"#{arg_pass}\" -D \"#{arg_name}\""
|
299
|
+
|
300
|
+
"#{utility("mysql")} #{arguments} < #{file_name}"
|
40
301
|
end
|
41
302
|
|
42
303
|
end
|