~srushe/expression-engine-migrator.ee_addon

ref: e6b3c44e916710257084910c65e10cf0afa2bb2b expression-engine-migrator.ee_addon/ee_migrator.rb -rw-r--r-- 10.1 KiB
e6b3c44e — Stephen Rushe Remove some debugging output 13 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env ruby

# ---------------------------------------------------------------------
#
# Name   : ExpressionEngine Migrator
# Version: 1.5
# Author : Stephen Rushe
# URL    : http://github.com/srushe/expression-engine-migrator.ee_addon
#
# This work is licensed under the Creative Commons Attribution-Share
# Alike 3.0 Unported License. To view a copy of this license, visit
# http://creativecommons.org/licenses/by-sa/3.0/
#
# ---------------------------------------------------------------------

require 'optparse'

# ---------------------------------------------------------------------
# A simple helper method to see if we have valid options.
# ---------------------------------------------------------------------
def all_or_none_specified(first, second)
  first_specified  = (first.nil? or first == '') ? false : true
  second_specified = (second.nil? or second == '') ? false : true
  return !(first_specified ^ second_specified)
end

# ---------------------------------------------------------------------
# Deal with any command-line options.
# ---------------------------------------------------------------------
options = { :table_prefix => 'exp', :all_data => false }
OptionParser.new do |opts|
  opts.banner = "Usage: #{$0} [options]"

  opts.on("-a", "--all_data",
          "Keep all data in the transformation") do |a|
    options[:all_data] = a
  end

  opts.on("-t", "--table_prefix [PREFIX]",
          "Specify the database table prefix") do |t|
    options[:table_prefix] = t || 'exp'
    options[:table_prefix].sub!(/_$/, '')  # Ensure extension doesn't end with a _
  end

  opts.on("-c", "--current_domain [DOMAIN NAME]",
          "Specify the domain name for the current site") do |c|
    options[:current_domain] = c
  end

  opts.on("-n", "--new_domain [DOMAIN NAME]",
          "Specify the domain name for the new site") do |n|
    options[:new_domain] = n
  end

  opts.on("-s", "--current_path [CURRENT SITE PATH]",
          "Specify the file system path to the current site") do |c|
    options[:current_path] = c
  end

  opts.on("-p", "--new_path [NEW SITE PATH]",
          "Specify the file system path to the new site") do |n|
    options[:new_path] = n
  end
end.parse!

# ---------------------------------------------------------------------
# Check that we have all of the data we require.
# ---------------------------------------------------------------------
valid_parameters = true

unless all_or_none_specified(options[:current_domain], options[:new_domain])
  $stderr.puts "You must specify either both domains or none"
  valid_parameters = false
end
unless all_or_none_specified(options[:current_path], options[:new_path])
  $stderr.puts "You must specify either both paths or none"
  valid_parameters = false
end
unless options[:table_prefix]
  $stderr.puts "Required option --table_prefix missing"
  valid_parameters = false
end

# ---------------------------------------------------------------------
# The web directories *must* be provided with starting slashes, unless
# they're empty. We'll add trailing ones if required though.
# ---------------------------------------------------------------------
[ :current_path, :new_path ].each do |opt|
  if options[opt]
    unless /^\//.match(options[opt])
      valid_parameters = false
      $stderr.puts "The option --#{opt} must have a leading slash"
    end
    options[opt] << '/' unless /\/$/.match(options[opt])
  end
end
exit unless valid_parameters

# ---------------------------------------------------------------------
# Store the parameters in nice little variables.
# ---------------------------------------------------------------------
table_prefix      = options[:table_prefix]
current_domain    = options[:current_domain]
new_domain        = options[:new_domain]
current_path      = options[:current_path]
new_path          = options[:new_path]

# -------------------------------------------------------------------
# Skip the rest of the changes unless the domain name or the site
# path has changed.
# -------------------------------------------------------------------
unless ((current_domain != new_domain) or (current_path != new_path))
  $stderr.puts "The domain or web path must be updated"
  exit
end

# ---------------------------------------------------------------------
# Do we have a file to process and does it exist?
# ---------------------------------------------------------------------
if ARGV[0].nil?
  $stderr.puts "You must specify a file"
  exit
end
filename = ARGV[0]

unless File.exist?(filename)
  $stderr.puts "The file #{filename} does not exist"
  exit
end

# ---------------------------------------------------------------------
# Open the database file for reading.
# ---------------------------------------------------------------------
db_file = File.new(filename, "r")

# ---------------------------------------------------------------------
# Process the lines one at a time.
# ---------------------------------------------------------------------
while (line = db_file.gets)
  line.chomp

  # -------------------------------------------------------------------
  # Skip unless it's an INSERT.
  # -------------------------------------------------------------------
  unless /^INSERT INTO /i.match(line)
    puts line
    next
  end

  # -------------------------------------------------------------------
  # Leave out certain lines unless we're keeping all data.
  # -------------------------------------------------------------------
  unless options[:all_data]
    next if /^INSERT INTO `?#{table_prefix}_captcha`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_cp_log`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_email_cache(|_mg|_ml)`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_email_console_cache`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_email_tracker`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_freeform_entries`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_freeform_params`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_mailing_list`? /i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_mailing_list_queue`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_message_attachments`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_message_copies`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_message_data`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_message_listed`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_password_lockout`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_referrers`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_reset_password`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_search`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_search_log`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_security_hashes`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_sessions`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_throttle`?/i.match(line)
    next if /^INSERT INTO `?#{table_prefix}_trackbacks`?/i.match(line)
  end
  
  # -------------------------------------------------------------------
  # If we're dealing with an INSERT into a table which uses serialised
  # data then we need to perform some recalculation of the offset.
  # -------------------------------------------------------------------
  if /^INSERT INTO `?#{table_prefix}_(extensions|relationships|sites)`?/i.match(line)
    
    # -----------------------------------------------------------------
    # Replace the domain name if it has changed.
    # -----------------------------------------------------------------
    if (current_path and (current_path != new_path))
      while matches = /(\}|;)s:(\d+):\\"#{current_path.gsub('/', '\/')}(.*?)\\";/.match(line)
        full_match      = matches[0]
        start_char      = matches[1]
        characters      = matches[2]
        post_domain_str = matches[3]

        replacement_string  = "#{start_char}s:#{characters.to_i + new_path.length - current_path.length}:"
        replacement_string << "\\\"#{new_path}#{post_domain_str}\\\";"
        line.gsub!(/#{Regexp.escape(full_match)}/, replacement_string)
      end
    end

    if (current_domain and (current_domain != new_domain))
      # ---------------------------------------------------------------
      # What string should we check for when looking for the current
      # domain?
      # ---------------------------------------------------------------
      current_domain_re = /^http:\/\//.match(current_domain) ? Regexp.new(/#{current_domain}/) : Regexp.new(/http:\/\/#{current_domain}/)

      # ---------------------------------------------------------------
      # What string should we replace the current domain with?
      # ---------------------------------------------------------------
      new_domain_string = /^http:\/\//.match(new_domain) ? new_domain : "http://#{new_domain}"
                                     
      while matches = /(\}|;)s:(\d+):\\"#{current_domain_re}(.*?)\\";/i.match(line)
        full_match      = matches[0]
        start_char      = matches[1]
        characters      = matches[2]
        post_domain_str = matches[3]
        
        replacement_string  = "#{start_char}s:#{characters.to_i + new_domain.length - current_domain.length}:"
        replacement_string << "\\\"#{new_domain_string}#{post_domain_str}\\\";"
        line.gsub!(/#{Regexp.escape(full_match)}/, replacement_string)
      end
    end
    
  # -------------------------------------------------------------------
  # If we're dealing with an INSERT into a table which doesn't use
  # serialised data then we can do a simple replace.
  # -------------------------------------------------------------------
  else
    if current_path and (current_path != new_path)
      line.gsub!(/#{current_path.gsub('/', '\/')}/, "#{new_path}")
    end
    if current_domain and (current_domain != new_domain)
      line.gsub!(/#{current_domain}/, "#{new_domain}")
    end
  end

  # -------------------------------------------------------------------
  # Print out the converted line.
  # -------------------------------------------------------------------
  puts line
end