root/trunk/lib/MT/TemplateMap.pm @ 3082

Revision 3082, 9.6 kB (checked in by bchoate, 14 months ago)

Merging fireball branch changes to-date to trunk: svn merge -r2974:3081 http://code.sixapart.com/svn/movabletype/branches/fireball .

  • Property svn:keywords set to Author Date Id Revision
Line 
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
7package MT::TemplateMap;
8
9use strict;
10use base qw( MT::Object );
11
12__PACKAGE__->install_properties({
13    column_defs => {
14        'id' => 'integer not null auto_increment',
15        'blog_id' => 'integer not null',
16        'template_id' => 'integer not null',
17        'archive_type' => 'string(25) not null',
18        'file_template' => 'string(255)',
19        'is_preferred' => 'boolean',
20        'build_type' => 'smallint',
21        'build_interval' => 'integer',
22    },
23    indexes => {
24        blog_id => 1,
25        template_id => 1,
26        archive_type => 1,
27        is_preferred => 1,
28    },
29    defaults => {
30        'build_type' => 1,
31    },
32    child_classes => ['MT::FileInfo'],
33    datasource => 'templatemap',
34    primary_key => 'id',
35    cacheable => 0,
36});
37
38sub class_label {
39    return MT->translate("Archive Mapping");
40}
41
42sub class_label_plural {
43    return MT->translate("Archive Mappings");
44}
45
46sub save {
47    my $map = shift;
48    my $res = $map->SUPER::save();
49    return $res unless $res;
50
51    my $at   = $map->archive_type;
52    my $blog = MT->model('blog')->load($map->blog_id)
53        or return;
54    my $blog_at   = $blog->archive_type;
55    my @ats = map { $_ } 
56        grep { $map->archive_type ne $_ }
57            split /,/, $blog_at
58                if $blog_at ne 'None';
59    push @ats, $map->archive_type;
60    my $new_at = join ',', @ats;
61    if ($new_at ne $blog_at) {
62        $blog->archive_type($new_at);
63        $blog->save;
64    }
65    return 1;
66}
67
68sub remove {
69    my $map = shift;
70    $map->remove_children({ key => 'templatemap_id' });
71    my $result = $map->SUPER::remove(@_);
72
73    if (ref $map) {
74        my $remaining = MT::TemplateMap->load(
75          {
76            blog_id => $map->blog_id,
77            archive_type => $map->archive_type,
78            id => [ $map->id ],
79          },
80          {
81            limit => 1,
82            not => { id => 1 }
83          }
84        );
85        if ($remaining) {
86            $remaining->is_preferred(1);
87            $remaining->save;
88        }
89        else {
90            my $blog = MT->model('blog')->load($map->blog_id)
91                or return;
92            my $at   = $blog->archive_type;
93            if ( $at && $at ne 'None' ) {
94                my @newat = map { $_ } grep { $map->archive_type ne $_ } split /,/, $at;
95                $blog->archive_type(join ',', @newat);
96                $blog->save;
97            }
98        }
99    }
100    else {
101        my $blog_id;
102        if ( $_[0] && $_[0]->{template_id} ) {
103            my $tmpl = MT::Template->load( $_[0]->{template_id} );
104            if ( $tmpl ) {
105                return $result unless $tmpl->blog_id; # global template does not have maps
106                $blog_id = $tmpl->blog_id;
107            }
108        }
109        elsif ( $_[0] && $_[0]->{blog_id} ) {
110            # for cases where we remove with a blog_id parameter
111            $blog_id = $_[0]->{blog_id};
112        }
113
114        my $maps_iter = MT::TemplateMap->count_group_by(
115            { ( defined $blog_id ? ( blog_id => $blog_id ) : () ) },
116            { group => [ 'blog_id', 'archive_type' ] }
117        );
118        my %ats;
119        while ( my ( $count, $blog_id, $at ) = $maps_iter->() ) {
120            my $ats = $ats{$blog_id};
121            push @$ats, $at if $count > 0;
122            $ats{$blog_id} = $ats;
123        }
124        my $iter;
125        if ( $blog_id ) {
126            my $blog = MT::Blog->load( $blog_id );
127            $iter = sub { my $ret = $blog; $blog = undef; $ret; }
128        } else {
129            $iter = MT::Blog->load_iter();
130        }
131        while ( my $blog = $iter->() ) {
132            $blog->archive_type( $ats{ $blog->id } ? join ',', @{ $ats{ $blog->id } } : '' );
133            $blog->save;
134            for my $at ( @{ $ats{ $blog->id } } ) {
135                unless ( __PACKAGE__->exist({
136                    blog_id => $blog->id, archive_type => $at, is_preferred => 1 
137                }) ) {
138                    my $remaining = __PACKAGE__->load(
139                      {
140                        blog_id => $blog->id,
141                        archive_type => $at,
142                      },
143                      {
144                        limit => 1,
145                      }
146                    );
147                    if ($remaining) {
148                        $remaining->is_preferred(1);
149                        $remaining->save;
150                    }
151                }
152            }
153        }
154    }
155    $result;
156}
157
158sub prefer {
159    my $map = shift;
160    my ($prefer) = @_;
161    $prefer = (defined($prefer) && $prefer) ? 1 : 0;
162
163    if ($prefer) {
164        return 1 if $map->is_preferred;
165        my $preferred = MT::TemplateMap->load({
166                blog_id => $map->blog_id,
167                archive_type => $map->archive_type,
168                is_preferred => 1,
169            }) or return;
170        $preferred->is_preferred(0);
171        $preferred->save or return $map->error($preferred->errstr);
172        $map->is_preferred(1);
173        $map->save or return $map->error($map->errstr);
174    } else {
175        return 1 unless $map->is_preferred;
176        if ($map->_prefer_next_map) {
177            $map->is_preferred(0);
178            $map->save or return $map->error($map->errstr);
179        }
180    }
181}
182
183sub _prefer_next_map {
184    my $map = shift;
185    my @all = MT::TemplateMap->load({ blog_id => $map->blog_id,
186                                      archive_type => $map->archive_type });
187    @all = grep { $_->id != $map->id } @all;
188    if (@all) {
189        $all[0]->is_preferred(1);
190        $all[0]->save;
191        return 1;
192    }
193    return 0;
194}
195
1961;
197__END__
198
199=head1 NAME
200
201MT::TemplateMap - Movable Type archive-template association record
202
203=head1 SYNOPSIS
204
205    use MT::TemplateMap;
206    my $map = MT::TemplateMap->new;
207    $map->blog_id($tmpl->blog_id);
208    $map->template_id($tmpl->id);
209    $map->archive_type('Monthly');
210    $map->file_template('<$MTArchiveDate format="%Y/%m/index.html"$>');
211    $map->is_preferred(1);
212    $map->save
213        or die $map->errstr;
214
215=head1 DESCRIPTION
216
217An I<MT::TemplateMap> object represents a single association between an
218Archive Template and an archive type for a particular blog. For example, if
219you set up a template called C<Date-Based> and assign to the C<Monthly>
220archive type in your blog, such an association will be represented by one
221I<MT::TemplateMap> object.
222
223=head1 USAGE
224
225As a subclass of I<MT::Object>, I<MT::TemplateMap> inherits all of the
226data-management and -storage methods from that class; thus you should look
227at the I<MT::Object> documentation for details about creating a new object,
228loading an existing object, saving an object, etc.
229
230=head1 DATA ACCESS METHODS
231
232The I<MT::TemplateMap> object holds the following pieces of data. These
233fields can be accessed and set using the standard data access methods
234described in the I<MT::Object> documentation.
235
236=over 4
237
238=item * id
239
240The numeric ID of the template map record.
241
242=item * blog_id
243
244The numeric ID of the blog with which this template map record is associated.
245
246=item * template_id
247
248The numeric ID of the template.
249
250=item * archive_type
251
252The archive type; should be one of the following values: C<Individual>,
253C<Daily>, C<Weekly>, C<Monthly>, or C<Category>.
254
255=item * file_template
256
257The Archive File Template for this particular mapping; this defines the output
258files for the pages generated from the template for this archive type,
259using standard MT template tags.
260
261=item * is_preferred
262
263A boolean flag specifying whether this particular template is preferred over
264any others defined for this archive type. This is used when generating links
265to archives of this archive type--the link will always link to the preferred
266archive type.
267
268=back
269
270=head1 METHODS
271
272=over 4
273
274=item * save()
275
276Saves the object.  It also rearranges blog's archive type.  If the saved
277template map is new and there is no other template maps with the same
278archive type has been, the archive type is also added to the blog.
279
280=item * remove()
281
282Removes template maps specified in terms and args (if called as class method)
283or the template map (if called as instance method).  It also rearrange blog's
284archive types which are used to determine what types of archive will be
285published during rebuild.  If template map is removed and there remains no
286template map with the archive type, the archive type is removed from blog's
287archive types to be rebuilt.
288
289=item * prefer(boolean)
290
291Set the template map preferred or not, depending on the argument.  If the map
292has been preferred and is being unpreferred, and if there are any other
293I<MT::TemplateMap> objects defined for this particular archive type and blog,
294the first of the other objects will be set as the preferred object.
295Its I<is_preferred> flag will be set to true.  If the map is the only
296I<MT::TemplateMap> object for the blog and the archive type, the method does
297nothing - the map continues to be preferred.
298
299=back
300
301=head1 DATA LOOKUP
302
303In addition to numeric ID lookup, you can look up or sort records by any
304combination of the following fields. See the I<load> documentation in
305I<MT::Object> for more information.
306
307=over 4
308
309=item * blog_id
310
311=item * template_id
312
313=item * archive_type
314
315=item * is_preferred
316
317=back
318
319=head1 NOTES
320
321=over 4
322
323=item * $obj->remove()
324
325When you remove a I<MT::TemplateMap> object using I<MT::TemplateMap::remove>,
326if the I<$map> object you are removing has the I<is_preferred> flag set to
327true, and if there are any other I<MT::TemplateMap> objects defined for this
328particular archive type and blog, the first of the other objects will be
329set as the preferred object. Its I<is_preferred> flag will be set to true.
330
331=back
332
333=head1 AUTHOR & COPYRIGHT
334
335Please see L<MT/AUTHOR & COPYRIGHT>.
336
337=cut
Note: See TracBrowser for help on using the browser.