root/branches/release-30/lib/MT/CMS/Template.pm @ 1369

Revision 1369, 35.5 kB (checked in by bchoate, 22 months ago)

Broke CMS into smaller parts to reduce memory footprint and group code into logical parts. BugId:58666

  • Property svn:keywords set to Id Revision
Line 
1package MT::CMS::Template;
2
3use strict;
4
5sub edit {
6    my $cb = shift;
7    my ($app, $id, $obj, $param) = @_;
8
9    my $q = $app->param;
10    my $blog_id = $q->param('blog_id');
11    my $type = $q->param('_type');
12    my $blog = $app->blog;
13    my $cfg = $app->config;
14    my $perms = $app->permissions;
15
16    if ($id) {
17        # FIXME: Template types should not be enumerated here
18        $param->{nav_templates} = 1;
19        my $tab;
20        if ( $obj->type eq 'index' ) {
21            $tab = 'index';
22            $param->{template_group_trans} = $app->translate('index');
23        }
24        elsif ($obj->type eq 'archive'
25            || $obj->type eq 'individual'
26            || $obj->type eq 'category'
27            || $obj->type eq 'page' )
28        {
29
30            # FIXME: enumeration of types
31            $tab = 'archive';
32            $param->{template_group_trans} = $app->translate('archive');
33        }
34        elsif ( $obj->type eq 'custom' ) {
35            $tab = 'module';
36            $param->{template_group_trans} = $app->translate('module');
37        }
38        elsif ( $obj->type eq 'widget' ) {
39            $tab = 'widget';
40            $param->{template_group_trans} = $app->translate('widget');
41        }
42        elsif ( $obj->type eq 'email' ) {
43            $tab = 'email';
44            $param->{template_group_trans} = $app->translate('email');
45        }
46        else {
47            $tab = 'system';
48            $param->{template_group_trans} = $app->translate('system');
49        }
50        $param->{template_group} = $tab;
51        $blog_id = $obj->blog_id;
52
53        # FIXME: enumeration of types
54             $param->{has_name} = $obj->type eq 'index'
55          || $obj->type eq 'custom'
56          || $obj->type eq 'widget'
57          || $obj->type eq 'archive'
58          || $obj->type eq 'category'
59          || $obj->type eq 'page'
60          || $obj->type eq 'individual';
61        if ( !$param->{has_name} ) {
62            $param->{ 'type_' . $obj->type } = 1;
63            $param->{name} = $obj->name;
64        }
65        $app->add_breadcrumb( $param->{name} );
66        $param->{has_outfile} = $obj->type eq 'index';
67        $param->{has_rebuild} =
68          (      ( $obj->type eq 'index' )
69              && ( ( $blog->custom_dynamic_templates || "" ) ne 'all' ) );
70        $param->{custom_dynamic} =
71          $blog && ( $blog->custom_dynamic_templates || "" ) eq 'custom';
72        $param->{has_build_options} =
73          ( $param->{custom_dynamic} || $param->{has_rebuild} );
74
75        # FIXME: enumeration of types
76             $param->{is_special} = $param->{type} ne 'index'
77          && $param->{type} ne 'archive'
78          && $param->{type} ne 'category'
79          && $param->{type} ne 'page'
80          && $param->{type} ne 'individual';
81             $param->{has_build_options} = $param->{has_build_options}
82          && $param->{type} ne 'custom'
83          && $param->{type} ne 'widget'
84          && !$param->{is_special};
85        $param->{rebuild_me} =
86          defined $obj->rebuild_me ? $obj->rebuild_me : 1;
87        $param->{search_label} = $app->translate('Templates');
88        $param->{object_type}  = 'template';
89        my $published_url = $obj->published_url;
90        $param->{published_url} = $published_url if $published_url;
91        $param->{saved_rebuild} = 1 if $q->param('saved_rebuild');
92
93        $app->load_list_actions( 'template', $param );
94
95        $obj->compile;
96        if ( $obj->{errors} && @{ $obj->{errors} } ) {
97            $param->{error} = $app->translate(
98                "One or more errors were found in this template.");
99            $param->{error} .= "<ul>\n";
100            foreach my $err ( @{ $obj->{errors} } ) {
101                $param->{error} .= "<li>"
102                  . MT::Util::encode_html( $err->{message} )
103                  . "</li>\n";
104            }
105            $param->{error} .= "</ul>\n";
106        }
107
108        # Populate list of included templates
109        if ( my $includes = $obj->getElementsByTagName('Include') ) {
110            my @includes;
111            my @widgets;
112            my %seen;
113            foreach my $tag (@$includes) {
114                my $include = {};
115                my $mod = $include->{include_module} = $tag->[1]->{module} || $tag->[1]->{widget};
116                next unless $mod;
117                my $type = $tag->[1]->{widget} ? 'widget' : 'custom';
118                next if exists $seen{$type}{$mod};
119                $seen{$type}{$mod} = 1;
120                my $other = MT::Template->load(
121                    {
122                        blog_id => [ $obj->blog_id, 0 ],
123                        name    => $mod,
124                        type    => $type,
125                    }, {
126                        sort      => 'blog_id',
127                        direction => 'descend',
128                    }
129                );
130                if ($other) {
131                    $include->{include_link} = $app->mt_uri(
132                        mode => 'view',
133                        args => {
134                            blog_id => $other->blog_id || 0,
135                            '_type' => 'template',
136                            id      => $other->id
137                        }
138                    );
139                }
140                else {
141                    $include->{create_link} = $app->mt_uri(
142                        mode => 'view',
143                        args => {
144                            blog_id => $obj->blog_id,
145                            '_type' => 'template',
146                            type    => $type,
147                            name    => $mod,
148                        }
149                    );
150                }
151                if ($type eq 'widget') {
152                    push @widgets, $include;
153                } else {
154                    push @includes, $include;
155                }
156            }
157            $param->{include_loop} = \@includes if @includes;
158            $param->{widget_loop} = \@widgets if @widgets;
159        }
160        my @sets = ( @{ $obj->getElementsByTagName('WidgetSet') || [] }, @{ $obj->getElementsByTagName('WidgetManager') || [] } );
161        if ( @sets ) {
162            my @widget_sets;
163            my %seen;
164            foreach my $set (@sets) {
165                my $name = $set->[1]->{name};
166                next unless $name;
167                next if $seen{$name};
168                $seen{$name} = 1;
169                push @widget_sets, {
170                    include_link => $app->mt_uri(
171                        mode => 'edit_widget',
172                        args => {
173                            blog_id => $obj->blog_id,
174                            widgetmanager => $name,
175                        },
176                    ),
177                    include_module => $name,
178                };
179            }
180            $param->{widget_set_loop} = \@widget_sets if @widget_sets;
181        }
182        $param->{have_includes} = 1 if $param->{widget_set_loop} || $param->{include_loop} || $param->{widget_loop};
183        # Populate archive types for creating new map
184        my $obj_type = $obj->type;
185        if (   $obj_type eq 'individual'
186            || $obj_type eq 'page'
187            || $obj_type eq 'author'
188            || $obj_type eq 'category'
189            || $obj_type eq 'archive' )
190        {
191            my @at = $app->publisher->archive_types;
192            my @archive_types;
193            for my $at (@at) {
194                my $archiver      = $app->publisher->archiver($at);
195                my $archive_label = $archiver->archive_label;
196                $archive_label = $at unless $archive_label;
197                $archive_label = $archive_label->()
198                  if ( ref $archive_label ) eq 'CODE';
199                if (   ( $obj_type eq 'archive' )
200                    || ( $obj_type eq 'author' )
201                    || ( $obj_type eq 'category' ) )
202                {
203
204                    # only include if it is NOT an entry-based archive type
205                    next if $archiver->entry_based;
206                }
207                elsif ( $obj_type eq 'page' ) {
208                    # only include if it is a entry-based archive type and page
209                    next unless $archiver->entry_based;
210                    next if $archiver->entry_class ne 'page';
211                }
212                elsif ( $obj_type eq 'individual' ) {
213                    # only include if it is a entry-based archive type and entry
214                    next unless $archiver->entry_based;
215                    next if $archiver->entry_class eq 'page';
216                }
217                push @archive_types,
218                  {
219                    archive_type_translated => $archive_label,
220                    archive_type            => $at,
221                  };
222                @archive_types =
223                  sort { archive_type_sorter( $a, $b ) } @archive_types;
224            }
225            $param->{archive_types} = \@archive_types;
226
227            # Populate template maps for this template
228            require MT::CMS::Blog;
229            my $maps = MT::CMS::Blog::_populate_archive_loop( $app, $blog, $obj );
230            $param->{object_loop} = $param->{template_map_loop} = $maps
231              if @$maps;
232        }
233    } else {
234        my $new_tmpl = $q->param('create_new_template');
235        my $template_type;
236        if ($new_tmpl) {
237            if ( $new_tmpl =~ m/^blank:(.+)/ ) {
238                $template_type = $1;
239                $param->{type} = $1;
240            }
241            elsif ( $new_tmpl =~ m/^default:([^:]+):(.+)/ ) {
242                $template_type = $1;
243                $template_type = 'custom' if $template_type eq 'module';
244                my $template_id = $2;
245                my $set = $blog ? $blog->template_set : undef;
246                require MT::DefaultTemplates;
247                my $def_tmpl = MT::DefaultTemplates->templates($set) || [];
248                my ($tmpl) =
249                  grep { $_->{identifier} eq $template_id } @$def_tmpl;
250                $param->{text} = $app->translate_templatized( $tmpl->{text} )
251                  if $tmpl;
252                $param->{type} = $template_type;
253            }
254        }
255        else {
256            $template_type = $q->param('type');
257            $template_type = 'custom' if 'module' eq $template_type;
258            $param->{type}   = $template_type;
259        }
260        return $app->errtrans("Create template requires type")
261          unless $template_type;
262        $param->{nav_templates} = 1;
263        my $tab;
264
265        # FIXME: enumeration of types
266        if ( $template_type eq 'index' ) {
267            $tab = 'index';
268            $param->{template_group_trans} = $app->translate('index');
269        }
270        elsif ($template_type eq 'archive'
271            || $template_type eq 'individual'
272            || $template_type eq 'category'
273            || $template_type eq 'page' )
274        {
275            $tab                         = 'archive';
276            $param->{template_group_trans} = $app->translate('archive');
277            $param->{type_archive}         = 1;
278            my @types = (
279                {
280                    key   => 'archive',
281                    label => $app->translate('Archive')
282                },
283                {
284                    key   => 'individual',
285                    label => $app->translate('Entry or Page')
286                },
287            );
288            $param->{new_archive_types} = \@types;
289        }
290        elsif ( $template_type eq 'custom' ) {
291            $tab = 'module';
292            $param->{template_group_trans} = $app->translate('module');
293        }
294        elsif ( $template_type eq 'widget' ) {
295            $tab = 'widget';
296            $param->{template_group_trans} = $app->translate('widget');
297        }
298        else {
299            $tab = 'system';
300            $param->{template_group_trans} = $app->translate('system');
301        }
302        $param->{template_group} = $tab;
303        $app->translate($tab);
304        $app->add_breadcrumb( $app->translate('New Template') );
305
306        # FIXME: enumeration of types
307             $param->{has_name} = $template_type eq 'index'
308          || $template_type eq 'custom'
309          || $template_type eq 'widget'
310          || $template_type eq 'archive'
311          || $template_type eq 'category'
312          || $template_type eq 'page'
313          || $template_type eq 'individual';
314        $param->{has_outfile} = $template_type eq 'index';
315        $param->{has_rebuild} =
316          (      ( $template_type eq 'index' )
317              && ( ( $blog->custom_dynamic_templates || "" ) ne 'all' ) );
318        $param->{custom_dynamic} =
319          $blog && $blog->custom_dynamic_templates eq 'custom';
320        $param->{has_build_options} =
321             $blog && ($blog->custom_dynamic_templates eq 'custom'
322          || $param->{has_rebuild});
323
324        # FIXME: enumeration of types
325             $param->{is_special} = $param->{type} ne 'index'
326          && $param->{type} ne 'archive'
327          && $param->{type} ne 'category'
328          && $param->{type} ne 'page'
329          && $param->{type} ne 'individual';
330             $param->{has_build_options} = $param->{has_build_options}
331          && $param->{type} ne 'custom'
332          && $param->{type} ne 'widget'
333          && !$param->{is_special};
334
335        $param->{rebuild_me} = 1;
336        $param->{name}       = MT::Util::decode_url( $app->param('name') )
337          if $app->param('name');
338    }
339    my $set = $blog ? $blog->template_set : undef;
340    require MT::DefaultTemplates;
341    my $tmpls = MT::DefaultTemplates->templates($set);
342    my @tmpl_ids;
343    foreach my $dtmpl (@$tmpls) {
344        if ( !$param->{has_name} ) {
345            if ($obj->type eq 'email') {
346                if ($dtmpl->{identifier} eq $obj->identifier) {
347                    $param->{template_name_label} = $dtmpl->{label};
348                    $param->{template_name}       = $dtmpl->{name};
349                }
350            }
351            else {
352                if ( $dtmpl->{type} eq $obj->type ) {
353                    $param->{template_name_label} = $dtmpl->{label};
354                    $param->{template_name}       = $dtmpl->{name};
355                }
356            }
357        }
358        if ( $dtmpl->{type} eq 'index' ) {
359            push @tmpl_ids,
360              {
361                label    => $dtmpl->{label},
362                key      => $dtmpl->{key},
363                selected => $dtmpl->{key} eq
364                  ( ( $obj ? $obj->identifier : undef ) || '' ),
365              };
366        }
367    }
368    $param->{index_identifiers} = \@tmpl_ids;
369
370    $param->{"type_$param->{type}"} = 1;
371    if ($perms) {
372        my $pref_param =
373          $app->load_template_prefs( $perms->template_prefs );
374        %$param = ( %$param, %$pref_param );
375    }
376
377    # Populate structure for template snippets
378    if ( my $snippets = $app->registry('template_snippets') || {} ) {
379        my @snippets;
380        for my $snip_id ( keys %$snippets ) {
381            my $label = $snippets->{$snip_id}{label};
382            $label = $label->() if ref($label) eq 'CODE';
383            push @snippets,
384              {
385                id      => $snip_id,
386                trigger => $snippets->{$snip_id}{trigger},
387                label   => $label,
388                content => $snippets->{$snip_id}{content},
389              };
390        }
391        @snippets = sort { $a->{label} cmp $b->{label} } @snippets;
392        $param->{template_snippets} = \@snippets;
393    }
394
395    # Populate structure for tag documentation
396    my $all_tags = MT::Component->registry("tags");
397    my $tag_docs = {};
398    foreach my $tag_set (@$all_tags) {
399        my $url = $tag_set->{help_url};
400        $url = $url->() if ref($url) eq 'CODE';
401        # hey, at least give them a google search
402        $url ||= 'http://www.google.com/search?q=mt%t';
403        my $tag_list = '';
404        foreach my $type (qw( block function )) {
405            my $tags = $tag_set->{$type} or next;
406            $tag_list .= ($tag_list eq '' ? '' : ',') . join(",", keys(%$tags));
407        }
408        $tag_list =~ s/(^|,)plugin(,|$)/,/;
409        if (exists $tag_docs->{$url}) {
410            $tag_docs->{$url} .= ',' . $tag_list;
411        }
412        else {
413            $tag_docs->{$url} = $tag_list;
414        }
415    }
416    $param->{tag_docs} = $tag_docs;
417    $param->{link_doc} = $app->help_url('appendices/tags/');
418
419    # template language
420    $param->{template_lang} = 'html';
421    if ( $obj && $obj->outfile ) {
422        if ( $obj->outfile =~ m/\.(css|js|html|php|pl|asp)$/ ) {
423            $param->{template_lang} = {
424                css => 'css',
425                js => 'javascript',
426                html => 'html',
427                php => 'php',
428                pl => 'perl',
429                asp => 'asp',
430            }->{$1};
431        }
432    }
433
434    1;
435}
436
437sub list {
438    my $app = shift;
439
440    my $perms = $app->blog ? $app->permissions : $app->user->permissions;
441    return $app->return_to_dashboard( redirect => 1 )
442      unless $perms || $app->user->is_superuser;
443    if ( $perms && !$perms->can_edit_templates ) {
444        return $app->return_to_dashboard( permission => 1 );
445    }
446
447    require MT::Template;
448    my $blog_id = $app->param('blog_id') || 0;
449    my $filter  = $app->param('filter_key');
450    if ( !$filter ) {
451        if ($app->blog) {
452            $filter = 'index_templates';
453            $app->param( 'filter_key', 'index_templates' );
454        }
455        else {
456            $filter = 'module_templates';
457            $app->param( 'filter_key', 'module_templates' );
458        }
459    }
460    else {
461        # global index templates redirect to module templates
462        if ( !$app->blog && $filter eq 'index_templates' ) {
463            $filter = 'module_templates';
464            $app->param( 'filter_key', 'module_templates' );
465        }
466    }
467    my $terms = { blog_id => $blog_id };
468    my $args  = { sort    => 'name' };
469
470    my $hasher = sub {
471        my ( $obj, $row ) = @_;
472        my $template_type;
473        my $type = $row->{type} || '';
474        if ( $type =~ m/^(individual|page|category|archive)$/ ) {
475            $template_type = 'archive';
476        }
477        elsif ( $type eq 'widget' ) {
478            $template_type = 'widget';
479        }
480        elsif ( $type eq 'index' ) {
481            $template_type = 'index';
482        }
483        elsif ( $type eq 'custom' ) {
484            $template_type = 'module';
485        }
486        elsif ( $type eq 'email' ) {
487            $template_type = 'email';
488        }
489        elsif ( $type eq 'backup' ) {
490            $template_type = 'backup';
491        }
492        else {
493            $template_type = 'system';
494        }
495        $row->{template_type} = $template_type;
496        $row->{type} = 'entry' if $type eq 'individual';
497        my $published_url = $obj->published_url;
498        $row->{published_url} = $published_url if $published_url;
499    };
500
501    my $params        = {};
502    my $template_type = $filter;
503    $template_type =~ s/_templates//;
504    my $template_type_label = $app->translate($template_type);
505    if ( $template_type_label eq $template_type ) {
506        $template_type_label = "\u$template_type";
507    }
508    $params->{template_type}       = $template_type;
509    $params->{template_type_label} = $template_type_label;
510
511    #@tt_loop = sort { $a->{label} cmp $b->{label} } @tt_loop;
512    #$params->{template_type_loop} = \@tt_loop;
513
514    $app->load_list_actions( 'template', $params );
515    $params->{page_actions} = $app->page_actions('list_templates');
516    $params->{search_label} = $app->translate("Templates");
517    $params->{blog_view} = 1;
518    $params->{refreshed} = $app->param('refreshed');
519    $params->{published} = $app->param('published');
520
521    return $app->listing(
522        {
523            type     => 'template',
524            terms    => $terms,
525            args     => $args,
526            params   => $params,
527            no_limit => 1,
528            code     => $hasher,
529        }
530    );
531}
532
533sub reset_blog_templates {
534    my $app   = shift;
535    my $q     = $app->param;
536    my $perms = $app->permissions
537      or return $app->error( $app->translate("No permissions") );
538    return $app->error( $app->translate("Permission denied.") )
539      unless $perms->can_edit_templates;
540    $app->validate_magic() or return;
541    my $blog = MT::Blog->load( $perms->blog_id );
542    require MT::Template;
543    my @tmpl = MT::Template->load( { blog_id => $blog->id } );
544
545    for my $tmpl (@tmpl) {
546        $tmpl->remove or return $app->error( $tmpl->errstr );
547    }
548    my $set = $blog ? $blog->template_set : undef;
549    require MT::DefaultTemplates;
550    my $tmpl_list = MT::DefaultTemplates->templates($set) || [];
551    my @arch_tmpl;
552    for my $val (@$tmpl_list) {
553        $val->{name} = $app->translate( $val->{name} );
554        $val->{text} = $app->translate_templatized( $val->{text} );
555        my $tmpl = MT::Template->new;
556        $tmpl->set_values($val);
557        $tmpl->build_dynamic(0);
558        $tmpl->blog_id( $blog->id );
559        $tmpl->save
560          or return $app->error(
561            $app->translate(
562                "Populating blog with default templates failed: [_1]",
563                $tmpl->errstr
564            )
565          );
566
567        # FIXME: enumeration of types
568        if (   $val->{type} eq 'archive'
569            || $val->{type} eq 'category'
570            || $val->{type} eq 'page'
571            || $val->{type} eq 'individual' )
572        {
573            push @arch_tmpl, $tmpl;
574        }
575    }
576
577    ## Set up mappings from new templates to archive types.
578    for my $tmpl (@arch_tmpl) {
579        my (@at);
580
581        # FIXME: enumeration of types
582        if ( $tmpl->type eq 'archive' ) {
583            @at = qw( Daily Weekly Monthly Category );
584        }
585        elsif ( $tmpl->type eq 'page' ) {
586            @at = qw( Page );
587        }
588        elsif ( $tmpl->type eq 'individual' ) {
589            @at = qw( Individual );
590        }
591        require MT::TemplateMap;
592        for my $at (@at) {
593            my $map = MT::TemplateMap->new;
594            $map->archive_type($at);
595            $map->is_preferred(1);
596            $map->template_id( $tmpl->id );
597            $map->blog_id( $tmpl->blog_id );
598            $map->save
599              or return $app->error(
600                $app->translate(
601                    "Setting up mappings failed: [_1]",
602                    $map->errstr
603                )
604              );
605        }
606    }
607    $app->redirect(
608        $app->uri(
609            'mode' => 'list',
610            args =>
611              { '_type' => 'template', blog_id => $blog->id, 'reset' => 1 }
612        )
613    );
614}
615
616sub delete_map {
617    my $app = shift;
618    $app->validate_magic() or return;
619    my $perms = $app->{perms}
620      or return $app->error( $app->translate("No permissions") );
621    my $q  = $app->param;
622    my $id = $q->param('id');
623
624    require MT::TemplateMap;
625    MT::TemplateMap->remove( { id => $id } );
626    my $html =
627      $app->_generate_map_table( $q->param('blog_id'),
628        $q->param('template_id') );
629    $app->{no_print_body} = 1;
630    $app->send_http_header("text/plain");
631    $app->print($html);
632}
633
634sub add_map {
635    my $app = shift;
636    $app->validate_magic() or return;
637    my $perms = $app->{perms}
638      or return $app->error( $app->translate("No permissions") );
639
640    my $q = $app->param;
641
642    require MT::TemplateMap;
643    my $blog_id = $q->param('blog_id');
644    my $at      = $q->param('new_archive_type');
645    my $count   = MT::TemplateMap->count(
646        {
647            blog_id      => $blog_id,
648            archive_type => $at
649        }
650    );
651    my $map = MT::TemplateMap->new;
652    $map->is_preferred( $count ? 0 : 1 );
653    $map->template_id( scalar $q->param('template_id') );
654    $map->blog_id($blog_id);
655    $map->archive_type($at);
656    $map->save
657      or return $app->error(
658        $app->translate( "Saving map failed: [_1]", $map->errstr ) );
659    my $html =
660      $app->_generate_map_table( $blog_id, scalar $q->param('template_id') );
661    $app->rebuild(
662        BlogID      => $blog_id,
663        ArchiveType => $at,
664        TemplateMap => $map,
665        TemplateID  => scalar $q->param('template_id'),
666        NoStatic    => 1
667    ) or return $app->publish_error();
668    $app->{no_print_body} = 1;
669    $app->send_http_header("text/plain");
670    $app->print($html);
671}
672
673sub delete_map {
674    my $app = shift;
675    $app->validate_magic() or return;
676    my $perms = $app->{perms}
677      or return $app->error( $app->translate("No permissions") );
678    my $q  = $app->param;
679    my $id = $q->param('id');
680
681    require MT::TemplateMap;
682    MT::TemplateMap->remove( { id => $id } );
683    my $html =
684      $app->_generate_map_table( $q->param('blog_id'),
685        $q->param('template_id') );
686    $app->{no_print_body} = 1;
687    $app->send_http_header("text/plain");
688    $app->print($html);
689}
690
691sub add_map {
692    my $app = shift;
693    $app->validate_magic() or return;
694    my $perms = $app->{perms}
695      or return $app->error( $app->translate("No permissions") );
696
697    my $q = $app->param;
698
699    require MT::TemplateMap;
700    my $blog_id = $q->param('blog_id');
701    my $at      = $q->param('new_archive_type');
702    my $count   = MT::TemplateMap->count(
703        {
704            blog_id      => $blog_id,
705            archive_type => $at
706        }
707    );
708    my $map = MT::TemplateMap->new;
709    $map->is_preferred( $count ? 0 : 1 );
710    $map->template_id( scalar $q->param('template_id') );
711    $map->blog_id($blog_id);
712    $map->archive_type($at);
713    $map->save
714      or return $app->error(
715        $app->translate( "Saving map failed: [_1]", $map->errstr ) );
716    my $html =
717      $app->_generate_map_table( $blog_id, scalar $q->param('template_id') );
718    $app->rebuild(
719        BlogID      => $blog_id,
720        ArchiveType => $at,
721        TemplateMap => $map,
722        TemplateID  => scalar $q->param('template_id'),
723        NoStatic    => 1
724    ) or return $app->publish_error();
725    $app->{no_print_body} = 1;
726    $app->send_http_header("text/plain");
727    $app->print($html);
728}
729
730sub can_view {
731    my ( $eh, $app, $id ) = @_;
732    my $perms = $app->permissions;
733    return !$id || ($perms && $perms->can_edit_templates) || (!$app->blog && $app->user->can_edit_templates);
734}
735
736sub can_save {
737    my ( $eh, $app, $id ) = @_;
738    my $perms = $app->permissions;
739    return ($perms && $perms->can_edit_templates) || (!$perms && $app->user->can_edit_templates);
740}
741
742sub can_delete {
743    my ( $eh, $app, $obj ) = @_;
744    return 1 if $app->user->is_superuser();
745    my $perms = $app->permissions;
746    return ($perms && $perms->can_edit_templates) || (!$perms && $app->user->can_edit_templates);
747}
748
749sub pre_save {
750    my $eh = shift;
751    my ( $app, $obj ) = @_;
752
753    $obj->rebuild_me(0) 
754      if $app->param('current_rebuild_me')
755      && !$app->param('rebuild_me');
756    $obj->build_dynamic(0)
757      if $app->param('current_build_dynamic')
758      && !$app->param('build_dynamic');
759
760    ## Strip linefeed characters.
761    ( my $text = $obj->text ) =~ tr/\r//d;
762
763    if ($text =~ m/<(MT|_)_trans/i) {
764        $text = $app->translate_templatized($text);
765    }
766
767    $obj->text($text);
768
769    # update text heights if necessary
770    if ( my $perms = $app->permissions ) {
771        my $prefs = $perms->template_prefs || '';
772        my $text_height = $app->param('text_height');
773        if ( defined $text_height ) {
774            my ($pref_text_height) = $prefs =~ m/\btext:(\d+)\b/;
775            $pref_text_height ||= 0;
776            if ( $text_height != $pref_text_height ) {
777                if ( $prefs =~ m/\btext\b/ ) {
778                    $prefs =~ s/\btext(:\d+)\b/text:$text_height/;
779                }
780                else {
781                    $prefs = 'text:' . $text_height . ',' . $prefs;
782                }
783            }
784        }
785
786        if ( $prefs ne ( $perms->template_prefs || '' ) ) {
787            $perms->template_prefs($prefs);
788            $perms->save;
789        }
790    }
791    1;
792}
793
794sub post_save {
795    my $eh = shift;
796    my ( $app, $obj, $original ) = @_;
797
798    my $sess_obj = $app->autosave_session_obj;
799    $sess_obj->remove if $sess_obj;
800
801    require MT::TemplateMap;
802    my $q = $app->param;
803    my @p = $q->param;
804    for my $p (@p) {
805        if ( $p =~ /^archive_tmpl_preferred_(\w+)_(\d+)$/ ) {
806            my $at     = $1;
807            my $map_id = $2;
808            my $map    = MT::TemplateMap->load($map_id);
809            $map->prefer( $q->param($p) );    # prefer method saves in itself
810        }
811        elsif ( $p =~ /^archive_file_tmpl_(\d+)$/ ) {
812            my $map_id = $1;
813            my $map    = MT::TemplateMap->load($map_id);
814            $map->file_template( $q->param($p) );
815            $map->save;
816        }
817    }
818
819    if ( !$original->id ) {
820        $app->log(
821            {
822                message => $app->translate(
823                    "Template '[_1]' (ID:[_2]) created by '[_3]'",
824                    $obj->name, $obj->id, $app->user->name
825                ),
826                level    => MT::Log::INFO(),
827                class    => 'template',
828                category => 'new',
829            }
830        );
831    }
832
833    if ( $obj->build_dynamic ) {
834        if ( $obj->type eq 'index' ) {
835            $app->rebuild_indexes(
836                BlogID   => $obj->blog_id,
837                Template => $obj,
838                NoStatic => 1,
839            ) or return $app->publish_error();    # XXXX
840        }
841        else {
842            $app->rebuild(
843                BlogID     => $obj->blog_id,
844                TemplateID => $obj->id,
845                NoStatic   => 1,
846            ) or return $app->publish_error();
847        }
848    }
849    1;
850}
851
852sub post_delete {
853    my ( $eh, $app, $obj ) = @_;
854
855    $app->log(
856        {
857            message => $app->translate(
858                "Template '[_1]' (ID:[_2]) deleted by '[_3]'",
859                $obj->name, $obj->id, $app->user->name
860            ),
861            level    => MT::Log::INFO(),
862            class    => 'system',
863            category => 'delete'
864        }
865    );
866}
867
868sub build_template_table {
869    my $app = shift;
870    my (%args) = @_;
871
872    my $perms     = $app->permissions;
873    my $list_pref = $app->list_pref('template');
874    my $limit     = $args{limit};
875    my $param     = $args{param} || {};
876    my $iter;
877    if ( $args{load_args} ) {
878        my $class = $app->model('template');
879        $iter = $class->load_iter( @{ $args{load_args} } );
880    }
881    elsif ( $args{iter} ) {
882        $iter = $args{iter};
883    }
884    elsif ( $args{items} ) {
885        $iter = sub { pop @{ $args{items} } };
886        $limit = scalar @{ $args{items} };
887    }
888    return [] unless $iter;
889
890    my @data;
891    my $i;
892    my %blogs;
893    while ( my $tmpl = $iter->() ) {
894        my $blog = $blogs{ $tmpl->blog_id } ||=
895          MT::Blog->load( $tmpl->blog_id );
896        my $row = $tmpl->column_values;
897        $row->{name} = '' if !defined $row->{name};
898        $row->{name} =~ s/^\s+|\s+$//g;
899        $row->{name} = "(" . $app->translate("No Name") . ")"
900          if $row->{name} eq '';
901        my $published_url = $tmpl->published_url;
902        $row->{published_url} = $published_url if $published_url;
903
904        # FIXME: enumeration of types
905        $row->{can_delete} = 1
906          if $tmpl->type =~ m/(custom|index|archive|page|individual|category)/;
907        if ($blog) {
908            $row->{weblog_name} = $blog->name;
909        }
910        elsif ($tmpl->blog_id) {
911            $row->{weblog_name} = '* ' . $app->translate('Orphaned') . ' *';
912        }
913        else {
914            $row->{weblog_name} = '* ' . $app->translate('Global Templates') . ' *';
915        }
916        $row->{object} = $tmpl;
917        push @data, $row;
918        last if @data > $limit;
919    }
920    return [] unless @data;
921
922    $param->{template_table}[0]              = {%$list_pref};
923    $param->{template_table}[0]{object_loop} = \@data;
924    $param->{template_table}[0]{object_type} = 'template';
925    $app->load_list_actions( 'template', $param );
926    $param->{object_loop} = \@data;
927    \@data;
928}
929
930sub refresh_individual_templates {
931    my ($app) = @_;
932
933    require MT::Util;
934
935    my $user = $app->user;
936    my $perms = $app->permissions;
937    return $app->error(
938        $app->translate(
939            "Permission denied.")
940      )
941      #TODO: system level-designer permission
942      unless $user->is_superuser() || $user->can_edit_templates()
943      || ( $perms
944        && ( $perms->can_edit_templates()
945          || $perms->can_administer_blog ) );
946
947    my $set;
948    if ( my $blog_id = $app->param('blog_id') ) {
949        my $blog = $app->model('blog')->load($blog_id);
950        $set = $blog->template_set()
951            if $blog;
952    }
953
954    require MT::DefaultTemplates;
955    my $tmpl_list = MT::DefaultTemplates->templates($set) or return;
956
957    my $trnames    = {};
958    my $tmpl_types = {};
959    my $tmpl_ids   = {};
960    my $tmpls      = {};
961    foreach my $tmpl (@$tmpl_list) {
962        $tmpl->{text} = $app->translate_templatized( $tmpl->{text} );
963        $tmpl_ids->{ $tmpl->{identifier} } = $tmpl
964            if $tmpl->{identifier};
965        $trnames->{ $app->translate( $tmpl->{name} ) } = $tmpl->{name};
966        if ( $tmpl->{type} !~ m/^(archive|individual|page|category|index|custom|widget)$/ )
967        {
968            $tmpl_types->{ $tmpl->{type} } = $tmpl;
969        }
970        else {
971            $tmpls->{ $tmpl->{type} }{ $tmpl->{name} } = $tmpl;
972        }
973    }
974
975    my $t = time;
976
977    my @msg;
978    my @id = $app->param('id');
979    require MT::Template;
980    foreach my $tmpl_id (@id) {
981        my $tmpl = MT::Template->load($tmpl_id);
982        next unless $tmpl;
983        my $blog_id = $tmpl->blog_id;
984
985        # FIXME: permission check -- for this blog_id
986
987        my @ts = MT::Util::offset_time_list( $t, $blog_id );
988        my $ts = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $ts[5] + 1900,
989          $ts[4] + 1, @ts[ 3, 2, 1, 0 ];
990
991        my $orig_name = $trnames->{ $tmpl->name } || $tmpl->name;
992        my $val = ( $tmpl->identifier ? $tmpl_ids->{ $tmpl->identifier() } : undef )
993          || $tmpl_types->{ $tmpl->type() }
994          || $tmpls->{ $tmpl->type() }{$orig_name};
995        if ( !$val ) {
996            push @msg,
997              $app->translate(
998"Skipping template '[_1]' since it appears to be a custom template.",
999                $tmpl->name
1000              );
1001            next;
1002        }
1003
1004        my $text = $tmpl->text;
1005        $text =~ s/\s+//g;
1006
1007        my $def_text = $val->{text};
1008        $def_text =~ s/\s+//g;
1009
1010        if ($text ne $def_text) {
1011            # if it has been customized, back it up to a new tmpl record
1012            my $backup = $tmpl->clone;
1013            delete $backup->{column_values}
1014              ->{id};    # make sure we don't overwrite original
1015            delete $backup->{changed_cols}->{id};
1016            $backup->name( $backup->name . ' (Backup from ' . $ts . ')' );
1017            $backup->type('backup');
1018            $backup->outfile('');
1019            $backup->linked_file( $tmpl->linked_file );
1020            $backup->rebuild_me(0);
1021            $backup->build_dynamic(0);
1022            $backup->identifier(undef);
1023            $backup->save;
1024            push @msg,
1025              $app->translate(
1026    'Refreshing template <strong>[_3]</strong> with <a href="?__mode=view&amp;blog_id=[_1]&amp;_type=template&amp;id=[_2]">backup</a>',
1027                  $blog_id, $backup->id, $tmpl->name );
1028
1029            # we found that the previous template had not been
1030            # altered, so replace it with new default template...
1031            $tmpl->text( $val->{text} );
1032            $tmpl->identifier( $val->{identifier} );
1033            $tmpl->linked_file('');
1034            $tmpl->save;
1035        } else {
1036            push @msg, $app->translate("Skipping template '[_1]' since it has not been changed.", $tmpl->name);
1037        }
1038    }
1039    my @msg_loop;
1040    push @msg_loop, { message => $_ } foreach @msg;
1041
1042    $app->build_page( 'refresh_results.tmpl',
1043        { message_loop => \@msg_loop, return_url => $app->return_uri } );
1044}
1045
1046sub publish_index_templates {
1047    my $app = shift;
1048    $app->validate_magic or return;
1049
1050    # permission check
1051    my $perms = $app->permissions;
1052    return $app->errtrans("Permission denied.")
1053        unless $app->user->is_superuser ||
1054            $perms->can_administer_blog ||
1055            $perms->can_rebuild;
1056
1057    my $blog = $app->blog;
1058    my $templates = MT->model('template')->lookup_multi([ $app->param('id') ]);
1059    TEMPLATE: for my $tmpl (@$templates) {
1060        next TEMPLATE if !defined $tmpl;
1061        next TEMPLATE if $tmpl->blog_id != $blog->id;
1062        $app->rebuild_indexes(
1063            Blog     => $blog,
1064            Template => $tmpl,
1065        );
1066    }
1067
1068    $app->call_return( published => 1 );
1069}
1070
10711;
Note: See TracBrowser for help on using the browser.