| 1 | #!/usr/bin/perl |
|---|
| 2 | # $Id:$ |
|---|
| 3 | use strict; |
|---|
| 4 | use warnings; |
|---|
| 5 | |
|---|
| 6 | use lib 't/lib', 'extlib', 'lib', '../lib', '../extlib'; |
|---|
| 7 | use Test::More qw(no_plan);#tests => 3598; |
|---|
| 8 | |
|---|
| 9 | use MT; |
|---|
| 10 | use MT::Tag; |
|---|
| 11 | use MT::Author; |
|---|
| 12 | use MT::Blog; |
|---|
| 13 | use MT::Role; |
|---|
| 14 | use MT::Category; |
|---|
| 15 | use MT::Entry; |
|---|
| 16 | use MT::TBPing; |
|---|
| 17 | use MT::Comment; |
|---|
| 18 | use MT::Test qw(:db :data); |
|---|
| 19 | |
|---|
| 20 | use vars qw( $DB_DIR $T_CFG ); |
|---|
| 21 | |
|---|
| 22 | use MT::BackupRestore; |
|---|
| 23 | use Data::Dumper; |
|---|
| 24 | |
|---|
| 25 | system("rm t/db/* 2>null"); |
|---|
| 26 | |
|---|
| 27 | my @emails = ( 'fumiakiy@sixapart.jp', 'fyoshimatsu@sixapart.com' ); |
|---|
| 28 | my $chuck = MT::Author->load({ name => 'Chuck D' }); |
|---|
| 29 | my $bob = MT::Author->load({ name => 'Bob D' }); |
|---|
| 30 | my $mel = MT::Author->load({ name => 'Melody' }); |
|---|
| 31 | &setup; |
|---|
| 32 | |
|---|
| 33 | my $mt = MT->new( Config => $T_CFG ) or die MT->errstr; |
|---|
| 34 | isa_ok($mt, 'MT'); |
|---|
| 35 | |
|---|
| 36 | my $backup_data = ''; |
|---|
| 37 | my $printer = sub { $backup_data .= $_[0] }; |
|---|
| 38 | |
|---|
| 39 | my %skip = ( |
|---|
| 40 | 'session' => 1, |
|---|
| 41 | 'config' => 1, |
|---|
| 42 | 'schwartz_job' => 1, |
|---|
| 43 | 'schwartz_error' => 1, |
|---|
| 44 | 'schwartz_funcmap' => 1, |
|---|
| 45 | 'schwartz_exitstatus' => 1, |
|---|
| 46 | ); |
|---|
| 47 | my %oldies; |
|---|
| 48 | my $types = MT->registry('object_types'); |
|---|
| 49 | foreach my $key (keys %$types) { |
|---|
| 50 | next if exists $skip{$key}; |
|---|
| 51 | next if $key =~ /\w+\.\w+/; # skip subclasses |
|---|
| 52 | my $iter = MT->model($key)->load_iter; |
|---|
| 53 | my @data; |
|---|
| 54 | while ( my $obj = $iter->() ) { |
|---|
| 55 | push @data, $obj unless $obj->can('class') && ($obj->class ne $key); |
|---|
| 56 | } |
|---|
| 57 | $oldies{$key} = \@data; |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | MT::BackupRestore->backup(undef, $printer, sub {}, sub {}, sub { print $_[0], "\n"; }, 0, 'UTF-8'); |
|---|
| 61 | |
|---|
| 62 | use IO::String; |
|---|
| 63 | my $h = IO::String->new(\$backup_data); |
|---|
| 64 | my (%objects, %deferred, @errors); |
|---|
| 65 | MT::BackupRestore->restore_process_single_file($h, \%objects, \%deferred, \@errors, "4.0", 0, sub { print $_[0], "\n"; }); |
|---|
| 66 | |
|---|
| 67 | is(scalar(keys %deferred), 0, 'no deferred objects remain'); |
|---|
| 68 | warn join "\n", @errors if @errors; |
|---|
| 69 | is(scalar(@errors), 0, 'no error during backup'); |
|---|
| 70 | &checkthemout(\%oldies, \%objects); |
|---|
| 71 | |
|---|
| 72 | &finish; |
|---|
| 73 | require MIME::Base64; |
|---|
| 74 | |
|---|
| 75 | sub checkthemout { |
|---|
| 76 | my ($oldies, $objects) = @_; |
|---|
| 77 | foreach my $name (keys %$oldies) { |
|---|
| 78 | my $old_objects = $oldies->{$name}; |
|---|
| 79 | my %meta; |
|---|
| 80 | for my $old (@$old_objects) { |
|---|
| 81 | my $class = MT->model($name); |
|---|
| 82 | isnt($class, undef, "$name must be valid"); |
|---|
| 83 | if ($class =~ /MT::Asset(::.+)*/) { |
|---|
| 84 | $class = 'MT::Asset'; |
|---|
| 85 | } |
|---|
| 86 | my $key = "$class#" . $old->id; |
|---|
| 87 | my $tmp_obj = $objects->{$key}; |
|---|
| 88 | isnt(undef, $tmp_obj, "$key must not hold undef"); |
|---|
| 89 | my $obj = $class->load($tmp_obj->id, {cached_ok=>0}); |
|---|
| 90 | isnt($obj, undef); |
|---|
| 91 | for my $col (@{$obj->column_names}) { |
|---|
| 92 | next if $col eq 'id'; |
|---|
| 93 | if ($col =~ /(\w+)_id$/) { |
|---|
| 94 | my $parent_name = $1; |
|---|
| 95 | my $parent_class = MT->model($parent_name); |
|---|
| 96 | next if !defined($parent_class); |
|---|
| 97 | if ('ARRAY' ne ref($parent_class)) { |
|---|
| 98 | $parent_class = [ $parent_class ]; |
|---|
| 99 | } |
|---|
| 100 | my $old_parent_id = $old->column($col); |
|---|
| 101 | next if !defined($old_parent_id); # like MT::Entry's category_id... |
|---|
| 102 | next if $old_parent_id eq '0'; # like MT::Trackback's category_id... |
|---|
| 103 | my $parent; |
|---|
| 104 | foreach (@$parent_class) { |
|---|
| 105 | my $parent_key = $_ . '#' . $old_parent_id; |
|---|
| 106 | my $new_parent = $objects->{$parent_key}; |
|---|
| 107 | next unless $new_parent; |
|---|
| 108 | $parent = $_->load($new_parent->id); |
|---|
| 109 | last if $parent; |
|---|
| 110 | } |
|---|
| 111 | unless ($parent) { |
|---|
| 112 | # try the other way to find package name for the parents |
|---|
| 113 | my $parents_hash = $class->parents; |
|---|
| 114 | $parent_class = $parents_hash->{$col} if $parents_hash; |
|---|
| 115 | if ( ref($parent_class) eq 'HASH' ) { |
|---|
| 116 | $parent_class = $parent_class->{class}; |
|---|
| 117 | } |
|---|
| 118 | if ( !$parent_class && ($col eq 'entry_id') && ('MT::Trackback' eq $class) ) { |
|---|
| 119 | $parent_class = [ MT->model('entry'), MT->model('page') ]; |
|---|
| 120 | } |
|---|
| 121 | if ( $parent_class && ( 'ARRAY' eq ref($parent_class) ) ) { |
|---|
| 122 | foreach (@$parent_class) { |
|---|
| 123 | my $parent_key = $_ . '#' . $old_parent_id; |
|---|
| 124 | my $new_parent = $objects->{$parent_key}; |
|---|
| 125 | next unless $new_parent; |
|---|
| 126 | $parent = $_->load($new_parent->id); |
|---|
| 127 | last if $parent; |
|---|
| 128 | } |
|---|
| 129 | } |
|---|
| 130 | } |
|---|
| 131 | isnt(undef, $parent, "parent object(" . $old->id . ") of $class pointed to by $col should not be undef"); |
|---|
| 132 | } else { |
|---|
| 133 | next if $col eq 'modified_on'; |
|---|
| 134 | next if ( |
|---|
| 135 | (defined($old->column($col)) && ($old->column($col) eq '')) && |
|---|
| 136 | (!defined($obj->column($col))) |
|---|
| 137 | ); |
|---|
| 138 | next if ($name eq 'category' && ($col eq 'parent')); |
|---|
| 139 | next if ($name eq 'folder' && ($col eq 'parent')); |
|---|
| 140 | if ( ($name eq 'trackback') && ($col eq 'is_disabled') ) { |
|---|
| 141 | if ( defined($obj->is_disabled) && $obj->is_disabled |
|---|
| 142 | && (!defined($obj->entry->allow_pings) || ($obj->entry->allow_pings == 0)) ) |
|---|
| 143 | { |
|---|
| 144 | # is_disabled will be changed upon $entry->save |
|---|
| 145 | # and save may occur $comment's post_save trigger |
|---|
| 146 | # no harm for the testing purpose, ignore the case. |
|---|
| 147 | next; |
|---|
| 148 | } |
|---|
| 149 | } |
|---|
| 150 | if ('HASH' eq ref($old->$col)) { |
|---|
| 151 | is(Dumper($old->$col), Dumper($old->$col), $col); |
|---|
| 152 | } elsif ('blob' eq $obj->column_defs->{$col}->{type}) { |
|---|
| 153 | is( |
|---|
| 154 | MIME::Base64::encode_base64($old->$col, ''), |
|---|
| 155 | MIME::Base64::encode_base64($obj->$col, ''), |
|---|
| 156 | "blob - $col"); |
|---|
| 157 | } else { |
|---|
| 158 | is($old->$col, $obj->$col, "$class<$col>" . $obj->id); |
|---|
| 159 | } |
|---|
| 160 | } |
|---|
| 161 | } |
|---|
| 162 | unless ( exists($meta{ref($obj)}) ) { |
|---|
| 163 | my @metacolumns = MT::Meta->metadata_by_class( ref($obj) ); |
|---|
| 164 | my %metacolumns = map { $_->{name} => $_->{type} } @metacolumns; |
|---|
| 165 | $meta{ref($obj)} = \%metacolumns |
|---|
| 166 | } |
|---|
| 167 | my $metacolumns = $meta{ref($obj)}; |
|---|
| 168 | foreach my $metacol (keys %$metacolumns) { |
|---|
| 169 | if ( my $type = $metacolumns->{$metacol} ) { |
|---|
| 170 | if ( 'vblob' eq $type ) { |
|---|
| 171 | if ( defined($old->$metacol) && defined($obj->$metacol) ) { |
|---|
| 172 | is( |
|---|
| 173 | MIME::Base64::encode_base64($old->$metacol, ''), |
|---|
| 174 | MIME::Base64::encode_base64($obj->$metacol, ''), |
|---|
| 175 | "vblob - $metacol"); |
|---|
| 176 | } |
|---|
| 177 | } |
|---|
| 178 | else { |
|---|
| 179 | is($old->$metacol, $obj->$metacol, "$class<meta:$metacol>" . $obj->id); |
|---|
| 180 | } |
|---|
| 181 | } |
|---|
| 182 | } |
|---|
| 183 | } |
|---|
| 184 | } |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | sub finish { |
|---|
| 188 | use MT::Notification; |
|---|
| 189 | MT::Notification->remove({email => $_}) foreach @emails; |
|---|
| 190 | |
|---|
| 191 | use MT::TBPing; |
|---|
| 192 | MT::TBPing->remove({tb_id=>2, blog_id=>1,id=>2}); |
|---|
| 193 | |
|---|
| 194 | use MT::Role; |
|---|
| 195 | MT::Role->remove; |
|---|
| 196 | |
|---|
| 197 | use MT::Association; |
|---|
| 198 | MT::Association->remove; |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | sub setup { |
|---|
| 202 | use MT::Notification; |
|---|
| 203 | my $note = MT::Notification->new; |
|---|
| 204 | $note->email($emails[0]); |
|---|
| 205 | $note->blog_id(1); |
|---|
| 206 | $note->save; |
|---|
| 207 | $note = undef; |
|---|
| 208 | my $note2 = MT::Notification->new; |
|---|
| 209 | $note2->email($emails[1]); |
|---|
| 210 | $note2->blog_id(1); |
|---|
| 211 | $note2->save; |
|---|
| 212 | $note2 = undef; |
|---|
| 213 | |
|---|
| 214 | my $cat = MT::Category->load({ label => 'bar', blog_id => 1}); |
|---|
| 215 | if ($cat) { |
|---|
| 216 | $cat->allow_pings(1); |
|---|
| 217 | $cat->save; |
|---|
| 218 | } |
|---|
| 219 | |
|---|
| 220 | require MT::TBPing; |
|---|
| 221 | my $ping = MT::TBPing->load(2); |
|---|
| 222 | if (!$ping) { |
|---|
| 223 | $ping = new MT::TBPing; |
|---|
| 224 | $ping->tb_id(2); |
|---|
| 225 | $ping->blog_id(1); |
|---|
| 226 | $ping->ip('127.0.0.1'); |
|---|
| 227 | $ping->title('Cat Trackback'); |
|---|
| 228 | $ping->excerpt('Foo Bar Baz Quux'); |
|---|
| 229 | $ping->source_url('http://example.net/'); |
|---|
| 230 | $ping->blog_name("Example Blog 2"); |
|---|
| 231 | $ping->created_on('20050405000000'); |
|---|
| 232 | $ping->id(2); |
|---|
| 233 | $ping->visible(1); |
|---|
| 234 | $ping->save |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | my @default_roles = ( |
|---|
| 238 | # { name => 'System Administrator', |
|---|
| 239 | # perms => ['administer'] }, |
|---|
| 240 | # { name => 'System Designer', |
|---|
| 241 | # perms => ['edit_templates', 'rebuild'] }, |
|---|
| 242 | { name => 'Weblog Administrator', |
|---|
| 243 | description => 'Can administer the weblog.', |
|---|
| 244 | perms => ['administer_blog'] }, |
|---|
| 245 | { name => 'Designer', |
|---|
| 246 | description => 'Can edit, manage and rebuild weblog templates.', |
|---|
| 247 | perms => ['edit_templates', 'rebuild'] }, |
|---|
| 248 | { name => 'Editor', |
|---|
| 249 | description => 'Can edit all entries/categories/tags on a weblog and rebuild.', |
|---|
| 250 | perms => ['edit_all_posts', 'edit_categories', 'rebuild', 'edit_tags'], }, |
|---|
| 251 | { name => 'Editor (can upload)', |
|---|
| 252 | description => 'Can upload files, edit all entries/categories/tags on a weblog and rebuild.', |
|---|
| 253 | perms => ['edit_all_posts', 'edit_categories', 'edit_tags', 'rebuild', 'upload'], }, |
|---|
| 254 | { name => 'Publisher', |
|---|
| 255 | description => 'Can upload files, edit all entries/categories/tags on a weblog, rebuild and send notifications.', |
|---|
| 256 | perms => ['edit_all_posts', 'edit_categories', 'edit_tags', 'send_notifications', 'rebuild', 'upload'], }, |
|---|
| 257 | # { name => 'Writer', |
|---|
| 258 | # description => 'Can create entries and edit their own.', |
|---|
| 259 | # perms => ['post'], }, |
|---|
| 260 | # { name => 'Writer (can upload)', |
|---|
| 261 | # description => 'Can create entries, edit their own and upload files.', |
|---|
| 262 | # perms => ['post', 'upload'], }, |
|---|
| 263 | # { name => 'System Blog Administrator', |
|---|
| 264 | # perms => ['administer_blog'] }, |
|---|
| 265 | ); |
|---|
| 266 | |
|---|
| 267 | require MT::Role; |
|---|
| 268 | foreach my $r (@default_roles) { |
|---|
| 269 | my $role = MT::Role->new(); |
|---|
| 270 | $role->name(MT->translate($r->{name})); |
|---|
| 271 | $role->description(MT->translate($r->{description})); |
|---|
| 272 | $role->clear_full_permissions; |
|---|
| 273 | $role->set_these_permissions($r->{perms}); |
|---|
| 274 | if ($r->{name} =~ m/^System/) { |
|---|
| 275 | $role->is_system(1); |
|---|
| 276 | } |
|---|
| 277 | $role->save; |
|---|
| 278 | } |
|---|
| 279 | |
|---|
| 280 | require MT::Association; |
|---|
| 281 | my $b1 = MT::Blog->load(1); |
|---|
| 282 | my $r = MT::Role->load({ name => 'Weblog Administrator' }); |
|---|
| 283 | MT::Association->link($chuck => $r => $b1); # Chuck is a weblog admin |
|---|
| 284 | |
|---|
| 285 | my $r2 = MT::Role->load({ name => 'Publisher' }); |
|---|
| 286 | MT::Association->link($bob => $r2 => $b1); # Bob is a publisher |
|---|
| 287 | |
|---|
| 288 | my $r3 = MT::Role->load({ name => 'Writer' }); |
|---|
| 289 | MT::Association->link($mel => $r3 => $b1); # Melody is a writer |
|---|
| 290 | } |
|---|