| 1 | # Movable Type (r) Open Source (C) 2001-2008 Six Apart, Ltd. |
|---|
| 2 | # This program is distributed under the terms of the |
|---|
| 3 | # GNU General Public License, version 2. |
|---|
| 4 | # |
|---|
| 5 | # $Id$ |
|---|
| 6 | |
|---|
| 7 | package MT::CMS::Template; |
|---|
| 8 | |
|---|
| 9 | use strict; |
|---|
| 10 | |
|---|
| 11 | sub edit { |
|---|
| 12 | my $cb = shift; |
|---|
| 13 | my ($app, $id, $obj, $param) = @_; |
|---|
| 14 | |
|---|
| 15 | my $q = $app->param; |
|---|
| 16 | my $blog_id = $q->param('blog_id'); |
|---|
| 17 | |
|---|
| 18 | # FIXME: enumeration of types |
|---|
| 19 | unless ( $blog_id ) { |
|---|
| 20 | my $type = $q->param('type') || ( $obj ? $obj->type : undef ); |
|---|
| 21 | return $app->return_to_dashboard( redirect => 1 ) |
|---|
| 22 | if $type eq 'archive' |
|---|
| 23 | || $type eq 'individual' |
|---|
| 24 | || $type eq 'category' |
|---|
| 25 | || $type eq 'page' |
|---|
| 26 | || $type eq 'index'; |
|---|
| 27 | } |
|---|
| 28 | |
|---|
| 29 | my $type = $q->param('_type'); |
|---|
| 30 | my $blog = $app->blog; |
|---|
| 31 | my $cfg = $app->config; |
|---|
| 32 | my $perms = $app->permissions; |
|---|
| 33 | my $can_preview = 0; |
|---|
| 34 | |
|---|
| 35 | if ($blog) { |
|---|
| 36 | # include_system/include_cache are only applicable |
|---|
| 37 | # to blog-level templates |
|---|
| 38 | $param->{include_system} = $blog->include_system; |
|---|
| 39 | $param->{include_cache} = $blog->include_cache; |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | if ($id) { |
|---|
| 43 | # FIXME: Template types should not be enumerated here |
|---|
| 44 | $param->{nav_templates} = 1; |
|---|
| 45 | my $tab; |
|---|
| 46 | if ( $obj->type eq 'index' ) { |
|---|
| 47 | $tab = 'index'; |
|---|
| 48 | $param->{template_group_trans} = $app->translate('index'); |
|---|
| 49 | } |
|---|
| 50 | elsif ($obj->type eq 'archive' |
|---|
| 51 | || $obj->type eq 'individual' |
|---|
| 52 | || $obj->type eq 'category' |
|---|
| 53 | || $obj->type eq 'page' ) |
|---|
| 54 | { |
|---|
| 55 | |
|---|
| 56 | # FIXME: enumeration of types |
|---|
| 57 | $tab = 'archive'; |
|---|
| 58 | $param->{template_group_trans} = $app->translate('archive'); |
|---|
| 59 | } |
|---|
| 60 | elsif ( $obj->type eq 'custom' ) { |
|---|
| 61 | $tab = 'module'; |
|---|
| 62 | $param->{template_group_trans} = $app->translate('module'); |
|---|
| 63 | } |
|---|
| 64 | elsif ( $obj->type eq 'widget' ) { |
|---|
| 65 | $tab = 'widget'; |
|---|
| 66 | $param->{template_group_trans} = $app->translate('widget'); |
|---|
| 67 | } |
|---|
| 68 | elsif ( $obj->type eq 'email' ) { |
|---|
| 69 | $tab = 'email'; |
|---|
| 70 | $param->{template_group_trans} = $app->translate('email'); |
|---|
| 71 | } |
|---|
| 72 | else { |
|---|
| 73 | $tab = 'system'; |
|---|
| 74 | $param->{template_group_trans} = $app->translate('system'); |
|---|
| 75 | } |
|---|
| 76 | $param->{template_group} = $tab; |
|---|
| 77 | $blog_id = $obj->blog_id; |
|---|
| 78 | |
|---|
| 79 | # FIXME: enumeration of types |
|---|
| 80 | $param->{has_name} = $obj->type eq 'index' |
|---|
| 81 | || $obj->type eq 'custom' |
|---|
| 82 | || $obj->type eq 'widget' |
|---|
| 83 | || $obj->type eq 'archive' |
|---|
| 84 | || $obj->type eq 'category' |
|---|
| 85 | || $obj->type eq 'page' |
|---|
| 86 | || $obj->type eq 'individual'; |
|---|
| 87 | if ( !$param->{has_name} ) { |
|---|
| 88 | $param->{ 'type_' . $obj->type } = 1; |
|---|
| 89 | $param->{name} = $obj->name; |
|---|
| 90 | } |
|---|
| 91 | $app->add_breadcrumb( $param->{name} ); |
|---|
| 92 | $param->{has_outfile} = $obj->type eq 'index'; |
|---|
| 93 | $param->{has_rebuild} = |
|---|
| 94 | ( ( $obj->type eq 'index' ) |
|---|
| 95 | && ( ( $blog->custom_dynamic_templates || "" ) ne 'all' ) ); |
|---|
| 96 | |
|---|
| 97 | # FIXME: enumeration of types |
|---|
| 98 | $param->{is_special} = $param->{type} ne 'index' |
|---|
| 99 | && $param->{type} ne 'archive' |
|---|
| 100 | && $param->{type} ne 'category' |
|---|
| 101 | && $param->{type} ne 'page' |
|---|
| 102 | && $param->{type} ne 'individual'; |
|---|
| 103 | $param->{has_build_options} = $param->{has_build_options} |
|---|
| 104 | && $param->{type} ne 'custom' |
|---|
| 105 | && $param->{type} ne 'widget' |
|---|
| 106 | && !$param->{is_special}; |
|---|
| 107 | $param->{search_label} = $app->translate('Templates'); |
|---|
| 108 | $param->{object_type} = 'template'; |
|---|
| 109 | my $published_url = $obj->published_url; |
|---|
| 110 | $param->{published_url} = $published_url if $published_url; |
|---|
| 111 | $param->{saved_rebuild} = 1 if $q->param('saved_rebuild'); |
|---|
| 112 | |
|---|
| 113 | my $filter = $app->param('filter_key'); |
|---|
| 114 | if ($param->{template_group} eq 'email') { |
|---|
| 115 | $app->param( 'filter_key', 'email_templates' ); |
|---|
| 116 | }elsif ($param->{template_group} eq 'system') { |
|---|
| 117 | $app->param( 'filter_key', 'system_templates' ); |
|---|
| 118 | } |
|---|
| 119 | $app->load_list_actions( 'template', $param ); |
|---|
| 120 | $app->param( 'filter_key', $filter ); |
|---|
| 121 | |
|---|
| 122 | $obj->compile; |
|---|
| 123 | if ( $obj->{errors} && @{ $obj->{errors} } ) { |
|---|
| 124 | $param->{error} = $app->translate( |
|---|
| 125 | "One or more errors were found in this template."); |
|---|
| 126 | $param->{error} .= "<ul>\n"; |
|---|
| 127 | foreach my $err ( @{ $obj->{errors} } ) { |
|---|
| 128 | $param->{error} .= "<li>" |
|---|
| 129 | . MT::Util::encode_html( $err->{message} ) |
|---|
| 130 | . "</li>\n"; |
|---|
| 131 | } |
|---|
| 132 | $param->{error} .= "</ul>\n"; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | # Populate list of included templates |
|---|
| 136 | if ( my $includes = $obj->getElementsByTagName('Include') ) { |
|---|
| 137 | my @includes; |
|---|
| 138 | my @widgets; |
|---|
| 139 | my %seen; |
|---|
| 140 | foreach my $tag (@$includes) { |
|---|
| 141 | my $include = {}; |
|---|
| 142 | my $mod = $include->{include_module} = $tag->[1]->{module} || $tag->[1]->{widget}; |
|---|
| 143 | next unless $mod; |
|---|
| 144 | my $type = $tag->[1]->{widget} ? 'widget' : 'custom'; |
|---|
| 145 | next if exists $seen{$type}{$mod}; |
|---|
| 146 | $seen{$type}{$mod} = 1; |
|---|
| 147 | my $other = MT::Template->load( |
|---|
| 148 | { |
|---|
| 149 | blog_id => [ $obj->blog_id, 0 ], |
|---|
| 150 | name => $mod, |
|---|
| 151 | type => $type, |
|---|
| 152 | }, { |
|---|
| 153 | sort => 'blog_id', |
|---|
| 154 | direction => 'descend', |
|---|
| 155 | } |
|---|
| 156 | ); |
|---|
| 157 | if ($other) { |
|---|
| 158 | $include->{include_link} = $app->mt_uri( |
|---|
| 159 | mode => 'view', |
|---|
| 160 | args => { |
|---|
| 161 | blog_id => $other->blog_id || 0, |
|---|
| 162 | '_type' => 'template', |
|---|
| 163 | id => $other->id |
|---|
| 164 | } |
|---|
| 165 | ); |
|---|
| 166 | # Try to compile template module if using MTInclude in this template. |
|---|
| 167 | $other->compile; |
|---|
| 168 | if ( $other->{errors} && @{ $other->{errors} } ) { |
|---|
| 169 | $param->{error} = $app->translate( |
|---|
| 170 | "One or more errors were found in included template module (".$other->name.")."); |
|---|
| 171 | $param->{error} .= "<ul>\n"; |
|---|
| 172 | foreach my $err ( @{ $other->{errors} } ) { |
|---|
| 173 | $param->{error} .= "<li>" |
|---|
| 174 | . MT::Util::encode_html( $err->{message} ) |
|---|
| 175 | . "</li>\n"; |
|---|
| 176 | } |
|---|
| 177 | $param->{error} .= "</ul>\n"; |
|---|
| 178 | } |
|---|
| 179 | } |
|---|
| 180 | else { |
|---|
| 181 | $include->{create_link} = $app->mt_uri( |
|---|
| 182 | mode => 'view', |
|---|
| 183 | args => { |
|---|
| 184 | blog_id => $obj->blog_id, |
|---|
| 185 | '_type' => 'template', |
|---|
| 186 | type => $type, |
|---|
| 187 | name => $mod, |
|---|
| 188 | } |
|---|
| 189 | ); |
|---|
| 190 | } |
|---|
| 191 | if ($type eq 'widget') { |
|---|
| 192 | push @widgets, $include; |
|---|
| 193 | } else { |
|---|
| 194 | push @includes, $include; |
|---|
| 195 | } |
|---|
| 196 | } |
|---|
| 197 | $param->{include_loop} = \@includes if @includes; |
|---|
| 198 | $param->{widget_loop} = \@widgets if @widgets; |
|---|
| 199 | } |
|---|
| 200 | my @sets = ( @{ $obj->getElementsByTagName('WidgetSet') || [] }, @{ $obj->getElementsByTagName('WidgetManager') || [] } ); |
|---|
| 201 | if ( @sets ) { |
|---|
| 202 | my @widget_sets; |
|---|
| 203 | my %seen; |
|---|
| 204 | foreach my $set (@sets) { |
|---|
| 205 | my $name = $set->[1]->{name}; |
|---|
| 206 | next unless $name; |
|---|
| 207 | next if $seen{$name}; |
|---|
| 208 | $seen{$name} = 1; |
|---|
| 209 | my $wset = MT::Template->load( |
|---|
| 210 | { |
|---|
| 211 | blog_id => [ $obj->blog_id, 0 ], |
|---|
| 212 | name => $name, |
|---|
| 213 | type => 'widgetset', |
|---|
| 214 | }, { |
|---|
| 215 | sort => 'blog_id', |
|---|
| 216 | direction => 'descend', |
|---|
| 217 | } |
|---|
| 218 | ); |
|---|
| 219 | push @widget_sets, { |
|---|
| 220 | include_link => $app->mt_uri( |
|---|
| 221 | mode => 'edit_widget', |
|---|
| 222 | args => { |
|---|
| 223 | blog_id => $wset->blog_id, |
|---|
| 224 | id => $wset->id, |
|---|
| 225 | }, |
|---|
| 226 | ), |
|---|
| 227 | include_module => $name, |
|---|
| 228 | }; |
|---|
| 229 | } |
|---|
| 230 | $param->{widget_set_loop} = \@widget_sets if @widget_sets; |
|---|
| 231 | } |
|---|
| 232 | $param->{have_includes} = 1 if $param->{widget_set_loop} || $param->{include_loop} || $param->{widget_loop}; |
|---|
| 233 | # Populate archive types for creating new map |
|---|
| 234 | my $obj_type = $obj->type; |
|---|
| 235 | if ( $obj_type eq 'individual' |
|---|
| 236 | || $obj_type eq 'page' |
|---|
| 237 | || $obj_type eq 'author' |
|---|
| 238 | || $obj_type eq 'category' |
|---|
| 239 | || $obj_type eq 'archive' ) |
|---|
| 240 | { |
|---|
| 241 | my @at = $app->publisher->archive_types; |
|---|
| 242 | my @archive_types; |
|---|
| 243 | for my $at (@at) { |
|---|
| 244 | my $archiver = $app->publisher->archiver($at); |
|---|
| 245 | my $archive_label = $archiver->archive_label; |
|---|
| 246 | $archive_label = $at unless $archive_label; |
|---|
| 247 | $archive_label = $archive_label->() |
|---|
| 248 | if ( ref $archive_label ) eq 'CODE'; |
|---|
| 249 | if ( ( $obj_type eq 'archive' ) |
|---|
| 250 | || ( $obj_type eq 'author' ) |
|---|
| 251 | || ( $obj_type eq 'category' ) ) |
|---|
| 252 | { |
|---|
| 253 | |
|---|
| 254 | # only include if it is NOT an entry-based archive type |
|---|
| 255 | next if $archiver->entry_based; |
|---|
| 256 | } |
|---|
| 257 | elsif ( $obj_type eq 'page' ) { |
|---|
| 258 | # only include if it is a entry-based archive type and page |
|---|
| 259 | next unless $archiver->entry_based; |
|---|
| 260 | next if $archiver->entry_class ne 'page'; |
|---|
| 261 | } |
|---|
| 262 | elsif ( $obj_type eq 'individual' ) { |
|---|
| 263 | # only include if it is a entry-based archive type and entry |
|---|
| 264 | next unless $archiver->entry_based; |
|---|
| 265 | next if $archiver->entry_class eq 'page'; |
|---|
| 266 | } |
|---|
| 267 | push @archive_types, |
|---|
| 268 | { |
|---|
| 269 | archive_type_translated => $archive_label, |
|---|
| 270 | archive_type => $at, |
|---|
| 271 | }; |
|---|
| 272 | @archive_types = |
|---|
| 273 | sort { MT::App::CMS::archive_type_sorter( $a, $b ) } @archive_types; |
|---|
| 274 | } |
|---|
| 275 | $param->{archive_types} = \@archive_types; |
|---|
| 276 | |
|---|
| 277 | # Populate template maps for this template |
|---|
| 278 | my $maps = _populate_archive_loop( $app, $blog, $obj ); |
|---|
| 279 | if (@$maps) { |
|---|
| 280 | $param->{object_loop} = $param->{template_map_loop} = $maps |
|---|
| 281 | if @$maps; |
|---|
| 282 | my %archive_types = map { $_->{archive_label} => 1 } @$maps; |
|---|
| 283 | $param->{enabled_archive_types} = join(", ", sort keys %archive_types); |
|---|
| 284 | } |
|---|
| 285 | } |
|---|
| 286 | # publish options |
|---|
| 287 | $param->{build_type} = $obj->build_type; |
|---|
| 288 | $param->{ 'build_type_' . ( $obj->build_type || 0 ) } = 1; |
|---|
| 289 | #my ( $period, $interval ) = _get_schedule( $obj->build_interval ); |
|---|
| 290 | #$param->{ 'schedule_period_' . $period } = 1; |
|---|
| 291 | #$param->{schedule_interval} = $interval; |
|---|
| 292 | $param->{type} = 'custom' if $param->{type} eq 'module'; |
|---|
| 293 | } else { |
|---|
| 294 | my $new_tmpl = $q->param('create_new_template'); |
|---|
| 295 | my $template_type; |
|---|
| 296 | if ($new_tmpl) { |
|---|
| 297 | if ( $new_tmpl =~ m/^blank:(.+)/ ) { |
|---|
| 298 | $template_type = $1; |
|---|
| 299 | $param->{type} = $1; |
|---|
| 300 | } |
|---|
| 301 | elsif ( $new_tmpl =~ m/^default:([^:]+):(.+)/ ) { |
|---|
| 302 | $template_type = $1; |
|---|
| 303 | $template_type = 'custom' if $template_type eq 'module'; |
|---|
| 304 | my $template_id = $2; |
|---|
| 305 | my $set = $blog ? $blog->template_set : undef; |
|---|
| 306 | require MT::DefaultTemplates; |
|---|
| 307 | my $def_tmpl = MT::DefaultTemplates->templates($set) || []; |
|---|
| 308 | my ($tmpl) = |
|---|
| 309 | grep { $_->{identifier} eq $template_id } @$def_tmpl; |
|---|
| 310 | $param->{text} = $app->translate_templatized( $tmpl->{text} ) |
|---|
| 311 | if $tmpl; |
|---|
| 312 | $param->{type} = $template_type; |
|---|
| 313 | } |
|---|
| 314 | } |
|---|
| 315 | else { |
|---|
| 316 | $template_type = $q->param('type'); |
|---|
| 317 | $template_type = 'custom' if 'module' eq $template_type; |
|---|
| 318 | $param->{type} = $template_type; |
|---|
| 319 | } |
|---|
| 320 | return $app->errtrans("Create template requires type") |
|---|
| 321 | unless $template_type; |
|---|
| 322 | $param->{nav_templates} = 1; |
|---|
| 323 | my $tab; |
|---|
| 324 | |
|---|
| 325 | # FIXME: enumeration of types |
|---|
| 326 | if ( $template_type eq 'index' ) { |
|---|
| 327 | $tab = 'index'; |
|---|
| 328 | $param->{template_group_trans} = $app->translate('index'); |
|---|
| 329 | } |
|---|
| 330 | elsif ($template_type eq 'archive' |
|---|
| 331 | || $template_type eq 'individual' |
|---|
| 332 | || $template_type eq 'category' |
|---|
| 333 | || $template_type eq 'page' ) |
|---|
| 334 | { |
|---|
| 335 | $tab = 'archive'; |
|---|
| 336 | $param->{template_group_trans} = $app->translate('archive'); |
|---|
| 337 | $param->{type_archive} = 1; |
|---|
| 338 | my @types = ( |
|---|
| 339 | { |
|---|
| 340 | key => 'archive', |
|---|
| 341 | label => $app->translate('Archive') |
|---|
| 342 | }, |
|---|
| 343 | { |
|---|
| 344 | key => 'individual', |
|---|
| 345 | label => $app->translate('Entry or Page') |
|---|
| 346 | }, |
|---|
| 347 | ); |
|---|
| 348 | $param->{new_archive_types} = \@types; |
|---|
| 349 | } |
|---|
| 350 | elsif ( $template_type eq 'custom' ) { |
|---|
| 351 | $tab = 'module'; |
|---|
| 352 | $param->{template_group_trans} = $app->translate('module'); |
|---|
| 353 | } |
|---|
| 354 | elsif ( $template_type eq 'widget' ) { |
|---|
| 355 | $tab = 'widget'; |
|---|
| 356 | $param->{template_group_trans} = $app->translate('widget'); |
|---|
| 357 | } |
|---|
| 358 | else { |
|---|
| 359 | $tab = 'system'; |
|---|
| 360 | $param->{template_group_trans} = $app->translate('system'); |
|---|
| 361 | } |
|---|
| 362 | $param->{template_group} = $tab; |
|---|
| 363 | $app->translate($tab); |
|---|
| 364 | $app->add_breadcrumb( $app->translate('New Template') ); |
|---|
| 365 | |
|---|
| 366 | # FIXME: enumeration of types |
|---|
| 367 | $param->{has_name} = $template_type eq 'index' |
|---|
| 368 | || $template_type eq 'custom' |
|---|
| 369 | || $template_type eq 'widget' |
|---|
| 370 | || $template_type eq 'archive' |
|---|
| 371 | || $template_type eq 'category' |
|---|
| 372 | || $template_type eq 'page' |
|---|
| 373 | || $template_type eq 'individual'; |
|---|
| 374 | $param->{has_outfile} = $template_type eq 'index'; |
|---|
| 375 | $param->{has_rebuild} = |
|---|
| 376 | ( ( $template_type eq 'index' ) |
|---|
| 377 | && ( ( $blog->custom_dynamic_templates || "" ) ne 'all' ) ); |
|---|
| 378 | $param->{custom_dynamic} = |
|---|
| 379 | $blog && $blog->custom_dynamic_templates eq 'custom'; |
|---|
| 380 | $param->{has_build_options} = |
|---|
| 381 | $blog && ($blog->custom_dynamic_templates eq 'custom' |
|---|
| 382 | || $param->{has_rebuild}); |
|---|
| 383 | |
|---|
| 384 | # FIXME: enumeration of types |
|---|
| 385 | $param->{is_special} = $param->{type} ne 'index' |
|---|
| 386 | && $param->{type} ne 'archive' |
|---|
| 387 | && $param->{type} ne 'category' |
|---|
| 388 | && $param->{type} ne 'page' |
|---|
| 389 | && $param->{type} ne 'individual'; |
|---|
| 390 | $param->{has_build_options} = $param->{has_build_options} |
|---|
| 391 | && $param->{type} ne 'custom' |
|---|
| 392 | && $param->{type} ne 'widget' |
|---|
| 393 | && !$param->{is_special}; |
|---|
| 394 | |
|---|
| 395 | $param->{name} = MT::Util::decode_url( $app->param('name') ) |
|---|
| 396 | if $app->param('name'); |
|---|
| 397 | } |
|---|
| 398 | $param->{publish_queue_available} = eval 'require List::Util; require Scalar::Util; 1;'; |
|---|
| 399 | |
|---|
| 400 | my $set = $blog ? $blog->template_set : undef; |
|---|
| 401 | require MT::DefaultTemplates; |
|---|
| 402 | my $tmpls = MT::DefaultTemplates->templates($set); |
|---|
| 403 | my @tmpl_ids; |
|---|
| 404 | foreach my $dtmpl (@$tmpls) { |
|---|
| 405 | if ( !$param->{has_name} ) { |
|---|
| 406 | if ($obj->type eq 'email') { |
|---|
| 407 | if ($dtmpl->{identifier} eq $obj->identifier) { |
|---|
| 408 | $param->{template_name_label} = $dtmpl->{label}; |
|---|
| 409 | $param->{template_name} = $dtmpl->{name}; |
|---|
| 410 | } |
|---|
| 411 | } |
|---|
| 412 | else { |
|---|
| 413 | if ( $dtmpl->{type} eq $obj->type ) { |
|---|
| 414 | $param->{template_name_label} = $dtmpl->{label}; |
|---|
| 415 | $param->{template_name} = $dtmpl->{name}; |
|---|
| 416 | } |
|---|
| 417 | } |
|---|
| 418 | } |
|---|
| 419 | if ( $dtmpl->{type} eq 'index' ) { |
|---|
| 420 | push @tmpl_ids, |
|---|
| 421 | { |
|---|
| 422 | label => $dtmpl->{label}, |
|---|
| 423 | key => $dtmpl->{key}, |
|---|
| 424 | selected => $dtmpl->{key} eq |
|---|
| 425 | ( ( $obj ? $obj->identifier : undef ) || '' ), |
|---|
| 426 | }; |
|---|
| 427 | } |
|---|
| 428 | } |
|---|
| 429 | $param->{index_identifiers} = \@tmpl_ids; |
|---|
| 430 | |
|---|
| 431 | $param->{"type_$param->{type}"} = 1; |
|---|
| 432 | if ($perms) { |
|---|
| 433 | my $pref_param = |
|---|
| 434 | $app->load_template_prefs( $perms->template_prefs ); |
|---|
| 435 | %$param = ( %$param, %$pref_param ); |
|---|
| 436 | } |
|---|
| 437 | |
|---|
| 438 | # Populate structure for template snippets |
|---|
| 439 | if ( my $snippets = $app->registry('template_snippets') || {} ) { |
|---|
| 440 | my @snippets; |
|---|
| 441 | for my $snip_id ( keys %$snippets ) { |
|---|
| 442 | my $label = $snippets->{$snip_id}{label}; |
|---|
| 443 | $label = $label->() if ref($label) eq 'CODE'; |
|---|
| 444 | push @snippets, |
|---|
| 445 | { |
|---|
| 446 | id => $snip_id, |
|---|
| 447 | trigger => $snippets->{$snip_id}{trigger}, |
|---|
| 448 | label => $label, |
|---|
| 449 | content => $snippets->{$snip_id}{content}, |
|---|
| 450 | }; |
|---|
| 451 | } |
|---|
| 452 | @snippets = sort { $a->{label} cmp $b->{label} } @snippets; |
|---|
| 453 | $param->{template_snippets} = \@snippets; |
|---|
| 454 | } |
|---|
| 455 | |
|---|
| 456 | # Populate structure for tag documentation |
|---|
| 457 | my $all_tags = MT::Component->registry("tags"); |
|---|
| 458 | my $tag_docs = {}; |
|---|
| 459 | foreach my $tag_set (@$all_tags) { |
|---|
| 460 | my $url = $tag_set->{help_url}; |
|---|
| 461 | $url = $url->() if ref($url) eq 'CODE'; |
|---|
| 462 | # hey, at least give them a google search |
|---|
| 463 | $url ||= 'http://www.google.com/search?q=mt%t'; |
|---|
| 464 | my $tag_list = ''; |
|---|
| 465 | foreach my $type (qw( block function )) { |
|---|
| 466 | my $tags = $tag_set->{$type} or next; |
|---|
| 467 | $tag_list .= ($tag_list eq '' ? '' : ',') . join(",", keys(%$tags)); |
|---|
| 468 | } |
|---|
| 469 | $tag_list =~ s/(^|,)plugin(,|$)/,/; |
|---|
| 470 | if (exists $tag_docs->{$url}) { |
|---|
| 471 | $tag_docs->{$url} .= ',' . $tag_list; |
|---|
| 472 | } |
|---|
| 473 | else { |
|---|
| 474 | $tag_docs->{$url} = $tag_list; |
|---|
| 475 | } |
|---|
| 476 | } |
|---|
| 477 | $param->{tag_docs} = $tag_docs; |
|---|
| 478 | $param->{link_doc} = $app->help_url('appendices/tags/'); |
|---|
| 479 | |
|---|
| 480 | $param->{screen_id} = "edit-template-" . $param->{type}; |
|---|
| 481 | |
|---|
| 482 | # template language |
|---|
| 483 | $param->{template_lang} = 'html'; |
|---|
| 484 | if ( $obj && $obj->outfile ) { |
|---|
| 485 | if ( $obj->outfile =~ m/\.(css|js|html|php|pl|asp)$/ ) { |
|---|
| 486 | $param->{template_lang} = { |
|---|
| 487 | css => 'css', |
|---|
| 488 | js => 'javascript', |
|---|
| 489 | html => 'html', |
|---|
| 490 | php => 'php', |
|---|
| 491 | pl => 'perl', |
|---|
| 492 | asp => 'asp', |
|---|
| 493 | }->{$1}; |
|---|
| 494 | } |
|---|
| 495 | } |
|---|
| 496 | |
|---|
| 497 | if (($param->{type} eq 'custom') || ($param->{type} eq 'widget')) { |
|---|
| 498 | if ($blog) { |
|---|
| 499 | $param->{include_with_ssi} = 0; |
|---|
| 500 | $param->{cache_path} = ''; |
|---|
| 501 | $param->{cache_expire_type} = 0; |
|---|
| 502 | $param->{cache_expire_period} = ''; |
|---|
| 503 | $param->{cache_expire_interval} = 0; |
|---|
| 504 | $param->{ssi_type} = uc $blog->include_system; |
|---|
| 505 | } |
|---|
| 506 | if ($obj) { |
|---|
| 507 | $param->{include_with_ssi} = $obj->include_with_ssi |
|---|
| 508 | if defined $obj->include_with_ssi; |
|---|
| 509 | $param->{cache_path} = $obj->cache_path |
|---|
| 510 | if defined $obj->cache_path; |
|---|
| 511 | $param->{cache_expire_type} = $obj->cache_expire_type |
|---|
| 512 | if defined $obj->cache_expire_type; |
|---|
| 513 | my ( $period, $interval ) = |
|---|
| 514 | _get_schedule( $obj->cache_expire_interval ); |
|---|
| 515 | $param->{cache_expire_period} = $period if defined $period; |
|---|
| 516 | $param->{cache_expire_interval} = $interval if defined $interval; |
|---|
| 517 | my @events = split ',', ($obj->cache_expire_event || ''); |
|---|
| 518 | foreach my $name (@events) { |
|---|
| 519 | $param->{ 'cache_expire_event_' . $name } = 1; |
|---|
| 520 | } |
|---|
| 521 | } |
|---|
| 522 | } |
|---|
| 523 | |
|---|
| 524 | # if unset, default to 30 so if they choose to enable caching, |
|---|
| 525 | # it will be preset to something sane. |
|---|
| 526 | $param->{cache_expire_interval} ||= 30; |
|---|
| 527 | |
|---|
| 528 | $param->{dirty} = 1 |
|---|
| 529 | if $app->param('dirty'); |
|---|
| 530 | |
|---|
| 531 | $param->{can_preview} = 1 |
|---|
| 532 | if (!$param->{is_special}) && (!$obj || ($obj && ($obj->outfile || '') !~ m/\.(css|xml|rss|js)$/)); |
|---|
| 533 | |
|---|
| 534 | 1; |
|---|
| 535 | } |
|---|
| 536 | |
|---|
| 537 | sub list { |
|---|
| 538 | my $app = shift; |
|---|
| 539 | |
|---|
| 540 | my $perms = $app->blog ? $app->permissions : $app->user->permissions; |
|---|
| 541 | return $app->return_to_dashboard( redirect => 1 ) |
|---|
| 542 | unless $perms || $app->user->is_superuser; |
|---|
| 543 | if ( $perms && !$perms->can_edit_templates ) { |
|---|
| 544 | return $app->return_to_dashboard( permission => 1 ); |
|---|
| 545 | } |
|---|
| 546 | my $blog = $app->blog; |
|---|
| 547 | |
|---|
| 548 | require MT::Template; |
|---|
| 549 | my $blog_id = $app->param('blog_id') || 0; |
|---|
| 550 | my $terms = { blog_id => $blog_id }; |
|---|
| 551 | my $args = { sort => 'name' }; |
|---|
| 552 | |
|---|
| 553 | my $hasher = sub { |
|---|
| 554 | my ( $obj, $row ) = @_; |
|---|
| 555 | my $template_type; |
|---|
| 556 | my $type = $row->{type} || ''; |
|---|
| 557 | if ( $type =~ m/^(individual|page|category|archive)$/ ) { |
|---|
| 558 | $template_type = 'archive'; |
|---|
| 559 | # populate context with templatemap loop |
|---|
| 560 | my $tblog = $obj->blog_id == $blog->id ? $blog : MT::Blog->load( $obj->blog_id ); |
|---|
| 561 | if ($tblog) { |
|---|
| 562 | $row->{archive_types} = _populate_archive_loop( $app, $tblog, $obj ); |
|---|
| 563 | } |
|---|
| 564 | } |
|---|
| 565 | elsif ( $type eq 'widget' ) { |
|---|
| 566 | $template_type = 'widget'; |
|---|
| 567 | } |
|---|
| 568 | elsif ( $type eq 'index' ) { |
|---|
| 569 | $template_type = 'index'; |
|---|
| 570 | } |
|---|
| 571 | elsif ( $type eq 'custom' ) { |
|---|
| 572 | $template_type = 'module'; |
|---|
| 573 | } |
|---|
| 574 | elsif ( $type eq 'email' ) { |
|---|
| 575 | $template_type = 'email'; |
|---|
| 576 | } |
|---|
| 577 | elsif ( $type eq 'backup' ) { |
|---|
| 578 | $template_type = 'backup'; |
|---|
| 579 | } |
|---|
| 580 | else { |
|---|
| 581 | $template_type = 'system'; |
|---|
| 582 | } |
|---|
| 583 | $row->{use_cache} = ( ($obj->cache_expire_type || 0) != 0 ) ? 1 : 0; |
|---|
| 584 | $row->{template_type} = $template_type; |
|---|
| 585 | $row->{type} = 'entry' if $type eq 'individual'; |
|---|
| 586 | my $published_url = $obj->published_url; |
|---|
| 587 | $row->{published_url} = $published_url if $published_url; |
|---|
| 588 | }; |
|---|
| 589 | |
|---|
| 590 | my $params = {}; |
|---|
| 591 | my $filter = $app->param('filter_key'); |
|---|
| 592 | my $template_type = $filter || ''; |
|---|
| 593 | $template_type =~ s/_templates//; |
|---|
| 594 | |
|---|
| 595 | $params->{screen_class} = "list-template"; |
|---|
| 596 | $params->{listing_screen} = 1; |
|---|
| 597 | |
|---|
| 598 | $app->load_list_actions( 'template', $params ); |
|---|
| 599 | $params->{page_actions} = $app->page_actions('list_templates'); |
|---|
| 600 | $params->{search_label} = $app->translate("Templates"); |
|---|
| 601 | $params->{object_type} = 'template'; |
|---|
| 602 | $params->{blog_view} = 1; |
|---|
| 603 | $params->{refreshed} = $app->param('refreshed'); |
|---|
| 604 | $params->{published} = $app->param('published'); |
|---|
| 605 | $params->{saved_copied} = $app->param('saved_copied'); |
|---|
| 606 | $params->{saved_deleted} = $app->param('saved_deleted'); |
|---|
| 607 | $params->{saved} = $app->param('saved'); |
|---|
| 608 | |
|---|
| 609 | # determine list of system template types: |
|---|
| 610 | my $scope; |
|---|
| 611 | my $set; |
|---|
| 612 | if ( $blog ) { |
|---|
| 613 | $set = $blog->template_set; |
|---|
| 614 | $scope = 'system'; |
|---|
| 615 | } |
|---|
| 616 | else { |
|---|
| 617 | $scope = 'global:system'; |
|---|
| 618 | } |
|---|
| 619 | my @tmpl_path = ( $set && ($set ne 'mt_blog')) ? ("template_sets", $set, 'templates', $scope) : ("default_templates", $scope); |
|---|
| 620 | my $sys_tmpl = MT->registry(@tmpl_path) || {}; |
|---|
| 621 | |
|---|
| 622 | my @tmpl_loop; |
|---|
| 623 | my %types; |
|---|
| 624 | if ($template_type ne 'backup') { |
|---|
| 625 | if ($blog) { |
|---|
| 626 | # blog template listings |
|---|
| 627 | %types = ( |
|---|
| 628 | 'index' => { |
|---|
| 629 | label => $app->translate("Index Templates"), |
|---|
| 630 | type => 'index', |
|---|
| 631 | order => 100, |
|---|
| 632 | }, |
|---|
| 633 | 'archive' => { |
|---|
| 634 | label => $app->translate("Archive Templates"), |
|---|
| 635 | type => ['archive', 'individual', 'page', 'category'], |
|---|
| 636 | order => 200, |
|---|
| 637 | }, |
|---|
| 638 | 'module' => { |
|---|
| 639 | label => $app->translate("Template Modules"), |
|---|
| 640 | type => 'custom', |
|---|
| 641 | order => 300, |
|---|
| 642 | }, |
|---|
| 643 | 'system' => { |
|---|
| 644 | label => $app->translate("System Templates"), |
|---|
| 645 | type => [ keys %$sys_tmpl ], |
|---|
| 646 | order => 400, |
|---|
| 647 | }, |
|---|
| 648 | ); |
|---|
| 649 | } else { |
|---|
| 650 | # global template listings |
|---|
| 651 | %types = ( |
|---|
| 652 | 'module' => { |
|---|
| 653 | label => $app->translate("Template Modules"), |
|---|
| 654 | type => 'custom', |
|---|
| 655 | order => 100, |
|---|
| 656 | }, |
|---|
| 657 | 'email' => { |
|---|
| 658 | label => $app->translate("Email Templates"), |
|---|
| 659 | type => 'email', |
|---|
| 660 | order => 200, |
|---|
| 661 | }, |
|---|
| 662 | 'system' => { |
|---|
| 663 | label => $app->translate("System Templates"), |
|---|
| 664 | type => [ keys %$sys_tmpl ], |
|---|
| 665 | order => 300, |
|---|
| 666 | }, |
|---|
| 667 | ); |
|---|
| 668 | } |
|---|
| 669 | } else { |
|---|
| 670 | # global template listings |
|---|
| 671 | %types = ( |
|---|
| 672 | 'backup' => { |
|---|
| 673 | label => $app->translate("Template Backups"), |
|---|
| 674 | type => 'backup', |
|---|
| 675 | order => 100, |
|---|
| 676 | }, |
|---|
| 677 | ); |
|---|
| 678 | } |
|---|
| 679 | my @types = sort { $types{$a}->{order} <=> $types{$b}->{order} } keys %types; |
|---|
| 680 | if ($template_type) { |
|---|
| 681 | @types = ( $template_type ); |
|---|
| 682 | } |
|---|
| 683 | $app->delete_param('filter_key') if $filter; |
|---|
| 684 | foreach my $tmpl_type (@types) { |
|---|
| 685 | if ( $tmpl_type eq 'index' ) { |
|---|
| 686 | $app->param( 'filter_key', 'index_templates' ); |
|---|
| 687 | } |
|---|
| 688 | elsif ( $tmpl_type eq 'archive' ) { |
|---|
| 689 | $app->param( 'filter_key', 'archive_templates' ); |
|---|
| 690 | } |
|---|
| 691 | elsif ( $tmpl_type eq 'system' ) { |
|---|
| 692 | $app->param( 'filter_key', 'system_templates' ); |
|---|
| 693 | } |
|---|
| 694 | elsif ( $tmpl_type eq 'email' ) { |
|---|
| 695 | $app->param( 'filter_key', 'email_templates' ); |
|---|
| 696 | } |
|---|
| 697 | elsif ( $tmpl_type eq 'module' ) { |
|---|
| 698 | $app->param( 'filter_key', 'module_templates' ); |
|---|
| 699 | } |
|---|
| 700 | $terms->{type} = $types{$tmpl_type}->{type}; |
|---|
| 701 | my $tmpl_param = $app->listing( |
|---|
| 702 | { |
|---|
| 703 | type => 'template', |
|---|
| 704 | terms => $terms, |
|---|
| 705 | args => $args, |
|---|
| 706 | no_limit => 1, |
|---|
| 707 | no_html => 1, |
|---|
| 708 | code => $hasher, |
|---|
| 709 | } |
|---|
| 710 | ); |
|---|
| 711 | |
|---|
| 712 | my $template_type_label = $types{$tmpl_type}->{label}; |
|---|
| 713 | $tmpl_param->{template_type} = $tmpl_type; |
|---|
| 714 | $tmpl_param->{template_type_label} = $template_type_label; |
|---|
| 715 | push @tmpl_loop, $tmpl_param; |
|---|
| 716 | } |
|---|
| 717 | if ($filter) { |
|---|
| 718 | $params->{filter_key} = $filter; |
|---|
| 719 | $params->{filter_label} = $types{$template_type}{label} |
|---|
| 720 | if exists $types{$template_type}; |
|---|
| 721 | $app->param('filter_key', $filter); |
|---|
| 722 | } else { |
|---|
| 723 | # restore filter_key param (we modified it for the |
|---|
| 724 | # sake of the individual table listings) |
|---|
| 725 | $app->delete_param('filter_key'); |
|---|
| 726 | } |
|---|
| 727 | |
|---|
| 728 | $params->{template_type_loop} = \@tmpl_loop; |
|---|
| 729 | $params->{screen_id} = "list-template"; |
|---|
| 730 | |
|---|
| 731 | return $app->load_tmpl('list_template.tmpl', $params); |
|---|
| 732 | } |
|---|
| 733 | |
|---|
| 734 | sub preview { |
|---|
| 735 | my $app = shift; |
|---|
| 736 | my $q = $app->param; |
|---|
| 737 | my $blog_id = $q->param('blog_id'); |
|---|
| 738 | my $blog = $app->blog; |
|---|
| 739 | my $id = $q->param('id'); |
|---|
| 740 | my $tmpl; |
|---|
| 741 | my $user_id = $app->user->id; |
|---|
| 742 | |
|---|
| 743 | # We can only do previews on blog templates. Have to publish |
|---|
| 744 | # the preview file somewhere! |
|---|
| 745 | return $app->errtrans("Invalid request.") unless $blog; |
|---|
| 746 | |
|---|
| 747 | require MT::Template; |
|---|
| 748 | if ($id) { |
|---|
| 749 | $tmpl = MT::Template->load( { id => $id, blog_id => $blog_id } ) |
|---|
| 750 | or return $app->errtrans( "Invalid request." ); |
|---|
| 751 | } |
|---|
| 752 | else { |
|---|
| 753 | $tmpl = MT::Template->new; |
|---|
| 754 | $tmpl->id(-1); |
|---|
| 755 | $tmpl->blog_id($blog_id); |
|---|
| 756 | } |
|---|
| 757 | |
|---|
| 758 | my $names = $tmpl->column_names; |
|---|
| 759 | my %values = map { $_ => scalar $app->param($_) } @$names; |
|---|
| 760 | delete $values{'id'} unless $q->param('id'); |
|---|
| 761 | |
|---|
| 762 | ## Strip linefeed characters. |
|---|
| 763 | for my $col (qw( text )) { |
|---|
| 764 | $values{$col} =~ tr/\r//d if $values{$col}; |
|---|
| 765 | } |
|---|
| 766 | $tmpl->set_values( \%values ); |
|---|
| 767 | |
|---|
| 768 | my $preview_basename = $app->preview_object_basename; |
|---|
| 769 | |
|---|
| 770 | my $type = $tmpl->type; |
|---|
| 771 | my $preview_tmpl = $tmpl; |
|---|
| 772 | my $archive_file; |
|---|
| 773 | my $archive_url; |
|---|
| 774 | my %param; |
|---|
| 775 | my $blog_path = $blog->site_path; |
|---|
| 776 | my $blog_url = $blog->site_url; |
|---|
| 777 | |
|---|
| 778 | if (($type eq 'custom') || ($type eq 'widget')) { |
|---|
| 779 | # determine 'host' template |
|---|
| 780 | $preview_tmpl = MT::Template->load({ blog_id => $blog_id, identifier => 'main_index' }); |
|---|
| 781 | if (!$preview_tmpl) { |
|---|
| 782 | return $app->errtrans("Can't locate host template to preview module/widget."); |
|---|
| 783 | } |
|---|
| 784 | my $req = $app->request; |
|---|
| 785 | # stash this module so that it is selected through a |
|---|
| 786 | # MTInclude tag instead of the one in the database: |
|---|
| 787 | my $tmpl_name = $tmpl->name; |
|---|
| 788 | $tmpl_name =~ s/^Widget: // if $type eq 'widget'; |
|---|
| 789 | my $stash_id = 'template_' . $type . '::' . $blog_id . '::' . $tmpl_name; |
|---|
| 790 | $req->stash($stash_id, [ $tmpl, $tmpl->tokens ]); |
|---|
| 791 | } elsif (($type eq 'individual') || ($type eq 'page')) { |
|---|
| 792 | my $ctx = $preview_tmpl->context; |
|---|
| 793 | my $entry_type = $type eq 'individual' ? 'entry' : 'page'; |
|---|
| 794 | my ($obj) = create_preview_content($app, $blog, $entry_type, 1); |
|---|
| 795 | $obj->basename( $preview_basename ); |
|---|
| 796 | $ctx->stash('entry', $obj); |
|---|
| 797 | $ctx->{current_archive_type} = $type eq 'individual' ? 'Individual' : 'Page'; |
|---|
| 798 | if (($type eq 'individual') && $blog->archive_path) { |
|---|
| 799 | $blog_path = $blog->archive_path; |
|---|
| 800 | $blog_url = $blog->archive_url; |
|---|
| 801 | } |
|---|
| 802 | $archive_file = File::Spec->catfile( $blog_path, $obj->archive_file ); |
|---|
| 803 | $archive_url = $obj->archive_url; |
|---|
| 804 | } elsif ($type eq 'archive') { |
|---|
| 805 | # some variety of archive template |
|---|
| 806 | my $ctx = $preview_tmpl->context; |
|---|
| 807 | require MT::TemplateMap; |
|---|
| 808 | my $map = MT::TemplateMap->load( { template_id => $id, is_preferred => 1 }); |
|---|
| 809 | if (! $map) { |
|---|
| 810 | return $app->error("Cannot preview without a template map!"); |
|---|
| 811 | } |
|---|
| 812 | $ctx->{current_archive_type} = $map->archive_type; |
|---|
| 813 | my $archiver = MT->publisher->archiver( $map->archive_type ); |
|---|
| 814 | my @entries = create_preview_content($app, $blog, $archiver->entry_class, 10); |
|---|
| 815 | if ($archiver->date_based) { |
|---|
| 816 | $ctx->{current_timestamp} = $entries[0]->authored_on; |
|---|
| 817 | $ctx->{current_timestamp_end} = $entries[$#entries]->authored_on; |
|---|
| 818 | } |
|---|
| 819 | if ($archiver->author_based) { |
|---|
| 820 | $ctx->stash('author', $app->user); |
|---|
| 821 | } |
|---|
| 822 | my $cat; |
|---|
| 823 | if ($archiver->category_based) { |
|---|
| 824 | $cat = new MT::Category; |
|---|
| 825 | $cat->label($app->translate("Preview")); |
|---|
| 826 | $cat->basename("preview"); |
|---|
| 827 | $cat->parent(0); |
|---|
| 828 | $ctx->stash('archive_category', $cat); |
|---|
| 829 | } |
|---|
| 830 | $ctx->stash('entries', \@entries); |
|---|
| 831 | |
|---|
| 832 | my $file = MT->publisher->archive_file_for( $entries[0], $blog, $map->archive_type, $cat, $map, $ctx->{current_timestamp}, $app->user); |
|---|
| 833 | $archive_file = File::Spec->catfile( $blog_path, $file ); |
|---|
| 834 | $archive_url = MT::Util::caturl( $blog_url, $file ); |
|---|
| 835 | } elsif ($type eq 'index') { |
|---|
| 836 | } else { |
|---|
| 837 | # for now, only index templates can be previewed |
|---|
| 838 | return $app->errtrans("Invalid request."); |
|---|
| 839 | } |
|---|
| 840 | |
|---|
| 841 | my $orig_file; |
|---|
| 842 | my $path; |
|---|
| 843 | |
|---|
| 844 | # Default case; works for index templates (other template types should |
|---|
| 845 | # have defined $archive_file by now). |
|---|
| 846 | $archive_file = File::Spec->catfile( $blog_path, $preview_tmpl->outfile ) |
|---|
| 847 | unless defined $archive_file; |
|---|
| 848 | |
|---|
| 849 | ( $orig_file, $path ) = File::Basename::fileparse( $archive_file ); |
|---|
| 850 | |
|---|
| 851 | $archive_url = MT::Util::caturl( $blog_url, $orig_file ) |
|---|
| 852 | unless defined $archive_url; |
|---|
| 853 | |
|---|
| 854 | my $file_ext; |
|---|
| 855 | require File::Basename; |
|---|
| 856 | $file_ext = $archive_file; |
|---|
| 857 | if ($file_ext =~ m/\.[a-z]+$/) { |
|---|
| 858 | $file_ext =~ s!.+\.!.!; |
|---|
| 859 | } else { |
|---|
| 860 | $file_ext = ''; |
|---|
| 861 | } |
|---|
| 862 | $archive_file = File::Spec->catfile( $path, $preview_basename . $file_ext ); |
|---|
| 863 | |
|---|
| 864 | my @data; |
|---|
| 865 | $app->run_callbacks( 'cms_pre_preview.template', $app, $preview_tmpl, \@data ); |
|---|
| 866 | |
|---|
| 867 | my $has_hires = eval 'require Time::HiRes; 1' ? 1 : 0; |
|---|
| 868 | my $start_time = $has_hires ? Time::HiRes::time() : time; |
|---|
| 869 | |
|---|
| 870 | my $ctx = $preview_tmpl->context; |
|---|
| 871 | $preview_tmpl->var('preview_template', 1); |
|---|
| 872 | my $html = $preview_tmpl->output; |
|---|
| 873 | |
|---|
| 874 | $param{build_time} = $has_hires ? sprintf("%.3f", Time::HiRes::time() - $start_time ) : "~" . ( time - $start_time ); |
|---|
| 875 | |
|---|
| 876 | unless ( defined($html) ) { |
|---|
| 877 | return $app->error( $app->translate( "Publish error: [_1]", |
|---|
| 878 | MT::Util::encode_html( $preview_tmpl->errstr ) ) ); |
|---|
| 879 | } |
|---|
| 880 | |
|---|
| 881 | # If MT is configured to do 'local' previews, convert all |
|---|
| 882 | # the normal blog URLs into the domain used by MT itself (ie, |
|---|
| 883 | # blog is published to www.example.com, which is a different |
|---|
| 884 | # server from where MT runs, mt.example.com; previews therefore |
|---|
| 885 | # should occur locally, so replace all http://www.example.com/ |
|---|
| 886 | # with http://mt.example.com/). |
|---|
| 887 | my ($old_url, $new_url); |
|---|
| 888 | if ($app->config('LocalPreviews')) { |
|---|
| 889 | $old_url = $blog_url; |
|---|
| 890 | $old_url =~ s!^(https?://[^/]+?/)(.*)?!$1!; |
|---|
| 891 | $new_url = $app->base . '/'; |
|---|
| 892 | $html =~ s!\Q$old_url\E!$new_url!g; |
|---|
| 893 | } |
|---|
| 894 | |
|---|
| 895 | my $fmgr = $blog->file_mgr; |
|---|
| 896 | |
|---|
| 897 | ## Determine if we need to build directory structure, |
|---|
| 898 | ## and build it if we do. DirUmask determines |
|---|
| 899 | ## directory permissions. |
|---|
| 900 | require File::Basename; |
|---|
| 901 | $path =~ s!/$!! |
|---|
| 902 | unless $path eq '/'; ## OS X doesn't like / at the end in mkdir(). |
|---|
| 903 | unless ( $fmgr->exists($path) ) { |
|---|
| 904 | $fmgr->mkpath($path); |
|---|
| 905 | } |
|---|
| 906 | |
|---|
| 907 | if ( $fmgr->exists($path) && $fmgr->can_write($path) ) { |
|---|
| 908 | $param{preview_file} = $preview_basename; |
|---|
| 909 | my $preview_url = $archive_url; |
|---|
| 910 | $preview_url =~ s! / \Q$orig_file\E ( /? ) $!/$preview_basename$file_ext$1!x; |
|---|
| 911 | |
|---|
| 912 | # We also have to translate the URL used for the |
|---|
| 913 | # published file to be on the MT app domain. |
|---|
| 914 | if (defined $new_url) { |
|---|
| 915 | $preview_url =~ s!^\Q$old_url\E!$new_url!; |
|---|
| 916 | } |
|---|
| 917 | |
|---|
| 918 | $param{preview_url} = $preview_url; |
|---|
| 919 | |
|---|
| 920 | $fmgr->put_data( $html, $archive_file ); |
|---|
| 921 | |
|---|
| 922 | # we have to make a record of this preview just in case it |
|---|
| 923 | # isn't cleaned up by re-editing, saving or cancelling on |
|---|
| 924 | # by the user. |
|---|
| 925 | require MT::Session; |
|---|
| 926 | my $sess_obj = MT::Session->get_by_key( |
|---|
| 927 | { |
|---|
| 928 | id => $preview_basename, |
|---|
| 929 | kind => 'TF', # TF = Temporary File |
|---|
| 930 | name => $archive_file, |
|---|
| 931 | } |
|---|
| 932 | ); |
|---|
| 933 | $sess_obj->start(time); |
|---|
| 934 | $sess_obj->save; |
|---|
| 935 | } |
|---|
| 936 | else { |
|---|
| 937 | return $app->error( $app->translate( |
|---|
| 938 | "Unable to create preview file in this location: [_1]", $path ) ); |
|---|
| 939 | } |
|---|
| 940 | |
|---|
| 941 | $param{id} = $id if $id; |
|---|
| 942 | $param{new_object} = $param{id} ? 0 : 1; |
|---|
| 943 | $param{name} = $tmpl->name; |
|---|
| 944 | my $cols = $tmpl->column_names; |
|---|
| 945 | for my $col (@$cols) { |
|---|
| 946 | push @data, |
|---|
| 947 | { |
|---|
| 948 | data_name => $col, |
|---|
| 949 | data_value => scalar $q->param($col) |
|---|
| 950 | }; |
|---|
| 951 | } |
|---|
| 952 | $param{template_loop} = \@data; |
|---|
| 953 | $param{object_type} = $type; |
|---|
| 954 | return $app->load_tmpl( 'preview_template_strip.tmpl', \%param ); |
|---|
| 955 | } |
|---|
| 956 | |
|---|
| 957 | sub create_preview_content { |
|---|
| 958 | my ($app, $blog, $type, $number) = @_; |
|---|
| 959 | |
|---|
| 960 | my $blog_id = $blog->id; |
|---|
| 961 | my $entry_class = $app->model($type); |
|---|
| 962 | my @obj = $entry_class->load({ |
|---|
| 963 | blog_id => $blog_id, |
|---|
| 964 | status => MT::Entry::RELEASE() |
|---|
| 965 | }, { |
|---|
| 966 | limit => $number || 1, |
|---|
| 967 | direction => 'descend', |
|---|
| 968 | 'sort' => 'authored_on' |
|---|
| 969 | }); |
|---|
| 970 | unless ( @obj ) { |
|---|
| 971 | # create a dummy object |
|---|
| 972 | my $obj = $entry_class->new; |
|---|
| 973 | $obj->blog_id($blog_id); |
|---|
| 974 | $obj->id(-1); |
|---|
| 975 | $obj->author_id( $app->user->id ); |
|---|
| 976 | $obj->authored_on( $blog->current_timestamp ); |
|---|
| 977 | $obj->status( MT::Entry::RELEASE() ); |
|---|
| 978 | $obj->title($app->translate("Lorem ipsum")); |
|---|
| 979 | my $preview_text = $app->translate('LOREM_IPSUM_TEXT'); |
|---|
| 980 | if ($preview_text eq 'LOREM_IPSUM_TEXT') { |
|---|
| 981 | $preview_text = q{Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut diam quam, accumsan eu, aliquam vel, ultrices a, augue. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce hendrerit, lacus eget bibendum sollicitudin, mi tellus interdum neque, sit amet pretium tortor tellus id erat. Duis placerat justo ac erat. Duis posuere, risus eu elementum viverra, nisl lacus sagittis lorem, ac fermentum neque pede vitae arcu. Phasellus arcu elit, placerat eu, luctus posuere, tristique non, augue. In hac habitasse platea dictumst. Nunc non dolor et ipsum mattis malesuada. Praesent porta orci eu ligula. Ut dui augue, dapibus vitae, sodales in, lobortis non, felis. Aliquam feugiat mollis ipsum.}; |
|---|
| 982 | } |
|---|
| 983 | my $preview_more = $app->translate('LORE_IPSUM_TEXT_MORE'); |
|---|
| 984 | if ($preview_text eq 'LOREM_IPSUM_TEXT_MORE') { |
|---|
| 985 | $preview_more = q{Integer nunc nulla, vulputate sit amet, varius ac, faucibus ac, lectus. Nulla semper bibendum justo. In hac habitasse platea dictumst. Aliquam auctor pretium ante. Etiam porta consectetuer erat. Phasellus consequat, nisi eu suscipit elementum, metus leo malesuada pede, vel scelerisque lorem ligula in augue. Sed aliquet. Donec malesuada metus sit amet sapien. Integer non libero. Morbi egestas, mauris posuere consequat sodales, augue lectus suscipit velit, eu commodo lacus dolor congue justo. Suspendisse justo. Curabitur sagittis, lorem tincidunt elementum rhoncus, odio dolor mattis odio, quis ultrices ligula ipsum ac lacus. Nam et sapien ac lacus ultrices sollicitudin. Vestibulum ut dolor nec dui malesuada imperdiet. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; |
|---|
| 986 | |
|---|
| 987 | Quisque pharetra libero quis nibh. Cras lacus orci, commodo et, fringilla non, lobortis non, mauris. Curabitur dui sapien, tristique imperdiet, ultrices vitae, gravida varius, ante. Maecenas ac arcu nec nibh euismod feugiat. Pellentesque sed orci eget enim egestas faucibus. Aenean laoreet leo ornare velit. Nunc fermentum dolor eget massa. Fusce fringilla, tellus in pellentesque sodales, urna mi hendrerit leo, vel adipiscing ligula odio sit amet risus. Cras rhoncus, mi et posuere gravida, purus sem porttitor nisl, auctor laoreet nisl turpis quis ligula. Aliquam in nisi tristique augue egestas lacinia. Aenean ante magna, facilisis a, faucibus at, aliquam laoreet, dui. Ut tellus leo, tristique a, pellentesque ac, bibendum non, ipsum. Curabitur eu neque pretium arcu accumsan tincidunt. Ut ipsum. Quisque congue accumsan elit. Nulla ligula felis, aliquam ultricies, vestibulum vestibulum, semper vel, sapien. Aenean sodales ligula venenatis tellus. Vestibulum leo. Morbi viverra convallis eros. |
|---|
| 988 | |
|---|
| 989 | Phasellus rhoncus pulvinar enim. Ut gravida ante nec lectus. Nam luctus gravida odio. Morbi vitae lorem vitae justo fermentum porttitor. Suspendisse vestibulum magna at purus. Cras nec sem. Duis id felis. Mauris hendrerit dapibus est. Donec semper. Praesent vehicula interdum velit. Ut sed tellus et diam venenatis pulvinar.}; |
|---|
| 990 | } |
|---|
| 991 | $obj->text($preview_text); |
|---|
| 992 | $obj->text_more($preview_more); |
|---|
| 993 | $obj->keywords(MT->translate("sample, entry, preview")); |
|---|
| 994 | $obj->tags(qw( lorem ipsum sample preview )); |
|---|
| 995 | @obj = ($obj); |
|---|
| 996 | } |
|---|
| 997 | return @obj; |
|---|
| 998 | } |
|---|
| 999 | |
|---|
| 1000 | sub reset_blog_templates { |
|---|
| 1001 | my $app = shift; |
|---|
| 1002 | my $q = $app->param; |
|---|
| 1003 | my $perms = $app->permissions |
|---|
| 1004 | or return $app->error( $app->translate("No permissions") ); |
|---|
| 1005 | return $app->error( $app->translate("Permission denied.") ) |
|---|
| 1006 | unless $perms->can_edit_templates; |
|---|
| 1007 | $app->validate_magic() or return; |
|---|
| 1008 | my $blog = MT::Blog->load( $perms->blog_id ) |
|---|
| 1009 | or return $app->error($app->translate('Can\'t load blog #[_1].', $perms->blog_id)); |
|---|
| 1010 | require MT::Template; |
|---|
| 1011 | my @tmpl = MT::Template->load( { blog_id => $blog->id } ); |
|---|
| 1012 | |
|---|
| 1013 | for my $tmpl (@tmpl) { |
|---|
| 1014 | $tmpl->remove or return $app->error( $tmpl->errstr ); |
|---|
| 1015 | } |
|---|
| 1016 | my $set = $blog ? $blog->template_set : undef; |
|---|
| 1017 | require MT::DefaultTemplates; |
|---|
| 1018 | my $tmpl_list = MT::DefaultTemplates->templates($set) || []; |
|---|
| 1019 | my @arch_tmpl; |
|---|
| 1020 | for my $val (@$tmpl_list) { |
|---|
| 1021 | $val->{name} = $app->translate( $val->{name} ); |
|---|
| 1022 | $val->{text} = $app->translate_templatized( $val->{text} ); |
|---|
| 1023 | my $tmpl = MT::Template->new; |
|---|
| 1024 | if ( ( 'widgetset' eq $val->{type} ) |
|---|
| 1025 | && ( exists $val->{modulesets} ) ) { |
|---|
| 1026 | my $modulesets = delete $val->{modulesets}; |
|---|
| 1027 | $tmpl->modulesets( join ',', @$modulesets ); |
|---|
| 1028 | } |
|---|
| 1029 | $tmpl->set_values($val); |
|---|
| 1030 | $tmpl->build_dynamic(0); |
|---|
| 1031 | $tmpl->blog_id( $blog->id ); |
|---|
| 1032 | $tmpl->save |
|---|
| 1033 | or return $app->error( |
|---|
| 1034 | $app->translate( |
|---|
| 1035 | "Populating blog with default templates failed: [_1]", |
|---|
| 1036 | $tmpl->errstr |
|---|
| 1037 | ) |
|---|
| 1038 | ); |
|---|
| 1039 | |
|---|
| 1040 | # FIXME: enumeration of types |
|---|
| 1041 | if ( $val->{type} eq 'archive' |
|---|
| 1042 | || $val->{type} eq 'category' |
|---|
| 1043 | || $val->{type} eq 'page' |
|---|
| 1044 | || $val->{type} eq 'individual' ) |
|---|
| 1045 | { |
|---|
| 1046 | push @arch_tmpl, $tmpl; |
|---|
| 1047 | } |
|---|
| 1048 | } |
|---|
| 1049 | |
|---|
| 1050 | ## Set up mappings from new templates to archive types. |
|---|
| 1051 | for my $tmpl (@arch_tmpl) { |
|---|
| 1052 | my (@at); |
|---|
| 1053 | |
|---|
| 1054 | # FIXME: enumeration of types |
|---|
| 1055 | if ( $tmpl->type eq 'archive' ) { |
|---|
| 1056 | @at = qw( Daily Weekly Monthly Category ); |
|---|
| 1057 | } |
|---|
| 1058 | elsif ( $tmpl->type eq 'page' ) { |
|---|
| 1059 | @at = qw( Page ); |
|---|
| 1060 | } |
|---|
| 1061 | elsif ( $tmpl->type eq 'individual' ) { |
|---|
| 1062 | @at = qw( Individual ); |
|---|
| 1063 | } |
|---|
| 1064 | require MT::TemplateMap; |
|---|
| 1065 | for my $at (@at) { |
|---|
| 1066 | my $map = MT::TemplateMap->new; |
|---|
| 1067 | $map->archive_type($at); |
|---|
| 1068 | $map->is_preferred(1); |
|---|
| 1069 | $map->template_id( $tmpl->id ); |
|---|
| 1070 | $map->blog_id( $tmpl->blog_id ); |
|---|
| 1071 | $map->save |
|---|
| 1072 | or return $app->error( |
|---|
| 1073 | $app->translate( |
|---|
| 1074 | "Setting up mappings failed: [_1]", |
|---|
| 1075 | $map->errstr |
|---|
| 1076 | ) |
|---|
| 1077 | ); |
|---|
| 1078 | } |
|---|
| 1079 | } |
|---|
| 1080 | $app->redirect( |
|---|
| 1081 | $app->uri( |
|---|
| 1082 | 'mode' => 'list', |
|---|
| 1083 | args => |
|---|
| 1084 | { '_type' => 'template', blog_id => $blog->id, 'reset' => 1 } |
|---|
| 1085 | ) |
|---|
| 1086 | ); |
|---|
| 1087 | } |
|---|
| 1088 | |
|---|
| 1089 | sub _generate_map_table { |
|---|
| 1090 | my $app = shift; |
|---|
| 1091 | my ( $blog_id, $template_id ) = @_; |
|---|
| 1092 | |
|---|
| 1093 | require MT::Template; |
|---|
| 1094 | require MT::Blog; |
|---|
| 1095 | my $blog = MT::Blog->load($blog_id); |
|---|
| 1096 | my $template = MT::Template->load($template_id); |
|---|
| 1097 | my $tmpl = $app->load_tmpl('include/archive_maps.tmpl'); |
|---|
| 1098 | my $maps = _populate_archive_loop( $app, $blog, $template ); |
|---|
| 1099 | $tmpl->param( object_type => 'templatemap' ); |
|---|
| 1100 | $tmpl->param( publish_queue_available => eval 'require List::Util; require Scalar::Util; 1;' ); |
|---|
| 1101 | $tmpl->param( object_loop => $maps ) if @$maps; |
|---|
| 1102 | my $html = $tmpl->output(); |
|---|
| 1103 | |
|---|
| 1104 | if ( $html =~ m/<__trans / ) { |
|---|
| 1105 | $html = $app->translate_templatized($html); |
|---|
| 1106 | } |
|---|
| 1107 | $html; |
|---|
| 1108 | } |
|---|
| 1109 | |
|---|
| 1110 | sub _populate_archive_loop { |
|---|
| 1111 | my $app = shift; |
|---|
| 1112 | my ( $blog, $obj ) = @_; |
|---|
| 1113 | |
|---|
| 1114 | my $index = $app->config('IndexBasename'); |
|---|
| 1115 | my $ext = $blog->file_extension || ''; |
|---|
| 1116 | $ext = '.' . $ext if $ext ne ''; |
|---|
| 1117 | |
|---|
| 1118 | require MT::TemplateMap; |
|---|
| 1119 | my @tmpl_maps = MT::TemplateMap->load( { template_id => $obj->id } ); |
|---|
| 1120 | my @maps; |
|---|
| 1121 | my %types; |
|---|
| 1122 | foreach my $map_obj (@tmpl_maps) { |
|---|
| 1123 | my $map = {}; |
|---|
| 1124 | $map->{map_id} = $map_obj->id; |
|---|
| 1125 | $map->{map_is_preferred} = $map_obj->is_preferred; |
|---|
| 1126 | # publish options |
|---|
| 1127 | $map->{map_build_type} = $map_obj->build_type; |
|---|
| 1128 | $map->{ 'map_build_type_' . ( $map_obj->build_type || 0 ) } = 1; |
|---|
| 1129 | my ( $period, $interval ) = _get_schedule( $map_obj->build_interval ); |
|---|
| 1130 | $map->{ 'map_schedule_period_' . $period } = 1 |
|---|
| 1131 | if defined $period; |
|---|
| 1132 | $map->{map_schedule_interval} = $interval |
|---|
| 1133 | if defined $interval; |
|---|
| 1134 | |
|---|
| 1135 | my $at = $map->{archive_type} = $map_obj->archive_type; |
|---|
| 1136 | $types{$at}++; |
|---|
| 1137 | $map->{ 'archive_type_preferred_' . $blog->archive_type_preferred } = 1 |
|---|
| 1138 | if $blog->archive_type_preferred; |
|---|
| 1139 | $map->{file_template} = $map_obj->file_template |
|---|
| 1140 | if $map_obj->file_template; |
|---|
| 1141 | |
|---|
| 1142 | my $archiver = $app->publisher->archiver($at); |
|---|
| 1143 | next unless $archiver; |
|---|
| 1144 | $map->{archive_label} = $archiver->archive_label; |
|---|
| 1145 | my $tmpls = $archiver->default_archive_templates; |
|---|
| 1146 | my $tmpl_loop = []; |
|---|
| 1147 | foreach (@$tmpls) { |
|---|
| 1148 | my $name = $_->{label}; |
|---|
| 1149 | $name =~ s/\.html$/$ext/; |
|---|
| 1150 | $name =~ s/index$ext$/$index$ext/; |
|---|
| 1151 | push @$tmpl_loop, |
|---|
| 1152 | { |
|---|
| 1153 | name => $name, |
|---|
| 1154 | value => $_->{template}, |
|---|
| 1155 | default => ( $_->{default} || 0 ), |
|---|
| 1156 | }; |
|---|
| 1157 | } |
|---|
| 1158 | |
|---|
| 1159 | my $custom = 1; |
|---|
| 1160 | |
|---|
| 1161 | foreach (@$tmpl_loop) { |
|---|
| 1162 | if ( ( !$map->{file_template} && $_->{default} ) |
|---|
| 1163 | || ( $map->{file_template} eq $_->{value} ) ) |
|---|
| 1164 | { |
|---|
| 1165 | $_->{selected} = 1; |
|---|
| 1166 | $custom = 0; |
|---|
| 1167 | $map->{file_template} = $_->{value} |
|---|
| 1168 | if !$map->{file_template}; |
|---|
| 1169 | } |
|---|
| 1170 | } |
|---|
| 1171 | if ($custom) { |
|---|
| 1172 | unshift @$tmpl_loop, |
|---|
| 1173 | { |
|---|
| 1174 | name => $map->{file_template}, |
|---|
| 1175 | value => $map->{file_template}, |
|---|
| 1176 | selected => 1, |
|---|
| 1177 | }; |
|---|
| 1178 | } |
|---|
| 1179 | |
|---|
| 1180 | $map->{archive_tmpl_loop} = $tmpl_loop; |
|---|
| 1181 | if ( |
|---|
| 1182 | 1 < MT::TemplateMap->count( |
|---|
| 1183 | { archive_type => $at, blog_id => $obj->blog_id } |
|---|
| 1184 | ) |
|---|
| 1185 | ) |
|---|
| 1186 | { |
|---|
| 1187 | $map->{has_multiple_archives} = 1; |
|---|
| 1188 | } |
|---|
| 1189 | |
|---|
| 1190 | push @maps, $map; |
|---|
| 1191 | } |
|---|
| 1192 | @maps = sort { MT::App::CMS::archive_type_sorter( $a, $b ) } @maps; |
|---|
| 1193 | return \@maps; |
|---|
| 1194 | } |
|---|
| 1195 | |
|---|
| 1196 | sub delete_map { |
|---|
| 1197 | my $app = shift; |
|---|
| 1198 | $app->validate_magic() or return; |
|---|
| 1199 | my $perms = $app->{perms} |
|---|
| 1200 | or return $app->error( $app->translate("No permissions") ); |
|---|
| 1201 | my $q = $app->param; |
|---|
| 1202 | my $id = $q->param('id'); |
|---|
| 1203 | |
|---|
| 1204 | require MT::TemplateMap; |
|---|
| 1205 | MT::TemplateMap->remove( { id => $id } ); |
|---|
| 1206 | my $html = |
|---|
| 1207 | _generate_map_table( $app, $q->param('blog_id'), |
|---|
| 1208 | $q->param('template_id') ); |
|---|
| 1209 | $app->{no_print_body} = 1; |
|---|
| 1210 | $app->send_http_header("text/plain"); |
|---|
| 1211 | $app->print($html); |
|---|
| 1212 | } |
|---|
| 1213 | |
|---|
| 1214 | sub add_map { |
|---|
| 1215 | my $app = shift; |
|---|
| 1216 | $app->validate_magic() or return; |
|---|
| 1217 | my $perms = $app->{perms} |
|---|
| 1218 | or return $app->error( $app->translate("No permissions") ); |
|---|
| 1219 | |
|---|
| 1220 | my $q = $app->param; |
|---|
| 1221 | |
|---|
| 1222 | require MT::TemplateMap; |
|---|
| 1223 | my $blog_id = $q->param('blog_id'); |
|---|
| 1224 | my $at = $q->param('new_archive_type'); |
|---|
| 1225 | my $exist = MT::TemplateMap->exist( |
|---|
| 1226 | { |
|---|
| 1227 | blog_id => $blog_id, |
|---|
| 1228 | archive_type => $at |
|---|
| 1229 | } |
|---|
| 1230 | ); |
|---|
| 1231 | my $map = MT::TemplateMap->new; |
|---|
| 1232 | $map->is_preferred( $exist ? 0 : 1 ); |
|---|
| 1233 | $map->template_id( scalar $q->param('template_id') ); |
|---|
| 1234 | $map->blog_id($blog_id); |
|---|
| 1235 | $map->archive_type($at); |
|---|
| 1236 | $map->save |
|---|
| 1237 | or return $app->error( |
|---|
| 1238 | $app->translate( "Saving map failed: [_1]", $map->errstr ) ); |
|---|
| 1239 | my $html = |
|---|
| 1240 | _generate_map_table( $app, $blog_id, scalar $q->param('template_id') ); |
|---|
| 1241 | $app->{no_print_body} = 1; |
|---|
| 1242 | $app->send_http_header("text/plain"); |
|---|
| 1243 | $app->print($html); |
|---|
| 1244 | } |
|---|
| 1245 | |
|---|
| 1246 | sub can_view { |
|---|
| 1247 | my ( $eh, $app, $id ) = @_; |
|---|
| 1248 | my $perms = $app->permissions; |
|---|
| 1249 | return !$id || ($perms && $perms->can_edit_templates) || (!$app->blog && $app->user->can_edit_templates); |
|---|
| 1250 | } |
|---|
| 1251 | |
|---|
| 1252 | sub can_save { |
|---|
| 1253 | my ( $eh, $app, $id ) = @_; |
|---|
| 1254 | my $perms = $app->permissions; |
|---|
| 1255 | return ($perms && $perms->can_edit_templates) || (!$perms && $app->user->can_edit_templates); |
|---|
| 1256 | } |
|---|
| 1257 | |
|---|
| 1258 | sub can_delete { |
|---|
| 1259 | my ( $eh, $app, $obj ) = @_; |
|---|
| 1260 | return 1 if $app->user->is_superuser(); |
|---|
| 1261 | my $perms = $app->permissions; |
|---|
| 1262 | return ($perms && $perms->can_edit_templates) || (!$perms && $app->user->can_edit_templates); |
|---|
| 1263 | } |
|---|
| 1264 | |
|---|
| 1265 | sub pre_save { |
|---|
| 1266 | my $eh = shift; |
|---|
| 1267 | my ( $app, $obj ) = @_; |
|---|
| 1268 | |
|---|
| 1269 | ## Strip linefeed characters. |
|---|
| 1270 | ( my $text = $obj->text ) =~ tr/\r//d; |
|---|
| 1271 | |
|---|
| 1272 | if ($text =~ m/<(MT|_)_trans/i) { |
|---|
| 1273 | $text = $app->translate_templatized($text); |
|---|
| 1274 | } |
|---|
| 1275 | |
|---|
| 1276 | $obj->text($text); |
|---|
| 1277 | |
|---|
| 1278 | # update text heights if necessary |
|---|
| 1279 | if ( my $perms = $app->permissions ) { |
|---|
| 1280 | my $prefs = $perms->template_prefs || ''; |
|---|
| 1281 | my $text_height = $app->param('text_height'); |
|---|
| 1282 | if ( defined $text_height ) { |
|---|
| 1283 | my ($pref_text_height) = $prefs =~ m/\btext:(\d+)\b/; |
|---|
| 1284 | $pref_text_height ||= 0; |
|---|
| 1285 | if ( $text_height != $pref_text_height ) { |
|---|
| 1286 | if ( $prefs =~ m/\btext\b/ ) { |
|---|
| 1287 | $prefs =~ s/\btext(:\d+)\b/text:$text_height/; |
|---|
| 1288 | } |
|---|
| 1289 | else { |
|---|
| 1290 | $prefs = 'text:' . $text_height . ',' . $prefs; |
|---|
| 1291 | } |
|---|
| 1292 | } |
|---|
| 1293 | } |
|---|
| 1294 | |
|---|
| 1295 | if ( $prefs ne ( $perms->template_prefs || '' ) ) { |
|---|
| 1296 | $perms->template_prefs($prefs); |
|---|
| 1297 | $perms->save; |
|---|
| 1298 | } |
|---|
| 1299 | } |
|---|
| 1300 | |
|---|
| 1301 | # module caching |
|---|
| 1302 | $obj->include_with_ssi( $app->param('include_with_ssi') ? 1 : 0 ); |
|---|
| 1303 | $obj->cache_path( $app->param('cache_path')); |
|---|
| 1304 | my $cache_expire_type = $app->param('cache_expire_type') || ''; |
|---|
| 1305 | $obj->cache_expire_type($cache_expire_type); |
|---|
| 1306 | my $period = $app->param('cache_expire_period'); |
|---|
| 1307 | my $interval = $app->param('cache_expire_interval'); |
|---|
| 1308 | my $sec = _get_interval( $period, $interval ); |
|---|
| 1309 | $obj->cache_expire_interval($sec) if defined $sec; |
|---|
| 1310 | my $q = $app->param; |
|---|
| 1311 | my @events; |
|---|
| 1312 | |
|---|
| 1313 | foreach my $name ( $q->param('cache_expire_event') ) { |
|---|
| 1314 | push @events, $name; |
|---|
| 1315 | } |
|---|
| 1316 | $obj->cache_expire_event( join ',', @events ) if $#events >= 0; |
|---|
| 1317 | if ( $cache_expire_type == 1 ) { |
|---|
| 1318 | return $eh->error( |
|---|
| 1319 | $app->translate("You should not be able to enter 0 as the time.") ) |
|---|
| 1320 | if $interval == 0; |
|---|
| 1321 | } |
|---|
| 1322 | elsif ( $cache_expire_type == 2 ) { |
|---|
| 1323 | return $eh->error( |
|---|
| 1324 | $app->translate("You must select at least one event checkbox.") ) |
|---|
| 1325 | if !@events; |
|---|
| 1326 | } |
|---|
| 1327 | |
|---|
| 1328 | require MT::PublishOption; |
|---|
| 1329 | my $build_type = $app->param('build_type'); |
|---|
| 1330 | |
|---|
| 1331 | if ( $build_type == MT::PublishOption::SCHEDULED() ) { |
|---|
| 1332 | my $period = $app->param('schedule_period'); |
|---|
| 1333 | my $interval = $app->param('schedule_interval'); |
|---|
| 1334 | my $sec = _get_interval( $period, $interval ); |
|---|
| 1335 | $obj->build_interval($sec); |
|---|
| 1336 | } |
|---|
| 1337 | my $rebuild_me = 1; |
|---|
| 1338 | if ( $build_type == MT::PublishOption::DISABLED() |
|---|
| 1339 | || $build_type == MT::PublishOption::MANUALLY() ) |
|---|
| 1340 | { |
|---|
| 1341 | $rebuild_me = 0; |
|---|
| 1342 | } |
|---|
| 1343 | $obj->rebuild_me($rebuild_me); |
|---|
| 1344 | 1; |
|---|
| 1345 | } |
|---|
| 1346 | |
|---|
| 1347 | sub post_save { |
|---|
| 1348 | my $eh = shift; |
|---|
| 1349 | my ( $app, $obj, $original ) = @_; |
|---|
| 1350 | |
|---|
| 1351 | my $sess_obj = $app->autosave_session_obj; |
|---|
| 1352 | $sess_obj->remove if $sess_obj; |
|---|
| 1353 | |
|---|
| 1354 | my $dynamic = 0; |
|---|
| 1355 | my $q = $app->param; |
|---|
| 1356 | my $type = $q->param('type'); |
|---|
| 1357 | # FIXME: enumeration of types |
|---|
| 1358 | if ( $type eq 'custom' |
|---|
| 1359 | || $type eq 'index' |
|---|
| 1360 | || $type eq 'widget' |
|---|
| 1361 | || $type eq 'widgetset' ) |
|---|
| 1362 | { |
|---|
| 1363 | $dynamic = $obj->build_dynamic; |
|---|
| 1364 | } |
|---|
| 1365 | else |
|---|
| 1366 | { |
|---|
| 1367 | # archive template specific post_save tasks |
|---|
| 1368 | require MT::TemplateMap; |
|---|
| 1369 | my @p = $q->param; |
|---|
| 1370 | for my $p (@p) { |
|---|
| 1371 | my $map; |
|---|
| 1372 | if ( $p =~ /^archive_tmpl_preferred_(\w+)_(\d+)$/ ) { |
|---|
| 1373 | my $at = $1; |
|---|
| 1374 | my $map_id = $2; |
|---|
| 1375 | $map = MT::TemplateMap->load($map_id) |
|---|
| 1376 | or next; |
|---|
| 1377 | $map->prefer( $q->param($p) ); # prefer method saves in itself |
|---|
| 1378 | } |
|---|
| 1379 | elsif ( $p =~ /^archive_file_tmpl_(\d+)$/ ) { |
|---|
| 1380 | my $map_id = $1; |
|---|
| 1381 | $map = MT::TemplateMap->load($map_id) |
|---|
| 1382 | or next; |
|---|
| 1383 | $map->file_template( $q->param($p) ); |
|---|
| 1384 | $map->save; |
|---|
| 1385 | } |
|---|
| 1386 | elsif ( $p =~ /^map_build_type_(\d+)$/ ) { |
|---|
| 1387 | my $map_id = $1; |
|---|
| 1388 | $map = MT::TemplateMap->load($map_id) |
|---|
| 1389 | or next; |
|---|
| 1390 | my $build_type = $q->param($p); |
|---|
| 1391 | require MT::PublishOption; |
|---|
| 1392 | $map->build_type($build_type); |
|---|
| 1393 | if ( $build_type == MT::PublishOption::SCHEDULED() ) { |
|---|
| 1394 | my $period = $q->param( 'map_schedule_period_' . $map_id ); |
|---|
| 1395 | my $interval = $q->param( 'map_schedule_interval_' . $map_id ); |
|---|
| 1396 | my $sec = _get_interval( $period, $interval ); |
|---|
| 1397 | $map->build_interval($sec); |
|---|
| 1398 | } |
|---|
| 1399 | $map->save; |
|---|
| 1400 | } |
|---|
| 1401 | if ( !$dynamic |
|---|
| 1402 | && $map && $map->build_type == MT::PublishOption::DYNAMIC() ) |
|---|
| 1403 | { |
|---|
| 1404 | $dynamic = 1; |
|---|
| 1405 | } |
|---|
| 1406 | } |
|---|
| 1407 | } |
|---|
| 1408 | |
|---|
| 1409 | if ( !$original->id ) { |
|---|
| 1410 | $app->log( |
|---|
| 1411 | { |
|---|
| 1412 | message => $app->translate( |
|---|
| 1413 | "Template '[_1]' (ID:[_2]) created by '[_3]'", |
|---|
| 1414 | $obj->name, $obj->id, $app->user->name |
|---|
| 1415 | ), |
|---|
| 1416 | level => MT::Log::INFO(), |
|---|
| 1417 | class => 'template', |
|---|
| 1418 | category => 'new', |
|---|
| 1419 | } |
|---|
| 1420 | ); |
|---|
| 1421 | } |
|---|
| 1422 | |
|---|
| 1423 | if ( $dynamic ) { |
|---|
| 1424 | if ( $obj->type eq 'index' ) { |
|---|
| 1425 | $app->rebuild_indexes( |
|---|
| 1426 | BlogID => $obj->blog_id, |
|---|
| 1427 | Template => $obj, |
|---|
| 1428 | NoStatic => 1, |
|---|
| 1429 | ) or return $app->publish_error(); # XXXX |
|---|
| 1430 | } |
|---|
| 1431 | if ( my $blog = $app->blog ) { |
|---|
| 1432 | require MT::CMS::Blog; |
|---|
| 1433 | my ( $path, $url ); |
|---|
| 1434 | if ( $obj->type eq 'index' ) { |
|---|
| 1435 | $path = $blog->site_path; |
|---|
| 1436 | $url = $blog->site_url; |
|---|
| 1437 | } |
|---|
| 1438 | else { |
|---|
| 1439 | # must be archive since other types can't be dynamic |
|---|
| 1440 | if ( $path = $blog->archive_path ) { |
|---|
| 1441 | $url = $blog->archive_url; |
|---|
| 1442 | } |
|---|
| 1443 | else { |
|---|
| 1444 | $path = $blog->site_path; |
|---|
| 1445 | $url = $blog->site_url; |
|---|
| 1446 | } |
|---|
| 1447 | } |
|---|
| 1448 | # specific arguments so not to overwrite mtview and htaccess |
|---|
| 1449 | MT::CMS::Blog::prepare_dynamic_publishing( |
|---|
| 1450 | $eh, |
|---|
| 1451 | $blog, |
|---|
| 1452 | undef, |
|---|
| 1453 | undef, |
|---|
| 1454 | $path, |
|---|
| 1455 | $url |
|---|
| 1456 | ); |
|---|
| 1457 | } |
|---|
| 1458 | } |
|---|
| 1459 | 1; |
|---|
| 1460 | } |
|---|
| 1461 | |
|---|
| 1462 | sub post_delete { |
|---|
| 1463 | my ( $eh, $app, $obj ) = @_; |
|---|
| 1464 | |
|---|
| 1465 | $app->log( |
|---|
| 1466 | { |
|---|
| 1467 | message => $app->translate( |
|---|
| 1468 | "Template '[_1]' (ID:[_2]) deleted by '[_3]'", |
|---|
| 1469 | $obj->name, $obj->id, $app->user->name |
|---|
| 1470 | ), |
|---|
| 1471 | level => MT::Log::INFO(), |
|---|
| 1472 | class => 'system', |
|---|
| 1473 | category => 'delete' |
|---|
| 1474 | } |
|---|
| 1475 | ); |
|---|
| 1476 | } |
|---|
| 1477 | |
|---|
| 1478 | sub build_template_table { |
|---|
| 1479 | my $app = shift; |
|---|
| 1480 | my (%args) = @_; |
|---|
| 1481 | |
|---|
| 1482 | my $perms = $app->permissions; |
|---|
| 1483 | my $list_pref = $app->list_pref('template'); |
|---|
| 1484 | my $limit = $args{limit}; |
|---|
| 1485 | my $param = $args{param} || {}; |
|---|
| 1486 | my $iter; |
|---|
| 1487 | if ( $args{load_args} ) { |
|---|
| 1488 | my $class = $app->model('template'); |
|---|
| 1489 | $iter = $class->load_iter( @{ $args{load_args} } ); |
|---|
| 1490 | } |
|---|
| 1491 | elsif ( $args{iter} ) { |
|---|
| 1492 | $iter = $args{iter}; |
|---|
| 1493 | } |
|---|
| 1494 | elsif ( $args{items} ) { |
|---|
| 1495 | $iter = sub { pop @{ $args{items} } }; |
|---|
| 1496 | $limit = scalar @{ $args{items} }; |
|---|
| 1497 | } |
|---|
| 1498 | return [] unless $iter; |
|---|
| 1499 | |
|---|
| 1500 | my @data; |
|---|
| 1501 | my $i; |
|---|
| 1502 | my %blogs; |
|---|
| 1503 | while ( my $tmpl = $iter->() ) { |
|---|
| 1504 | my $blog = $blogs{ $tmpl->blog_id } ||= |
|---|
| 1505 | MT::Blog->load( $tmpl->blog_id ) if $tmpl->blog_id; |
|---|
| 1506 | |
|---|
| 1507 | my $row = $tmpl->column_values; |
|---|
| 1508 | $row->{name} = '' if !defined $row->{name}; |
|---|
| 1509 | $row->{name} =~ s/^\s+|\s+$//g; |
|---|
| 1510 | $row->{name} = "(" . $app->translate("No Name") . ")" |
|---|
| 1511 | if $row->{name} eq ''; |
|---|
| 1512 | my $published_url = $tmpl->published_url; |
|---|
| 1513 | $row->{published_url} = $published_url if $published_url; |
|---|
| 1514 | $row->{use_cache} = ( ($tmpl->cache_expire_type || 0) != 0 ) ? 1 : 0; |
|---|
| 1515 | |
|---|
| 1516 | # FIXME: enumeration of types |
|---|
| 1517 | $row->{can_delete} = 1 |
|---|
| 1518 | if $tmpl->type =~ m/(custom|index|archive|page|individual|category|widget)/; |
|---|
| 1519 | if ($blog) { |
|---|
| 1520 | $row->{weblog_name} = $blog->name; |
|---|
| 1521 | } |
|---|
| 1522 | elsif ($tmpl->blog_id) { |
|---|
| 1523 | $row->{weblog_name} = '* ' . $app->translate('Orphaned') . ' *'; |
|---|
| 1524 | } |
|---|
| 1525 | else { |
|---|
| 1526 | $row->{weblog_name} = '* ' . $app->translate('Global Templates') . ' *'; |
|---|
| 1527 | } |
|---|
| 1528 | $row->{object} = $tmpl; |
|---|
| 1529 | push @data, $row; |
|---|
| 1530 | last if defined($limit) && (@data > $limit); |
|---|
| 1531 | } |
|---|
| 1532 | return [] unless @data; |
|---|
| 1533 | |
|---|
| 1534 | $param->{template_table}[0] = {%$list_pref}; |
|---|
| 1535 | $param->{template_table}[0]{object_loop} = \@data; |
|---|
| 1536 | $param->{template_table}[0]{object_type} = 'template'; |
|---|
| 1537 | $app->load_list_actions( 'template', $param ); |
|---|
| 1538 | $param->{object_loop} = \@data; |
|---|
| 1539 | \@data; |
|---|
| 1540 | } |
|---|
| 1541 | |
|---|
| 1542 | sub dialog_publishing_profile { |
|---|
| 1543 | my $app = shift; |
|---|
| 1544 | $app->validate_magic or return; |
|---|
| 1545 | |
|---|
| 1546 | my $blog = $app->blog; |
|---|
| 1547 | $app->assert( $blog ) or return; |
|---|
| 1548 | |
|---|
| 1549 | # permission check |
|---|
| 1550 | my $perms = $app->permissions; |
|---|
| 1551 | return $app->errtrans("Permission denied.") |
|---|
| 1552 | unless $app->user->is_superuser || |
|---|
| 1553 | $perms->can_administer_blog || |
|---|
| 1554 | $perms->can_edit_templates; |
|---|
| 1555 | |
|---|
| 1556 | my $param = {}; |
|---|
| 1557 | $param->{dynamicity} = $blog->custom_dynamic_templates || 'none'; |
|---|
| 1558 | $param->{screen_id} = "publishing-profile-dialog"; |
|---|
| 1559 | $param->{return_args} = $app->param('return_args'); |
|---|
| 1560 | |
|---|
| 1561 | $app->build_page('dialog/publishing_profile.tmpl', |
|---|
| 1562 | $param); |
|---|
| 1563 | } |
|---|
| 1564 | |
|---|
| 1565 | sub dialog_refresh_templates { |
|---|
| 1566 | my $app = shift; |
|---|
| 1567 | $app->validate_magic or return; |
|---|
| 1568 | |
|---|
| 1569 | # permission check |
|---|
| 1570 | my $perms = $app->permissions; |
|---|
| 1571 | return $app->errtrans("Permission denied.") |
|---|
| 1572 | unless $app->user->is_superuser || |
|---|
| 1573 | $perms->can_administer_blog || |
|---|
| 1574 | $perms->can_edit_templates; |
|---|
| 1575 | |
|---|
| 1576 | my $param = {}; |
|---|
| 1577 | my $blog = $app->blog; |
|---|
| 1578 | $param->{return_args} = $app->param('return_args'); |
|---|
| 1579 | |
|---|
| 1580 | if ($blog) { |
|---|
| 1581 | $param->{blog_id} = $blog->id; |
|---|
| 1582 | |
|---|
| 1583 | my $sets = $app->registry("template_sets"); |
|---|
| 1584 | $sets->{$_}{key} = $_ for keys %$sets; |
|---|
| 1585 | $sets = $app->filter_conditional_list([ values %$sets ]); |
|---|
| 1586 | |
|---|
| 1587 | no warnings; # some sets may not define an order |
|---|
| 1588 | @$sets = sort { $a->{order} <=> $b->{order} } @$sets; |
|---|
| 1589 | $param->{'template_set_loop'} = $sets; |
|---|
| 1590 | |
|---|
| 1591 | my $existing_set = $blog->template_set || 'mt_blog'; |
|---|
| 1592 | foreach (@$sets) { |
|---|
| 1593 | if ($_->{key} eq $existing_set) { |
|---|
| 1594 | $_->{selected} = 1; |
|---|
| 1595 | } |
|---|
| 1596 | } |
|---|
| 1597 | $param->{'template_set_index'} = $#$sets; |
|---|
| 1598 | $param->{'template_set_count'} = scalar @$sets; |
|---|
| 1599 | |
|---|
| 1600 | $param->{template_sets} = $sets; |
|---|
| 1601 | $param->{screen_id} = "refresh-templates-dialog"; |
|---|
| 1602 | } |
|---|
| 1603 | |
|---|
| 1604 | # load template sets |
|---|
| 1605 | $app->build_page('dialog/refresh_templates.tmpl', |
|---|
| 1606 | $param); |
|---|
| 1607 | } |
|---|
| 1608 | |
|---|
| 1609 | sub refresh_all_templates { |
|---|
| 1610 | my ($app) = @_; |
|---|
| 1611 | |
|---|
| 1612 | my $backup = 0; |
|---|
| 1613 | if ($app->param('backup')) { |
|---|
| 1614 | # refresh templates dialog uses a 'backup' field |
|---|
| 1615 | $backup = 1; |
|---|
| 1616 | } |
|---|
| 1617 | |
|---|
| 1618 | my $template_set = $app->param('template_set'); |
|---|
| 1619 | my $refresh_type = $app->param('refresh_type') || 'refresh'; |
|---|
| 1620 | |
|---|
| 1621 | my $t = time; |
|---|
| 1622 | |
|---|
| 1623 | my @id; |
|---|
| 1624 | if ($app->param('blog_id')) { |
|---|
| 1625 | @id = ( scalar $app->param('blog_id') ); |
|---|
| 1626 | } |
|---|
| 1627 | else { |
|---|
| 1628 | @id = $app->param('id'); |
|---|
| 1629 | if (! @id) { |
|---|
| 1630 | # refresh global templates |
|---|
| 1631 | @id = ( 0 ); |
|---|
| 1632 | } |
|---|
| 1633 | } |
|---|
| 1634 | |
|---|
| 1635 | require MT::Template; |
|---|
| 1636 | require MT::DefaultTemplates; |
|---|
| 1637 | require MT::Blog; |
|---|
| 1638 | require MT::Permission; |
|---|
| 1639 | require MT::Util; |
|---|
| 1640 | |
|---|
| 1641 | foreach my $blog_id (@id) { |
|---|
| 1642 | my $blog; |
|---|
| 1643 | if ($blog_id) { |
|---|
| 1644 | $blog = MT::Blog->load($blog_id); |
|---|
| 1645 | next unless $blog; |
|---|
| 1646 | } |
|---|
| 1647 | if ( !$app->user->is_superuser() ) { |
|---|
| 1648 | my $perms = MT::Permission->load( |
|---|
| 1649 | { blog_id => $blog_id, author_id => $app->user->id } ); |
|---|
| 1650 | if ( |
|---|
| 1651 | !$perms |
|---|
| 1652 | || ( !$perms->can_edit_templates() |
|---|
| 1653 | && !$perms->can_administer_blog() ) |
|---|
| 1654 | ) |
|---|
| 1655 | { |
|---|
| 1656 | next; |
|---|
| 1657 | } |
|---|
| 1658 | } |
|---|
| 1659 | |
|---|
| 1660 | my $tmpl_list; |
|---|
| 1661 | if ($blog_id) { |
|---|
| 1662 | |
|---|
| 1663 | if ($refresh_type eq 'clean') { |
|---|
| 1664 | # the user wants to back up all templates and |
|---|
| 1665 | # install the new ones |
|---|
| 1666 | |
|---|
| 1667 | my @ts = MT::Util::offset_time_list( $t, $blog_id ); |
|---|
| 1668 | my $ts = sprintf "%04d-%02d-%02d %02d:%02d:%02d", |
|---|
| 1669 | $ts[5] + 1900, $ts[4] + 1, @ts[ 3, 2, 1, 0 ]; |
|---|
| 1670 | |
|---|
| 1671 | my $tmpl_iter = MT::Template->load_iter({ |
|---|
| 1672 | blog_id => $blog_id, |
|---|
| 1673 | type => { not => 'backup' }, |
|---|
| 1674 | }); |
|---|
| 1675 | |
|---|
| 1676 | while (my $tmpl = $tmpl_iter->()) { |
|---|
| 1677 | if ($backup) { |
|---|
| 1678 | # zap all template maps |
|---|
| 1679 | require MT::TemplateMap; |
|---|
| 1680 | MT::TemplateMap->remove({ |
|---|
| 1681 | template_id => $tmpl->id, |
|---|
| 1682 | }); |
|---|
| 1683 | $tmpl->type('backup'); |
|---|
| 1684 | $tmpl->name( |
|---|
| 1685 | $tmpl->name . ' (Backup from ' . $ts . ')' ); |
|---|
| 1686 | $tmpl->identifier(undef); |
|---|
| 1687 | $tmpl->rebuild_me(0); |
|---|
| 1688 | $tmpl->linked_file(undef); |
|---|
| 1689 | $tmpl->outfile(''); |
|---|
| 1690 | $tmpl->save; |
|---|
| 1691 | } else { |
|---|
| 1692 | $tmpl->remove; |
|---|
| 1693 | } |
|---|
| 1694 | } |
|---|
| 1695 | |
|---|
| 1696 | # This also creates our template mappings |
|---|
| 1697 | $blog->create_default_templates( $template_set || |
|---|
| 1698 | $blog->template_set || 'mt_blog' ); |
|---|
| 1699 | |
|---|
| 1700 | if ($template_set) { |
|---|
| 1701 | $blog->template_set( $template_set ); |
|---|
| 1702 | $blog->save; |
|---|
| 1703 | $app->run_callbacks( 'blog_template_set_change', { blog => $blog } ); |
|---|
| 1704 | } |
|---|
| 1705 | |
|---|
| 1706 | next; |
|---|
| 1707 | } |
|---|
| 1708 | |
|---|
| 1709 | $tmpl_list = MT::DefaultTemplates->templates($template_set || $blog->template_set) || MT::DefaultTemplates->templates(); |
|---|
| 1710 | } |
|---|
| 1711 | else { |
|---|
| 1712 | $tmpl_list = MT::DefaultTemplates->templates(); |
|---|
| 1713 | } |
|---|
| 1714 | |
|---|
| 1715 | foreach my $val (@$tmpl_list) { |
|---|
| 1716 | if ($blog_id) { |
|---|
| 1717 | # when refreshing blog templates, |
|---|
| 1718 | # skip over global templates which |
|---|
| 1719 | # specify a blog_id of 0... |
|---|
| 1720 | next if $val->{global}; |
|---|
| 1721 | } |
|---|
| 1722 | else { |
|---|
| 1723 | next unless exists $val->{global}; |
|---|
| 1724 | } |
|---|
| 1725 | |
|---|
| 1726 | if ( !$val->{orig_name} ) { |
|---|
| 1727 | $val->{orig_name} = $val->{name}; |
|---|
| 1728 | $val->{name} = $app->translate( $val->{name} ); |
|---|
| 1729 | $val->{text} = $app->translate_templatized( $val->{text} ); |
|---|
| 1730 | } |
|---|
| 1731 | |
|---|
| 1732 | my $orig_name = $val->{orig_name}; |
|---|
| 1733 | |
|---|
| 1734 | my @ts = MT::Util::offset_time_list( $t, ( $blog_id ? $blog_id : undef ) ); |
|---|
| 1735 | my $ts = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $ts[5] + 1900, |
|---|
| 1736 | $ts[4] + 1, @ts[ 3, 2, 1, 0 ]; |
|---|
| 1737 | |
|---|
| 1738 | my $terms = {}; |
|---|
| 1739 | $terms->{blog_id} = $blog_id; |
|---|
| 1740 | $terms->{type} = $val->{type}; |
|---|
| 1741 | if ( $val->{type} =~ |
|---|
| 1742 | m/^(archive|individual|page|category|index|custom|widget)$/ ) |
|---|
| 1743 | { |
|---|
| 1744 | $terms->{name} = $val->{name}; |
|---|
| 1745 | } |
|---|
| 1746 | else { |
|---|
| 1747 | $terms->{identifier} = $val->{identifier}; |
|---|
| 1748 | } |
|---|
| 1749 | |
|---|
| 1750 | # this should only return 1 template; we're searching |
|---|
| 1751 | # within a given blog for a specific type of template (for |
|---|
| 1752 | # "system" templates; or for a type + name, which should be |
|---|
| 1753 | # unique for that blog. |
|---|
| 1754 | my $tmpl = MT::Template->load($terms); |
|---|
| 1755 | if ($tmpl && $backup) { |
|---|
| 1756 | |
|---|
| 1757 | # check for default template text... |
|---|
| 1758 | # if it is a default template, then outright replace it |
|---|
| 1759 | my $text = $tmpl->text; |
|---|
| 1760 | $text =~ s/\s+//g; |
|---|
| 1761 | |
|---|
| 1762 | my $def_text = $val->{text}; |
|---|
| 1763 | $def_text =~ s/\s+//g; |
|---|
| 1764 | |
|---|
| 1765 | # if it has been customized, back it up to a new tmpl record |
|---|
| 1766 | if ($def_text ne $text) { |
|---|
| 1767 | my $backup = $tmpl->clone; |
|---|
| 1768 | delete $backup->{column_values} |
|---|
| 1769 | ->{id}; # make sure we don't overwrite original |
|---|
| 1770 | delete $backup->{changed_cols}->{id}; |
|---|
| 1771 | $backup->name( |
|---|
| 1772 | $backup->name . $app->translate( ' (Backup from [_1])', $ts ) ); |
|---|
| 1773 | $backup->type('backup'); |
|---|
| 1774 | # if ( $backup->type !~ |
|---|
| 1775 | # m/^(archive|individual|page|category|index|custom|widget)$/ ) |
|---|
| 1776 | # { |
|---|
| 1777 | # $backup->type('custom') |
|---|
| 1778 | # ; # system templates can't be created |
|---|
| 1779 | # } |
|---|
| 1780 | $backup->outfile(''); |
|---|
| 1781 | $backup->linked_file( $tmpl->linked_file ); |
|---|
| 1782 | $backup->identifier(undef); |
|---|
| 1783 | $backup->rebuild_me(0); |
|---|
| 1784 | $backup->build_dynamic(0); |
|---|
| 1785 | $backup->save; |
|---|
| 1786 | } |
|---|
| 1787 | } |
|---|
| 1788 | if ($tmpl) { |
|---|
| 1789 | # we found that the previous template had not been |
|---|
| 1790 | # altered, so replace it with new default template... |
|---|
| 1791 | if ( ( 'widgetset' eq $val->{type} ) |
|---|
| 1792 | && ( exists $val->{widgets} ) ) { |
|---|
| 1793 | my $modulesets = delete $val->{widgets}; |
|---|
| 1794 | $tmpl->modulesets( MT::Template->widgets_to_modulesets($modulesets, $blog_id) ); |
|---|
| 1795 | } |
|---|
| 1796 | $tmpl->text( $val->{text} ); |
|---|
| 1797 | $tmpl->identifier( $val->{identifier} ); |
|---|
| 1798 | $tmpl->type( $val->{type} ) |
|---|
| 1799 | ; # fixes mismatch of types for cases like "archive" => "individual" |
|---|
| 1800 | $tmpl->linked_file(''); |
|---|
| 1801 | $tmpl->save; |
|---|
| 1802 | } |
|---|
| 1803 | else { |
|---|
| 1804 | # create this one... |
|---|
| 1805 | my $tmpl = new MT::Template; |
|---|
| 1806 | if ( ( 'widgetset' eq $val->{type} ) |
|---|
| 1807 | && ( exists $val->{widgets} ) ) { |
|---|
| 1808 | my $modulesets = delete $val->{widgets}; |
|---|
| 1809 | $tmpl->modulesets( MT::Template->widgets_to_modulesets($modulesets, $blog_id) ); |
|---|
| 1810 | } |
|---|
| 1811 | $tmpl->build_dynamic(0); |
|---|
| 1812 | $tmpl->set_values( |
|---|
| 1813 | { |
|---|
| 1814 | text => $val->{text}, |
|---|
| 1815 | name => $val->{name}, |
|---|
| 1816 | type => $val->{type}, |
|---|
| 1817 | identifier => $val->{identifier}, |
|---|
| 1818 | outfile => $val->{outfile}, |
|---|
| 1819 | rebuild_me => $val->{rebuild_me}, |
|---|
| 1820 | } |
|---|
| 1821 | ); |
|---|
| 1822 | $tmpl->blog_id($blog_id); |
|---|
| 1823 | $tmpl->save |
|---|
| 1824 | or return $app->error( |
|---|
| 1825 | $app->translate("Error creating new template: ") |
|---|
| 1826 | . $tmpl->errstr ); |
|---|
| 1827 | } |
|---|
| 1828 | } |
|---|
| 1829 | } |
|---|
| 1830 | |
|---|
| 1831 | $app->add_return_arg( 'refreshed' => 1 ); |
|---|
| 1832 | $app->call_return; |
|---|
| 1833 | } |
|---|
| 1834 | |
|---|
| 1835 | sub refresh_individual_templates { |
|---|
| 1836 | my ($app) = @_; |
|---|
| 1837 | |
|---|
| 1838 | require MT::Util; |
|---|
| 1839 | |
|---|
| 1840 | my $user = $app->user; |
|---|
| 1841 | my $perms = $app->permissions; |
|---|
| 1842 | return $app->error( |
|---|
| 1843 | $app->translate( |
|---|
| 1844 | "Permission denied.") |
|---|
| 1845 | ) |
|---|
| 1846 | #TODO: system level-designer permission |
|---|
| 1847 | unless $user->is_superuser() || $user->can_edit_templates() |
|---|
| 1848 | || ( $perms |
|---|
| 1849 | && ( $perms->can_edit_templates() |
|---|
| 1850 | || $perms->can_administer_blog ) ); |
|---|
| 1851 | |
|---|
| 1852 | my $set; |
|---|
| 1853 | if ( my $blog_id = $app->param('blog_id') ) { |
|---|
| 1854 | my $blog = $app->model('blog')->load($blog_id) |
|---|
| 1855 | or return $app->error($app->translate('Can\'t load blog #[_1].', $blog_id)); |
|---|
| 1856 | $set = $blog->template_set() |
|---|
| 1857 | if $blog; |
|---|
| 1858 | } |
|---|
| 1859 | |
|---|
| 1860 | require MT::DefaultTemplates; |
|---|
| 1861 | my $tmpl_list = MT::DefaultTemplates->templates($set) or return; |
|---|
| 1862 | |
|---|
| 1863 | my $tmpl_types = {}; |
|---|
| 1864 | my $tmpl_ids = {}; |
|---|
| 1865 | my $tmpls = {}; |
|---|
| 1866 | foreach my $tmpl (@$tmpl_list) { |
|---|
| 1867 | $tmpl->{text} = $app->translate_templatized( $tmpl->{text} ); |
|---|
| 1868 | $tmpl_ids->{ $tmpl->{identifier} } = $tmpl |
|---|
| 1869 | if $tmpl->{identifier}; |
|---|
| 1870 | if ( $tmpl->{type} !~ m/^(archive|individual|page|category|index|custom|widget)$/ ) |
|---|
| 1871 | { |
|---|
| 1872 | $tmpl_types->{ $tmpl->{type} } = $tmpl; |
|---|
| 1873 | } |
|---|
| 1874 | else { |
|---|
| 1875 | $tmpls->{ $tmpl->{type} }{ $tmpl->{name} } = $tmpl; |
|---|
| 1876 | } |
|---|
| 1877 | } |
|---|
| 1878 | |
|---|
| 1879 | my $t = time; |
|---|
| 1880 | |
|---|
| 1881 | my @msg; |
|---|
| 1882 | my @id = $app->param('id'); |
|---|
| 1883 | require MT::Template; |
|---|
| 1884 | foreach my $tmpl_id (@id) { |
|---|
| 1885 | my $tmpl = MT::Template->load($tmpl_id); |
|---|
| 1886 | next unless $tmpl; |
|---|
| 1887 | my $blog_id = $tmpl->blog_id; |
|---|
| 1888 | |
|---|
| 1889 | # FIXME: permission check -- for this blog_id |
|---|
| 1890 | |
|---|
| 1891 | my @ts = MT::Util::offset_time_list( $t, $blog_id ); |
|---|
| 1892 | my $ts = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $ts[5] + 1900, |
|---|
| 1893 | $ts[4] + 1, @ts[ 3, 2, 1, 0 ]; |
|---|
| 1894 | |
|---|
| 1895 | my $val = ( $tmpl->identifier ? $tmpl_ids->{ $tmpl->identifier() } : undef ) |
|---|
| 1896 | || $tmpl_types->{ $tmpl->type() } |
|---|
| 1897 | || $tmpls->{ $tmpl->type() }{ $tmpl->name }; |
|---|
| 1898 | if ( !$val ) { |
|---|
| 1899 | push @msg, |
|---|
| 1900 | $app->translate( |
|---|
| 1901 | "Skipping template '[_1]' since it appears to be a custom template.", |
|---|
| 1902 | $tmpl->name |
|---|
| 1903 | ); |
|---|
| 1904 | next; |
|---|
| 1905 | } |
|---|
| 1906 | |
|---|
| 1907 | my $text = $tmpl->text; |
|---|
| 1908 | $text =~ s/\s+//g; |
|---|
| 1909 | |
|---|
| 1910 | my $def_text = $val->{text}; |
|---|
| 1911 | $def_text =~ s/\s+//g; |
|---|
| 1912 | |
|---|
| 1913 | if ($text ne $def_text) { |
|---|
| 1914 | # if it has been customized, back it up to a new tmpl record |
|---|
| 1915 | my $backup = $tmpl->clone; |
|---|
| 1916 | delete $backup->{column_values} |
|---|
| 1917 | ->{id}; # make sure we don't overwrite original |
|---|
| 1918 | delete $backup->{changed_cols}->{id}; |
|---|
| 1919 | $backup->name( $backup->name . ' (Backup from ' . $ts . ')' ); |
|---|
| 1920 | $backup->type('backup'); |
|---|
| 1921 | $backup->outfile(''); |
|---|
| 1922 | $backup->linked_file( $tmpl->linked_file ); |
|---|
| 1923 | $backup->rebuild_me(0); |
|---|
| 1924 | $backup->build_dynamic(0); |
|---|
| 1925 | $backup->identifier(undef); |
|---|
| 1926 | $backup->save; |
|---|
| 1927 | push @msg, |
|---|
| 1928 | $app->translate( |
|---|
| 1929 | 'Refreshing template <strong>[_3]</strong> with <a href="?__mode=view&blog_id=[_1]&_type=template&id=[_2]">backup</a>', |
|---|
| 1930 | $blog_id, $backup->id, $tmpl->name ); |
|---|
| 1931 | |
|---|
| 1932 | # we found that the previous template had not been |
|---|
| 1933 | # altered, so replace it with new default template... |
|---|
| 1934 | $tmpl->text( $val->{text} ); |
|---|
| 1935 | $tmpl->identifier( $val->{identifier} ); |
|---|
| 1936 | $tmpl->linked_file(''); |
|---|
| 1937 | $tmpl->save; |
|---|
| 1938 | } else { |
|---|
| 1939 | push @msg, $app->translate("Skipping template '[_1]' since it has not been changed.", $tmpl->name); |
|---|
| 1940 | } |
|---|
| 1941 | } |
|---|
| 1942 | my @msg_loop; |
|---|
| 1943 | push @msg_loop, { message => $_ } foreach @msg; |
|---|
| 1944 | |
|---|
| 1945 | $app->build_page( 'refresh_results.tmpl', |
|---|
| 1946 | { message_loop => \@msg_loop, return_url => $app->return_uri } ); |
|---|
| 1947 | } |
|---|
| 1948 | |
|---|
| 1949 | sub clone_templates { |
|---|
| 1950 | my ($app) = @_; |
|---|
| 1951 | |
|---|
| 1952 | my $user = $app->user; |
|---|
| 1953 | my $perms = $app->permissions; |
|---|
| 1954 | return $app->error( |
|---|
| 1955 | $app->translate( |
|---|
| 1956 | "Permission denied.") |
|---|
| 1957 | ) |
|---|
| 1958 | #TODO: system level-designer permission |
|---|
| 1959 | unless $user->is_superuser() || $user->can_edit_templates() |
|---|
| 1960 | || ( $perms |
|---|
| 1961 | && ( $perms->can_edit_templates() |
|---|
| 1962 | || $perms->can_administer_blog ) ); |
|---|
| 1963 | |
|---|
| 1964 | my @id = $app->param('id'); |
|---|
| 1965 | require MT::Template; |
|---|
| 1966 | foreach my $tmpl_id (@id) { |
|---|
| 1967 | my $tmpl = MT::Template->load($tmpl_id); |
|---|
| 1968 | next unless $tmpl; |
|---|
| 1969 | |
|---|
| 1970 | my $new_tmpl = $tmpl->clone({ |
|---|
| 1971 | Except => { |
|---|
| 1972 | id => 1, |
|---|
| 1973 | name => 1, |
|---|
| 1974 | identifier => 1, |
|---|
| 1975 | }, |
|---|
| 1976 | }); |
|---|
| 1977 | |
|---|
| 1978 | my $new_basename = $app->translate("Copy of [_1]", $tmpl->name); |
|---|
| 1979 | my $new_name = $new_basename; |
|---|
| 1980 | my $i = 0; |
|---|
| 1981 | while (MT::Template->exist({ name => $new_name, blog_id => $tmpl->blog_id })) { |
|---|
| 1982 | $new_name = $new_basename . ' (' . ++$i . ')'; |
|---|
| 1983 | } |
|---|
| 1984 | |
|---|
| 1985 | $new_tmpl->name($new_name); |
|---|
| 1986 | $new_tmpl->save; |
|---|
| 1987 | } |
|---|
| 1988 | |
|---|
| 1989 | $app->add_return_arg( 'saved_copied' => 1 ); |
|---|
| 1990 | $app->call_return; |
|---|
| 1991 | } |
|---|
| 1992 | |
|---|
| 1993 | sub publish_index_templates { |
|---|
| 1994 | my $app = shift; |
|---|
| 1995 | $app->validate_magic or return; |
|---|
| 1996 | |
|---|
| 1997 | # permission check |
|---|
| 1998 | my $perms = $app->permissions; |
|---|
| 1999 | return $app->errtrans("Permission denied.") |
|---|
| 2000 | unless $app->user->is_superuser || |
|---|
| 2001 | $perms->can_administer_blog || |
|---|
| 2002 | $perms->can_rebuild; |
|---|
| 2003 | |
|---|
| 2004 | my $blog = $app->blog; |
|---|
| 2005 | my $templates = MT->model('template')->lookup_multi([ $app->param('id') ]); |
|---|
| 2006 | TEMPLATE: for my $tmpl (@$templates) { |
|---|
| 2007 | next TEMPLATE if !defined $tmpl; |
|---|
| 2008 | next TEMPLATE if $tmpl->blog_id != $blog->id; |
|---|
| 2009 | next TEMPLATE unless $tmpl->build_type; |
|---|
| 2010 | |
|---|
| 2011 | $app->rebuild_indexes( |
|---|
| 2012 | Blog => $blog, |
|---|
| 2013 | Template => $tmpl, |
|---|
| 2014 | Force => 1, |
|---|
| 2015 | ); |
|---|
| 2016 | } |
|---|
| 2017 | |
|---|
| 2018 | $app->call_return( published => 1 ); |
|---|
| 2019 | } |
|---|
| 2020 | |
|---|
| 2021 | sub publish_archive_templates { |
|---|
| 2022 | my $app = shift; |
|---|
| 2023 | $app->validate_magic or return; |
|---|
| 2024 | |
|---|
| 2025 | # permission check |
|---|
| 2026 | my $perms = $app->permissions; |
|---|
| 2027 | return $app->errtrans("Permission denied.") |
|---|
| 2028 | unless $app->user->is_superuser |
|---|
| 2029 | || $perms->can_administer_blog |
|---|
| 2030 | || $perms->can_rebuild; |
|---|
| 2031 | |
|---|
| 2032 | my @ids = $app->param('id'); |
|---|
| 2033 | if (scalar @ids == 1) { |
|---|
| 2034 | # we also support a list of comma-delimited ids like this |
|---|
| 2035 | @ids = split /,/, $ids[0]; |
|---|
| 2036 | } |
|---|
| 2037 | return $app->error($app->translate("Invalid request.")) |
|---|
| 2038 | unless @ids; |
|---|
| 2039 | |
|---|
| 2040 | my $tmpl_id; |
|---|
| 2041 | my %ats; |
|---|
| 2042 | require MT::TemplateMap; |
|---|
| 2043 | while (!$tmpl_id && @ids) { |
|---|
| 2044 | $tmpl_id = shift @ids; |
|---|
| 2045 | my @tmpl_maps = MT::TemplateMap->load( { template_id => $tmpl_id } ); |
|---|
| 2046 | foreach my $map (@tmpl_maps) { |
|---|
| 2047 | next unless $map->build_type; |
|---|
| 2048 | $ats{ $map->archive_type } = 1; |
|---|
| 2049 | } |
|---|
| 2050 | undef $tmpl_id unless keys %ats; |
|---|
| 2051 | } |
|---|
| 2052 | |
|---|
| 2053 | # we have a template and archive types to publish! |
|---|
| 2054 | |
|---|
| 2055 | require MT::CMS::Blog; |
|---|
| 2056 | my $return_args; |
|---|
| 2057 | if (@ids) { |
|---|
| 2058 | # we have more to do after this, so save the list |
|---|
| 2059 | # of remaining archive templates... |
|---|
| 2060 | $return_args = $app->uri_params( |
|---|
| 2061 | mode => 'publish_archive_templates', |
|---|
| 2062 | args => { |
|---|
| 2063 | magic_token => $app->current_magic, |
|---|
| 2064 | blog_id => scalar $app->param('blog_id'), |
|---|
| 2065 | id => join(",", @ids), |
|---|
| 2066 | } |
|---|
| 2067 | ); |
|---|
| 2068 | } else { |
|---|
| 2069 | # nothing left after this publish operation; just return |
|---|
| 2070 | # to the edit screen. |
|---|
| 2071 | $return_args = $app->uri_params( |
|---|
| 2072 | mode => 'view', |
|---|
| 2073 | args => { |
|---|
| 2074 | _type => 'template', |
|---|
| 2075 | blog_id => scalar $app->param('blog_id'), |
|---|
| 2076 | published => 1, |
|---|
| 2077 | id => $tmpl_id, |
|---|
| 2078 | saved => 1, |
|---|
| 2079 | } |
|---|
| 2080 | ); |
|---|
| 2081 | } |
|---|
| 2082 | $return_args =~ s/^\?//; |
|---|
| 2083 | |
|---|
| 2084 | $app->return_args( $return_args ); |
|---|
| 2085 | $app->param( 'template_id', $tmpl_id ); |
|---|
| 2086 | $app->param( 'single_template', 1 ); # forces fullscreen mode |
|---|
| 2087 | $app->param( 'type', join(",", keys %ats) ); |
|---|
| 2088 | return MT::CMS::Blog::start_rebuild_pages($app); |
|---|
| 2089 | } |
|---|
| 2090 | |
|---|
| 2091 | sub save_widget { |
|---|
| 2092 | my $app = shift; |
|---|
| 2093 | my $q = $app->param; |
|---|
| 2094 | |
|---|
| 2095 | $app->validate_magic() or return; |
|---|
| 2096 | my $author = $app->user; |
|---|
| 2097 | |
|---|
| 2098 | my $id = $q->param('id'); |
|---|
| 2099 | |
|---|
| 2100 | if ( !$author->is_superuser ) { |
|---|
| 2101 | $app->run_callbacks( 'cms_save_permission_filter.template', $app, $id ) |
|---|
| 2102 | || return $app->error( |
|---|
| 2103 | $app->translate( "Permission denied: [_1]", $app->errstr() ) ); |
|---|
| 2104 | } |
|---|
| 2105 | |
|---|
| 2106 | my $filter_result = $app->run_callbacks( 'cms_save_filter.widgetset', $app ); |
|---|
| 2107 | |
|---|
| 2108 | if ( !$filter_result ) { |
|---|
| 2109 | return edit_widget( $app, { error => $app->translate( "Save failed: [_1]", $app->errstr ) } ); |
|---|
| 2110 | } |
|---|
| 2111 | |
|---|
| 2112 | my $class = $app->model('template'); |
|---|
| 2113 | my $obj; |
|---|
| 2114 | if ( $id ) { |
|---|
| 2115 | $obj = $class->load($id) |
|---|
| 2116 | or return $app->error($app->translate("Invalid ID [_1]", $id)); |
|---|
| 2117 | } |
|---|
| 2118 | else { |
|---|
| 2119 | $obj = $class->new; |
|---|
| 2120 | } |
|---|
| 2121 | |
|---|
| 2122 | my $original = $obj->clone(); |
|---|
| 2123 | $obj->name($q->param('name')); |
|---|
| 2124 | $obj->type('widgetset'); |
|---|
| 2125 | $obj->blog_id( $q->param('blog_id') || 0 ); |
|---|
| 2126 | $obj->modulesets($q->param('modules')); |
|---|
| 2127 | |
|---|
| 2128 | unless ( |
|---|
| 2129 | $app->run_callbacks( 'cms_pre_save.template', $app, $obj, $original ) ) |
|---|
| 2130 | { |
|---|
| 2131 | return edit_widget( $app, { error => $app->translate( "Save failed: [_1]", $app->errstr ) } ); |
|---|
| 2132 | } |
|---|
| 2133 | |
|---|
| 2134 | $obj->save |
|---|
| 2135 | or return $app->error( |
|---|
| 2136 | $app->translate( "Saving object failed: [_1]", $obj->errstr ) ); |
|---|
| 2137 | |
|---|
| 2138 | $app->run_callbacks( 'cms_post_save.template', $app, $obj, $original ) |
|---|
| 2139 | or return $app->error( $app->errstr() ); |
|---|
| 2140 | |
|---|
| 2141 | $app->redirect( |
|---|
| 2142 | $app->uri( |
|---|
| 2143 | 'mode' => 'edit_widget', |
|---|
| 2144 | args => |
|---|
| 2145 | { blog_id => $obj->blog_id, 'saved' => 1, rebuild => 1, id => $obj->id } |
|---|
| 2146 | ) |
|---|
| 2147 | ); |
|---|
| 2148 | } |
|---|
| 2149 | |
|---|
| 2150 | sub edit_widget { |
|---|
| 2151 | my $app = shift; |
|---|
| 2152 | my (%opt) = @_; |
|---|
| 2153 | |
|---|
| 2154 | my $q = $app->param(); |
|---|
| 2155 | my $id = scalar($q->param('id')) || $opt{id}; |
|---|
| 2156 | my $blog_id = scalar $q->param('blog_id') || 0; |
|---|
| 2157 | |
|---|
| 2158 | my $tmpl_class = $app->model('template'); |
|---|
| 2159 | require MT::Promise; |
|---|
| 2160 | my $obj_promise = MT::Promise::delay( |
|---|
| 2161 | sub { |
|---|
| 2162 | return $tmpl_class->load($id) || undef; |
|---|
| 2163 | } |
|---|
| 2164 | ); |
|---|
| 2165 | |
|---|
| 2166 | if ( !$app->user->is_superuser ) { |
|---|
| 2167 | $app->run_callbacks( 'cms_view_permission_filter.template', |
|---|
| 2168 | $app, $id, $obj_promise ) |
|---|
| 2169 | || return $app->error( |
|---|
| 2170 | $app->translate( "Permission denied: [_1]", $app->errstr() ) ); |
|---|
| 2171 | } |
|---|
| 2172 | |
|---|
| 2173 | my $param = { |
|---|
| 2174 | blog_id => $blog_id, |
|---|
| 2175 | search_type => "template", |
|---|
| 2176 | search_label => MT::Template->class_label_plural, |
|---|
| 2177 | $id ? ( id => $id ) : (), |
|---|
| 2178 | exists($opt{rebuild}) ? ( rebuild => $opt{rebuild} ) : (), |
|---|
| 2179 | exists($opt{error}) ? ( error => $opt{error} ) : (), |
|---|
| 2180 | exists($opt{saved}) ? ( saved => $opt{saved} ) : () |
|---|
| 2181 | }; |
|---|
| 2182 | if ($blog_id) { |
|---|
| 2183 | my $blog = $app->blog; |
|---|
| 2184 | # include_system/include_cache are only applicable |
|---|
| 2185 | # to blog-level templates |
|---|
| 2186 | $param->{include_system} = $blog->include_system; |
|---|
| 2187 | $param->{include_cache} = $blog->include_cache; |
|---|
| 2188 | $param->{include_with_ssi} = 0; |
|---|
| 2189 | $param->{cache_path} = ''; |
|---|
| 2190 | $param->{cache_enabled} = 0; |
|---|
| 2191 | $param->{cache_expire_type} = 0; |
|---|
| 2192 | $param->{cache_expire_period} = ''; |
|---|
| 2193 | $param->{cache_expire_interval} = 0; |
|---|
| 2194 | $param->{ssi_type} = uc $blog->include_system; |
|---|
| 2195 | } |
|---|
| 2196 | |
|---|
| 2197 | my $iter = $tmpl_class->load_iter( |
|---|
| 2198 | { type => 'widget', blog_id => $blog_id ? [ $blog_id, 0 ] : 0 }, |
|---|
| 2199 | { sort => 'name', direction => 'ascend' } |
|---|
| 2200 | ); |
|---|
| 2201 | |
|---|
| 2202 | my %all_widgets; |
|---|
| 2203 | while (my $m = $iter->()) { |
|---|
| 2204 | next unless $m; |
|---|
| 2205 | $all_widgets{ $m->id }{name} = $m->name; |
|---|
| 2206 | $all_widgets{ $m->id }{blog_id} = $m->blog_id; |
|---|
| 2207 | } |
|---|
| 2208 | |
|---|
| 2209 | my @inst_modules; |
|---|
| 2210 | my $wtmpl; |
|---|
| 2211 | if ( $id ) { |
|---|
| 2212 | $wtmpl = $obj_promise->force() |
|---|
| 2213 | or return $app->error( |
|---|
| 2214 | $app->translate( |
|---|
| 2215 | "Load failed: [_1]", |
|---|
| 2216 | $tmpl_class->errstr || $app->translate("(no reason given)") |
|---|
| 2217 | ) |
|---|
| 2218 | ); |
|---|
| 2219 | $param->{name} = $wtmpl->name; |
|---|
| 2220 | $param->{include_with_ssi} = $wtmpl->include_with_ssi |
|---|
| 2221 | if defined $wtmpl->include_with_ssi; |
|---|
| 2222 | $param->{cache_path} = $wtmpl->cache_path |
|---|
| 2223 | if defined $wtmpl->cache_path; |
|---|
| 2224 | $param->{cache_expire_type} = $wtmpl->cache_expire_type |
|---|
| 2225 | if defined $wtmpl->cache_expire_type; |
|---|
| 2226 | my ( $period, $interval ) = |
|---|
| 2227 | _get_schedule( $wtmpl->cache_expire_interval ); |
|---|
| 2228 | $param->{cache_expire_period} = $period if defined $period; |
|---|
| 2229 | $param->{cache_expire_interval} = $interval if defined $interval; |
|---|
| 2230 | my @events = split ',', $wtmpl->cache_expire_event; |
|---|
| 2231 | foreach my $name (@events) { |
|---|
| 2232 | $param->{ 'cache_expire_event_' . $name } = 1; |
|---|
| 2233 | } |
|---|
| 2234 | my $modulesets = $wtmpl->modulesets; |
|---|
| 2235 | if ( $modulesets ) { |
|---|
| 2236 | my @modules = split ',', $modulesets; |
|---|
| 2237 | foreach my $mid ( @modules ) { |
|---|
| 2238 | push @inst_modules, { |
|---|
| 2239 | id => $mid, |
|---|
| 2240 | name => $all_widgets{$mid}{name}, |
|---|
| 2241 | blog_id => $all_widgets{$mid}{blog_id}, |
|---|
| 2242 | }; |
|---|
| 2243 | delete $all_widgets{$mid}; |
|---|
| 2244 | } |
|---|
| 2245 | } |
|---|
| 2246 | } |
|---|
| 2247 | $param->{installed} = \@inst_modules if @inst_modules; |
|---|
| 2248 | my @avail_modules = map { { |
|---|
| 2249 | id => $_, name => $all_widgets{$_}{name}, blog_id => $all_widgets{$_}{blog_id} |
|---|
| 2250 | } } keys %all_widgets; |
|---|
| 2251 | $param->{available} = \@avail_modules; |
|---|
| 2252 | |
|---|
| 2253 | my $res = $app->run_callbacks('cms_edit.widgetset', $app, $id, $wtmpl, $param); |
|---|
| 2254 | if (!$res) { |
|---|
| 2255 | return $app->error($app->callback_errstr()); |
|---|
| 2256 | } |
|---|
| 2257 | |
|---|
| 2258 | $app->load_tmpl('edit_widget.tmpl', $param); |
|---|
| 2259 | } |
|---|
| 2260 | |
|---|
| 2261 | sub list_widget { |
|---|
| 2262 | my $app = shift; |
|---|
| 2263 | my (%opt) = @_; |
|---|
| 2264 | my $q = $app->param; |
|---|
| 2265 | |
|---|
| 2266 | my $perms = $app->blog ? $app->permissions : $app->user->permissions; |
|---|
| 2267 | return $app->return_to_dashboard( redirect => 1 ) |
|---|
| 2268 | unless $perms || $app->user->is_superuser; |
|---|
| 2269 | if ( $perms && !$perms->can_edit_templates ) { |
|---|
| 2270 | return $app->return_to_dashboard( permission => 1 ); |
|---|
| 2271 | } |
|---|
| 2272 | my $blog_id = $q->param('blog_id') || 0; |
|---|
| 2273 | |
|---|
| 2274 | my $widget_loop = &build_template_table( $app, |
|---|
| 2275 | load_args => [ |
|---|
| 2276 | { type => 'widget', blog_id => $blog_id ? [ $blog_id, 0 ] : 0 }, |
|---|
| 2277 | { sort => 'name', direction => 'ascend' } |
|---|
| 2278 | ], |
|---|
| 2279 | ); |
|---|
| 2280 | |
|---|
| 2281 | my $iter = $app->model('template')->load_iter( |
|---|
| 2282 | { type => 'widgetset', blog_id => $blog_id ? $blog_id : 0 }, |
|---|
| 2283 | { sort => 'name', direction => 'ascend' } |
|---|
| 2284 | ); |
|---|
| 2285 | my @widgetmanagers; |
|---|
| 2286 | while ( my $widgetset = $iter->() ) { |
|---|
| 2287 | next unless $widgetset; |
|---|
| 2288 | my $ws = { |
|---|
| 2289 | id => $widgetset->id, |
|---|
| 2290 | widgetmanager => $widgetset->name, |
|---|
| 2291 | }; |
|---|
| 2292 | if ( my $modulesets = $widgetset->modulesets ) { |
|---|
| 2293 | $ws->{widgets} = $modulesets; |
|---|
| 2294 | my @names; |
|---|
| 2295 | foreach my $module ( split ',', $modulesets ) { |
|---|
| 2296 | my ( $widget ) = grep { $_->{id} eq $module } @$widget_loop; |
|---|
| 2297 | push @names, $widget->{name} if $widget; |
|---|
| 2298 | } |
|---|
| 2299 | $ws->{names} = join(', ', @names) if @names; |
|---|
| 2300 | } |
|---|
| 2301 | push @widgetmanagers, $ws; |
|---|
| 2302 | } |
|---|
| 2303 | |
|---|
| 2304 | my @widget_loop; |
|---|
| 2305 | if ( $blog_id ) { |
|---|
| 2306 | # Remove system level widgets from the listing |
|---|
| 2307 | @widget_loop = grep { $_->{blog_id} == $blog_id } @$widget_loop; |
|---|
| 2308 | } |
|---|
| 2309 | else { |
|---|
| 2310 | @widget_loop = @$widget_loop; |
|---|
| 2311 | } |
|---|
| 2312 | |
|---|
| 2313 | my $param = { |
|---|
| 2314 | @widgetmanagers ? ( object_loop => \@widgetmanagers ) : (), |
|---|
| 2315 | @widget_loop ? ( widget_table => \@widget_loop ) : (), |
|---|
| 2316 | object_type => "template", |
|---|
| 2317 | search_type => "template", |
|---|
| 2318 | search_label => MT::Template->class_label_plural, |
|---|
| 2319 | listing_screen => 1, |
|---|
| 2320 | screen_id => "list-widget-set", |
|---|
| 2321 | $blog_id ? ( blog_view => 1, blog_id => $blog_id ) : (), |
|---|
| 2322 | exists($opt{rebuild}) ? ( rebuild => $opt{rebuild} ) : (), |
|---|
| 2323 | exists($opt{error}) ? ( error => $opt{error} ) : (), |
|---|
| 2324 | exists($opt{deleted}) ? ( saved => $opt{deleted} ) : () |
|---|
| 2325 | }; |
|---|
| 2326 | |
|---|
| 2327 | $app->load_tmpl('list_widget.tmpl', $param); |
|---|
| 2328 | } |
|---|
| 2329 | |
|---|
| 2330 | sub delete_widget { |
|---|
| 2331 | my $app = shift; |
|---|
| 2332 | my $q = $app->param; |
|---|
| 2333 | my $type = $q->param('_type'); |
|---|
| 2334 | |
|---|
| 2335 | return $app->errtrans("Invalid request.") |
|---|
| 2336 | unless $type; |
|---|
| 2337 | |
|---|
| 2338 | return $app->error( $app->translate("Invalid request.") ) |
|---|
| 2339 | if $app->request_method() ne 'POST'; |
|---|
| 2340 | |
|---|
| 2341 | $app->validate_magic() or return; |
|---|
| 2342 | |
|---|
| 2343 | my $tmpl_class = $app->model('template'); |
|---|
| 2344 | |
|---|
| 2345 | for my $id ( $q->param('id') ) { |
|---|
| 2346 | next unless $id; # avoid 'empty' ids |
|---|
| 2347 | |
|---|
| 2348 | my $obj = $tmpl_class->load($id); |
|---|
| 2349 | next unless $obj; |
|---|
| 2350 | $app->run_callbacks( 'cms_delete_permission_filter.template', |
|---|
| 2351 | $app, $obj ) |
|---|
| 2352 | || return $app->error( |
|---|
| 2353 | $app->translate( "Permission denied: [_1]", $app->errstr() ) ); |
|---|
| 2354 | |
|---|
| 2355 | $obj->remove |
|---|
| 2356 | or return $app->errtrans( |
|---|
| 2357 | 'Removing [_1] failed: [_2]', |
|---|
| 2358 | $app->translate('template'), |
|---|
| 2359 | $obj->errstr |
|---|
| 2360 | ); |
|---|
| 2361 | $app->run_callbacks( 'cms_post_delete.template', $app, $obj ); |
|---|
| 2362 | } |
|---|
| 2363 | $app->call_return; |
|---|
| 2364 | } |
|---|
| 2365 | |
|---|
| 2366 | sub restore_widgetmanagers { |
|---|
| 2367 | my ($cb, $objects, $deferred, $errors, $callback) = @_; |
|---|
| 2368 | my @keys = grep { $_ =~ /^MT::Template#/ } keys( %$objects ); |
|---|
| 2369 | foreach my $key ( @keys ) { |
|---|
| 2370 | my $tmpl = $objects->{$key}; |
|---|
| 2371 | next unless 'widgetset' eq $tmpl->type; |
|---|
| 2372 | my $modulesets = $tmpl->modulesets; |
|---|
| 2373 | next unless $modulesets; |
|---|
| 2374 | $callback->( MT->translate( 'Restoring widget set [_1]... ', $tmpl->name ) ); |
|---|
| 2375 | |
|---|
| 2376 | my @tmpl_ids = split ',', $modulesets; |
|---|
| 2377 | my @new_ids; |
|---|
| 2378 | foreach my $id ( @tmpl_ids ) { |
|---|
| 2379 | my $new_tmpl = $objects->{"MT::Template#$id"}; |
|---|
| 2380 | next unless $new_tmpl; |
|---|
| 2381 | push @new_ids, $new_tmpl->id; |
|---|
| 2382 | } |
|---|
| 2383 | if ( @new_ids ) { |
|---|
| 2384 | $tmpl->modulesets( join(',', @new_ids) ); |
|---|
| 2385 | $tmpl->save; |
|---|
| 2386 | $callback->( MT->translate("Done.") . "\n" ); |
|---|
| 2387 | } |
|---|
| 2388 | else { |
|---|
| 2389 | $callback->( MT->translate("Failed.") |
|---|