2
2
# This program is distributed under the terms of the
3
3
# GNU General Public License, version 2.
5
# $Id: Template.pm 1191 2008-01-10 23:34:17Z mpaschal $
5
# $Id: Template.pm 2396 2008-05-20 00:16:44Z bchoate $
7
7
package MT::Template;
10
10
use base qw( MT::Object );
12
use constant NODE => 'MT::Template::Node';
14
use constant NODE_TEXT => 1;
15
use constant NODE_BLOCK => 2;
16
use constant NODE_FUNCTION => 3;
11
use MT::Util qw( weaken );
13
sub NODE () { 'MT::Template::Node' }
15
sub NODE_TEXT () { 1 }
16
sub NODE_BLOCK () { 2 }
17
sub NODE_FUNCTION () { 3 }
31
32
'rebuild_me' => 'boolean',
32
33
'build_dynamic' => 'boolean',
33
34
'identifier' => 'string(50)',
35
'build_type' => 'smallint',
36
'build_interval' => 'integer',
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',
45
57
'build_dynamic' => 0,
48
61
child_of => 'MT::Blog',
51
64
datasource => 'template',
52
65
primary_key => 'id',
54
__PACKAGE__->install_meta({
55
columns => ['last_rebuild_time', 'page_layout'],
57
67
__PACKAGE__->add_trigger('pre_remove' => \&pre_remove_children);
126
137
$file = $test_file, last if -f $test_file;
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;
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);
210
221
my($ctx, $cond) = @_;
211
222
$ctx ||= $tmpl->context;
224
my $timer = MT->get_timer();
225
local $timer->{elapsed} = 0 if $timer;
213
227
local $ctx->{__stash}{template} = $tmpl;
214
228
my $tokens = $tmpl->tokens
216
my $build = MT::Builder->new;
230
my $build = $ctx->{__stash}{builder} || MT::Builder->new;
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);
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;
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')) {
236
251
'layout-wt' => 2,
243
258
$ctx->var( 'page_columns', $columns ) if $columns;
245
defined(my $res = $build->build($ctx, $tokens, $cond)) or
260
$ctx->var( $tmpl->identifier, 1 ) if defined $tmpl->identifier;
262
$timer->pause_partial if $timer;
264
my $res = $build->build($ctx, $tokens, $cond);
267
$timer->mark("MT::Template::build[" . ($tmpl->name || $tmpl->{__file} || "?").']');
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));
249
275
$res =~ s/^\s*//;
257
283
return $tmpl->build();
286
sub widgets_to_modulesets {
288
my ( $widgets, $blog_id ) = @_;
289
return unless $widgets && @$widgets;
291
my @wtmpls = $pkg->load(
292
{ name => $widgets, blog_id => $blog_id ? [ $blog_id, 0 ] : 0, type => 'widget' }
293
) if $widgets && @$widgets;
295
foreach my $name ( @$widgets ) {
296
my ( $widget ) = grep { $_->name eq $name } @wtmpls;
298
push @wids, $widget->id;
300
return join ',', @wids;
306
my $ms = $obj->modulesets;
309
if ( $ms && $ms =~ /;/ ) {
310
my @mods = split /;/, $ms;
312
# tmpl_id = column index . order in column ;
313
my ($id, $col) = /(\d+)=(\d+)\.(\d+)/;
314
push @inst, $id if $col && ( $col == 1 );
316
$obj->modulesets( join ',', @inst );
319
@inst = split /,/, $obj->modulesets;
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' ] }
328
my $string_tmpl = '<mt:include widget="%s">';
330
foreach my $wid (@inst) {
331
my ( $tmpl ) = grep { $_->id eq $wid } @widgets;
333
$text .= sprintf( $string_tmpl, $tmpl->name );
335
$obj->text($text) if $text;
336
return $obj->SUPER::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.'));
347
if ( 'widgetset' eq $tmpl->type ) {
348
return $tmpl->save_widgetset();
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;
267
364
if ($tmpl->linked_file) {
268
365
$tmpl->_sync_to_disk($tmpl->SUPER::text) or return;
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);
279
} elsif (($dcty eq 'archives') && ('archive' eq $tmpl->type)) {
280
$tmpl->build_dynamic(1);
283
369
$tmpl->SUPER::save;
374
return $tmpl->SUPER::build_dynamic($_[0]) if @_;
375
require MT::PublishOption;
376
return 1 if $tmpl->build_type == MT::PublishOption::DYNAMIC();
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);
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);
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)
368
463
$lfile = File::Spec->catfile($blog->site_path, $lfile);
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)
406
502
$lfile = File::Spec->catfile($blog->site_path, $lfile);
408
504
$lfile = File::Spec->catfile(MT->instance->server_path, $lfile);
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;
604
702
sub createTextNode {
605
703
my $tmpl = shift;
607
return bless [ 'TEXT', $text, undef, undef, undef, undef, $tmpl ], NODE;
705
my $node = bless [ 'TEXT', $text, undef, undef, undef, undef, $tmpl ], NODE;
610
710
sub insertAfter {
683
783
package MT::Template::Tokens;
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 }
690
790
sub getElementsByTagName {
691
791
my ($tokens, $name) = @_;