~ubuntu-branches/debian/squeeze/movabletype-opensource/squeeze

« back to all changes in this revision

Viewing changes to lib/MT/Template.pm

  • Committer: Bazaar Package Importer
  • Author(s): Dominic Hargreaves
  • Date: 2008-06-13 23:28:40 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080613232840-ya4jfxv1jgl45a3d
Tags: 4.2~rc2-1
* New upstream release candidate
* Update Standards-Version (no changes)
* Ensure that schema upgrade message is always seen

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
# This program is distributed under the terms of the
3
3
# GNU General Public License, version 2.
4
4
#
5
 
# $Id: Template.pm 1191 2008-01-10 23:34:17Z mpaschal $
 
5
# $Id: Template.pm 2396 2008-05-20 00:16:44Z bchoate $
6
6
 
7
7
package MT::Template;
8
8
 
9
9
use strict;
10
10
use base qw( MT::Object );
11
 
 
12
 
use constant NODE => 'MT::Template::Node';
13
 
 
14
 
use constant NODE_TEXT => 1;
15
 
use constant NODE_BLOCK => 2;
16
 
use constant NODE_FUNCTION => 3;
 
11
use MT::Util qw( weaken );
 
12
 
 
13
sub NODE () { 'MT::Template::Node' }
 
14
 
 
15
sub NODE_TEXT ()     { 1 }
 
16
sub NODE_BLOCK ()    { 2 }
 
17
sub NODE_FUNCTION () { 3 }
17
18
 
18
19
my $resync_to_db;
19
20
 
31
32
        'rebuild_me' => 'boolean',
32
33
        'build_dynamic' => 'boolean',
33
34
        'identifier' => 'string(50)',
 
35
        'build_type' => 'smallint',
 
36
        'build_interval' => 'integer',
 
37
 
 
38
        # meta properties
 
39
        'last_rebuild_time' => 'integer meta',
 
40
        'page_layout' => 'string meta',
 
41
        'include_with_ssi' => 'integer meta',
 
42
        'cache_expire_type' => 'integer meta',
 
43
        'cache_expire_interval' => 'integer meta',
 
44
        'cache_expire_event' => 'string meta',
 
45
        'cache_path' => 'string meta',
 
46
        'modulesets' => 'string meta',
34
47
    },
35
48
    indexes => {
36
49
        blog_id => 1,
37
50
        name => 1,
38
51
        type => 1,
39
 
        build_dynamic => 1,
40
52
        outfile => 1,
41
53
        identifier => 1,
42
54
    },
43
55
    defaults => {
44
56
        'rebuild_me' => 1,
45
57
        'build_dynamic' => 0,
 
58
        'build_type' => 1,
46
59
    },
47
60
    meta => 1,
48
61
    child_of => 'MT::Blog',
51
64
    datasource => 'template',
52
65
    primary_key => 'id',
53
66
});
54
 
__PACKAGE__->install_meta({
55
 
    columns => ['last_rebuild_time', 'page_layout'],
56
 
});
57
67
__PACKAGE__->add_trigger('pre_remove' => \&pre_remove_children);
58
68
 
59
69
use MT::Builder;
90
100
    my $tmpl = $pkg->new;
91
101
    $tmpl->{include_path} = $param{path};
92
102
    $tmpl->{include_filter} = $param{filter};
 
103
    $tmpl->{__file} = $file;
93
104
    my $contents = $tmpl->load_file($file);
94
105
    if (defined $contents) {
95
106
        if ($tmpl->{include_filter}) {
126
137
            $file = $test_file, last if -f $test_file;
127
138
        }
128
139
    }
129
 
    return $tmpl->trans_error(Carp::longmess("File not found: [_1]"), $file) unless -e $file;
 
140
    return $tmpl->trans_error("File not found: [_1]", $file) unless -e $file;
130
141
    local *FH;
131
142
    open FH, $file
132
143
        or return $tmpl->trans_error("Error reading file '[_1]': [_2]", $file, $!);
141
152
    return $tmpl->{context} = shift if @_;
142
153
    require MT::Template::Context;
143
154
    my $ctx = $tmpl->{context} ||= MT::Template::Context->new;
144
 
    $ctx->stash('template', $tmpl);
 
155
    weaken($ctx->{__stash}{'template'} = $tmpl);
145
156
    return $ctx;
146
157
}
147
158
 
210
221
    my($ctx, $cond) = @_;
211
222
    $ctx ||= $tmpl->context;
212
223
 
 
224
    my $timer = MT->get_timer();
 
225
    local $timer->{elapsed} = 0 if $timer;
 
226
 
213
227
    local $ctx->{__stash}{template} = $tmpl;
214
228
    my $tokens = $tmpl->tokens
215
229
        or return;
216
 
    my $build = MT::Builder->new;
 
230
    my $build = $ctx->{__stash}{builder} || MT::Builder->new;
 
231
    my $page_layout;
217
232
    if (my $blog_id = $tmpl->blog_id) {
218
233
        $ctx->stash('blog_id', $blog_id);
219
234
        my $blog = $ctx->stash('blog');
226
241
            $ctx->stash('blog_id', $blog->id);
227
242
        }
228
243
        MT->config->TimeOffset($blog->server_offset);
229
 
        $ctx->var( 'page_layout', $blog->page_layout )
230
 
            if $blog->page_layout;
 
244
        $page_layout = $blog->page_layout;
231
245
    }
232
 
    $ctx->var( 'page_layout', $tmpl->page_layout )
233
 
        if $tmpl->page_layout;
 
246
    $page_layout = $tmpl->page_layout if $tmpl->page_layout;
 
247
    $ctx->var( 'page_layout', $page_layout )
 
248
        unless $ctx->var('page_layout');
234
249
    if (my $layout = $ctx->var('page_layout')) {
235
250
        my $columns = {
236
251
            'layout-wt'  => 2,
242
257
        }->{$layout};
243
258
        $ctx->var( 'page_columns', $columns ) if $columns;
244
259
    }
245
 
    defined(my $res = $build->build($ctx, $tokens, $cond)) or
 
260
    $ctx->var( $tmpl->identifier, 1 ) if defined $tmpl->identifier;
 
261
 
 
262
    $timer->pause_partial if $timer;
 
263
 
 
264
    my $res = $build->build($ctx, $tokens, $cond);
 
265
 
 
266
    if ($timer) {
 
267
        $timer->mark("MT::Template::build[" . ($tmpl->name || $tmpl->{__file} || "?").']');
 
268
    }
 
269
 
 
270
    unless (defined($res)) {
246
271
        return $tmpl->error(MT->translate(
247
272
            "Publish error in template '[_1]': [_2]",
248
273
            $tmpl->name || $tmpl->{__file}, $build->errstr));
 
274
    }
249
275
    $res =~ s/^\s*//;
250
276
    return $res;
251
277
}
257
283
    return $tmpl->build();
258
284
}
259
285
 
 
286
sub widgets_to_modulesets {
 
287
    my $pkg = shift;
 
288
    my ( $widgets, $blog_id ) = @_;
 
289
    return unless $widgets && @$widgets;
 
290
 
 
291
    my @wtmpls = $pkg->load(
 
292
        { name => $widgets, blog_id => $blog_id ? [ $blog_id, 0 ] : 0, type => 'widget' }
 
293
    ) if $widgets && @$widgets;
 
294
    my @wids;
 
295
    foreach my $name ( @$widgets ) {
 
296
        my ( $widget ) = grep { $_->name eq $name } @wtmpls;
 
297
        next unless $widget;
 
298
        push @wids, $widget->id;
 
299
    }
 
300
    return join ',', @wids;
 
301
}
 
302
 
 
303
sub save_widgetset {
 
304
    my $obj = shift;
 
305
 
 
306
    my $ms = $obj->modulesets;
 
307
    # build module list
 
308
    my @inst;
 
309
    if ( $ms && $ms =~ /;/ ) {
 
310
        my @mods = split /;/, $ms;
 
311
        for (@mods) {
 
312
            # tmpl_id = column index . order in column ;
 
313
            my ($id, $col) = /(\d+)=(\d+)\.(\d+)/;
 
314
            push @inst, $id if $col && ( $col == 1 );
 
315
        }
 
316
        $obj->modulesets( join ',', @inst );
 
317
    }
 
318
    else {
 
319
        @inst = split /,/, $obj->modulesets;
 
320
    }
 
321
 
 
322
    my @widgets = MT::Template->load(
 
323
        { id => \@inst, type => 'widget',
 
324
          blog_id => $obj->blog_id ? [ 0, $obj->blog_id ] : '0' },
 
325
        { fetchonly => [ 'id', 'name' ] }
 
326
    ) if @inst;
 
327
 
 
328
    my $string_tmpl = '<mt:include widget="%s">';
 
329
    my $text = q();
 
330
    foreach my $wid (@inst) {
 
331
        my ( $tmpl ) = grep { $_->id eq $wid } @widgets;
 
332
        next unless $tmpl;
 
333
        $text .= sprintf( $string_tmpl, $tmpl->name );
 
334
    }
 
335
    $obj->text($text) if $text;
 
336
    return $obj->SUPER::save;
 
337
}
 
338
 
260
339
sub save {
261
340
    my $tmpl = shift;
262
341
    my $existing = MT::Template->load({ name => $tmpl->name, blog_id => $tmpl->blog_id });
264
343
        && ($existing->type eq $tmpl->type)) {
265
344
        return $tmpl->error(MT->translate('Template with the same name already exists in this blog.'));
266
345
    }
 
346
 
 
347
    if ( 'widgetset' eq $tmpl->type ) {
 
348
        return $tmpl->save_widgetset();
 
349
    }
 
350
 
 
351
    if ($tmpl->id && ($tmpl->is_changed('build_type'))) {
 
352
        # check for templatemaps, and update them appropriately
 
353
        require MT::TemplateMap;
 
354
        require MT::PublishOption;
 
355
        my @maps = MT::TemplateMap->load({ template_id => $tmpl->id });
 
356
        foreach my $map (@maps) {
 
357
            if ( ($map->build_type || 0) != ($tmpl->build_type || 0) ) {
 
358
                $map->build_type($tmpl->build_type);
 
359
                $map->save or die $map->errstr;
 
360
            }
 
361
        }
 
362
    }
 
363
 
267
364
    if ($tmpl->linked_file) {
268
365
        $tmpl->_sync_to_disk($tmpl->SUPER::text) or return;
269
366
    }
270
367
    $tmpl->{needs_db_sync} = 0;
271
 
    if ((!$tmpl->id) && (my $blog = $tmpl->blog)) {
272
 
        my $dcty = $blog->custom_dynamic_templates;
273
 
        if ($dcty eq 'all') {
274
 
            if (('index' eq $tmpl->type) || ('archive' eq $tmpl->type) ||
275
 
                ('individual' eq $tmpl->type) || ('page' eq $tmpl->type) ||
276
 
                    ('category' eq $tmpl->type)) {
277
 
                $tmpl->build_dynamic(1);
278
 
            }
279
 
        } elsif (($dcty eq 'archives') && ('archive' eq $tmpl->type)) {
280
 
            $tmpl->build_dynamic(1);
281
 
        }
282
 
    }
 
368
 
283
369
    $tmpl->SUPER::save;
284
370
}
285
371
 
 
372
sub build_dynamic {
 
373
    my $tmpl = shift;
 
374
    return $tmpl->SUPER::build_dynamic($_[0]) if @_;
 
375
    require MT::PublishOption;
 
376
    return 1 if $tmpl->build_type == MT::PublishOption::DYNAMIC();
 
377
}
 
378
 
286
379
sub blog {
287
380
    my $this = shift;
 
381
    return undef unless $this->blog_id;
288
382
    return $this->{__blog} if $this->{__blog};
289
383
    return $this->{__blog} = MT::Blog->load($this->blog_id);
290
384
}
337
431
                ## template, so saving would try to write-lock it).
338
432
                if (!defined $resync_to_db) {
339
433
                    $resync_to_db = {};
340
 
                    MT->add_callback('TakeDown', 9, undef, \&_resync_to_db);
 
434
                    MT->add_callback('takedown', 9, undef, \&_resync_to_db);
341
435
                }
342
436
                $resync_to_db->{$tmpl->id} = $tmpl;
343
437
                $tmpl->{needs_db_sync} = 1;
364
458
    my $lfile = $tmpl->linked_file;
365
459
    unless (File::Spec->file_name_is_absolute($lfile)) {
366
460
        if ($tmpl->blog_id) {
367
 
            my $blog = MT::Blog->load($tmpl->blog_id);
 
461
            my $blog = MT::Blog->load($tmpl->blog_id)
 
462
                or return;
368
463
            $lfile = File::Spec->catfile($blog->site_path, $lfile);
369
464
        }
370
465
        else {
402
497
    }
403
498
    unless (File::Spec->file_name_is_absolute($lfile)) {
404
499
        if ($tmpl->blog_id) {
405
 
            my $blog = MT::Blog->load($tmpl->blog_id);
 
500
            my $blog = MT::Blog->load($tmpl->blog_id)
 
501
                or return;
406
502
            $lfile = File::Spec->catfile($blog->site_path, $lfile);
407
503
        } else {
408
504
            $lfile = File::Spec->catfile(MT->instance->server_path, $lfile);
533
629
 
534
630
    return undef unless $tmpl->outfile;
535
631
    return undef unless ($tmpl->type eq 'index');
536
 
    
 
632
 
537
633
    my $blog = $tmpl->blog;
538
634
    return undef unless $blog;
539
635
    my $site_url = $blog->site_url || '';
598
694
sub createElement {
599
695
    my $tmpl = shift;
600
696
    my ($tag, $attr) = @_;
601
 
    return bless [ $tag, $attr, undef, undef, undef, undef, $tmpl ], NODE;
 
697
    my $node = bless [ $tag, $attr, undef, undef, undef, undef, $tmpl ], NODE;
 
698
    weaken($node->[6]);
 
699
    return $node;
602
700
}
603
701
 
604
702
sub createTextNode {
605
703
    my $tmpl = shift;
606
704
    my ($text) = @_;
607
 
    return bless [ 'TEXT', $text, undef, undef, undef, undef, $tmpl ], NODE;
 
705
    my $node = bless [ 'TEXT', $text, undef, undef, undef, undef, $tmpl ], NODE;
 
706
    weaken($node->[6]);
 
707
    return $node;
608
708
}
609
709
 
610
710
sub insertAfter {
683
783
package MT::Template::Tokens;
684
784
 
685
785
use strict;
686
 
use constant NODE_TEXT => 1;
687
 
use constant NODE_BLOCK => 2;
688
 
use constant NODE_FUNCTION => 3;
 
786
sub NODE_TEXT ()     { 1 }
 
787
sub NODE_BLOCK ()    { 2 }
 
788
sub NODE_FUNCTION () { 3 }
689
789
 
690
790
sub getElementsByTagName {
691
791
    my ($tokens, $name) = @_;
722
822
package MT::Template::Node;
723
823
 
724
824
use strict;
 
825
use MT::Util qw( weaken );
725
826
 
726
827
sub setAttribute {
727
828
    my $node = shift;
804
905
 
805
906
sub parentNode {
806
907
    my $node = shift;
807
 
    $node->[5] = shift if @_;
 
908
    weaken($node->[5] = shift) if @_;
808
909
    $node->[5];
809
910
}
810
911