root/branches/release-33/lib/MT/CMS/Category.pm @ 1773

Revision 1773, 13.8 kB (checked in by bchoate, 20 months ago)

Fixed call for move_category. BugId:76422

  • Property svn:keywords set to Id Revision
Line 
1package MT::CMS::Category;
2
3use strict;
4
5sub edit {
6    my $cb = shift;
7    my ($app, $id, $obj, $param) = @_;
8
9    my $blog = $app->blog;
10
11    if ($id) {
12        $param->{nav_categories} = 1;
13
14        #$param{ "tab_" . ( $app->param('tab') || 'details' ) } = 1;
15
16        # $app->add_breadcrumb($app->translate('Categories'),
17        #                      $app->uri( 'mode' => 'list_cat',
18        #                          args => { blog_id => $obj->blog_id }));
19        # $app->add_breadcrumb($obj->label);
20        my $parent   = $obj->parent_category;
21        my $site_url = $blog->site_url;
22        $site_url .= '/' unless $site_url =~ m!/$!;
23        $param->{path_prefix} =
24          $site_url . ( $parent ? $parent->publish_path : '' );
25        $param->{path_prefix} .= '/' unless $param->{path_prefix} =~ m!/$!;
26        require MT::Trackback;
27        my $tb = MT::Trackback->load( { category_id => $obj->id } );
28
29        if ($tb) {
30            my $list_pref = $app->list_pref('ping');
31            %$param = ( %$param, %$list_pref );
32            my $path = $app->config('CGIPath');
33            $path .= '/' unless $path =~ m!/$!;
34            if ($path =~ m!^/!) {
35                my ($blog_domain) = $blog->archive_url =~ m|(.+://[^/]+)|;
36                $path = $blog_domain . $path;
37            }
38
39            my $script = $app->config('TrackbackScript');
40            $param->{tb}     = 1;
41            $param->{tb_url} = $path . $script . '/' . $tb->id;
42            if ( $param->{tb_passphrase} = $tb->passphrase ) {
43                $param->{tb_url} .= '/' . encode_url( $param->{tb_passphrase} );
44            }
45            $app->load_list_actions( 'ping', $param->{ping_table}[0],
46                'pings' );
47        }
48    }
49    1;
50}
51
52sub list {
53    my $app   = shift;
54    my $q     = $app->param;
55    my $type  = $q->param('_type') || 'category';
56    my $class = $app->model($type);
57
58    my $perms = $app->permissions;
59    my $entry_class;
60    my $entry_type;
61    if ( $type eq 'category' ) {
62        $entry_type = 'entry';
63        return $app->return_to_dashboard( redirect => 1 )
64          unless $perms && $perms->can_edit_categories;
65    }
66    elsif ( $type eq 'folder' ) {
67        $entry_type = 'page';
68        return $app->return_to_dashboard( redirect => 1 )
69          unless $perms && $perms->can_manage_pages;
70    }
71    $entry_class = $app->model($entry_type);
72    my $blog_id = scalar $q->param('blog_id');
73    require MT::Blog;
74    my $blog = MT::Blog->load($blog_id)
75      or return $app->errtrans("Invalid request.");
76    my %param;
77    my %authors;
78    my $data = $app->_build_category_list(
79        blog_id    => $blog_id,
80        counts     => 1,
81        new_cat_id => scalar $q->param('new_cat_id'),
82        type       => $type
83    );
84    if ( $blog->site_url =~ /\/$/ ) {
85        $param{blog_site_url} = $blog->site_url;
86    }
87    else {
88        $param{blog_site_url} = $blog->site_url . '/';
89    }
90    $param{object_loop} = $param{category_loop} = $data;
91    $param{saved} = $q->param('saved');
92    $param{saved_deleted} = $q->param('saved_deleted');
93    $app->load_list_actions( $type, \%param );
94
95    #$param{nav_categories} = 1;
96    $param{sub_object_label} =
97        $type eq 'folder'
98      ? $app->translate('Subfolder')
99      : $app->translate('Subcategory');
100    $param{object_label}        = $class->class_label;
101    $param{object_label_plural} = $class->class_label_plural;
102    $param{object_type}         = $type;
103    $param{entry_label_plural}  = $entry_class->class_label_plural;
104    $param{entry_label}         = $entry_class->class_label;
105    $param{search_label}        = $param{entry_label_plural};
106    $param{search_type}         = $entry_type;
107    $param{screen_id} =
108        $type eq 'folder'
109      ? 'list-folder'
110      : 'list-category';
111    $param{listing_screen}      = 1;
112    $app->add_breadcrumb( $param{object_label_plural} );
113
114    $param{screen_class} = "list-${type}";
115    $param{screen_class} .= " list-category"
116      if $type eq 'folder';    # to piggyback on list-category styles
117    my $tmpl_file = 'list_' . $type . '.tmpl';
118    $app->load_tmpl( $tmpl_file, \%param );
119}
120
121sub save {
122    my $app   = shift;
123    my $q     = $app->param;
124    my $perms = $app->permissions;
125    my $type  = $q->param('_type');
126    my $class = $app->model($type)
127      or return $app->errtrans("Invalid request.");
128
129    if ( $type eq 'category' ) {
130        return $app->errtrans("Permission denied.")
131          unless $perms && $perms->can_edit_categories;
132    }
133    elsif ( $type eq 'folder' ) {
134        return $app->errtrans("Permission denied.")
135          unless $perms && $perms->can_manage_pages;
136    }
137
138    $app->validate_magic() or return;
139
140    my $blog_id = $q->param('blog_id');
141    my $cat;
142    if ( my $moved_cat_id = $q->param('move_cat_id') ) {
143        $cat = $class->load( $q->param('move_cat_id') );
144        move_category($app) or return;
145    }
146    else {
147        for my $p ( $q->param ) {
148            my ($parent) = $p =~ /^category-new-parent-(\d+)$/;
149            next unless ( defined $parent );
150
151            my $label = $q->param($p);
152            $label =~ s/(^\s+|\s+$)//g;
153            next unless ( $label ne '' );
154
155            $cat = $class->new;
156            my $original = $cat->clone;
157            $cat->blog_id($blog_id);
158            $cat->label($label);
159            $cat->author_id( $app->user->id );
160            $cat->parent($parent);
161
162            $app->run_callbacks( 'cms_pre_save.' . $type,
163                $app, $cat, $original )
164              || return $app->errtrans( "Saving [_1] failed: [_2]", $type,
165                $app->errstr );
166
167            $cat->save
168              or return $app->error(
169                $app->translate(
170                    "Saving [_1] failed: [_2]",
171                    $type, $cat->errstr
172                )
173              );
174
175            # Now post-process it.
176            $app->run_callbacks( 'cms_post_save.' . $type,
177                $app, $cat, $original );
178        }
179    }
180
181    return $app->errtrans( "The [_1] must be given a name!", $type )
182      if !$cat;
183
184    $app->redirect(
185        $app->uri(
186            'mode' => 'list_cat',
187            args   => {
188                _type      => $type,
189                blog_id    => $blog_id,
190                saved      => 1,
191                new_cat_id => $cat->id
192            }
193        )
194    );
195}
196
197sub category_add {
198    my $app  = shift;
199    my $q    = $app->param;
200    my $type = $q->param('_type') || 'category';
201    my $pkg  = $app->model($type);
202    my $data = $app->_build_category_list(
203        blog_id => scalar $q->param('blog_id'),
204        type    => $type
205    );
206    my %param;
207    $param{'category_loop'} = $data;
208    $app->add_breadcrumb( $app->translate( 'Add a [_1]', $pkg->class_label ) );
209    $param{object_type}  = $type;
210    $param{object_label} = $pkg->class_label;
211    $app->load_tmpl( 'popup/category_add.tmpl', \%param );
212}
213
214sub category_do_add {
215    my $app    = shift;
216    my $q      = $app->param;
217    my $type   = $q->param('_type') || 'category';
218    my $author = $app->user;
219    my $pkg    = $app->model($type);
220    $app->validate_magic() or return;
221    my $name = $q->param('label')
222      or return $app->error( $app->translate("No label") );
223    $name =~ s/(^\s+|\s+$)//g;
224    return $app->errtrans("Category name cannot be blank.")
225      if $name eq '';
226    my $parent   = $q->param('parent') || '0';
227    my $cat      = $pkg->new;
228    my $original = $cat->clone;
229    $cat->blog_id( scalar $q->param('blog_id') );
230    $cat->author_id( $app->user->id );
231    $cat->label($name);
232    $cat->parent($parent);
233
234    if ( !$author->is_superuser ) {
235        $app->run_callbacks( 'cms_save_permission_filter.' . $type,
236            $app, undef )
237          || return $app->error(
238            $app->translate( "Permission denied: [_1]", $app->errstr() ) );
239    }
240
241    my $filter_result = $app->run_callbacks( 'cms_save_filter.' . $type, $app )
242      || return;
243
244    $app->run_callbacks( 'cms_pre_save.' . $type, $app, $cat, $original )
245      || return;
246
247    $cat->save or return $app->error( $cat->errstr );
248
249    # Now post-process it.
250    $app->run_callbacks( 'cms_post_save.' . $type, $app, $cat, $original )
251      or return;
252
253    my $id = $cat->id;
254    $name = encode_js($name);
255    my %param = ( javascript => <<SCRIPT);
256    o.doAddCategoryItem('$name', '$id');
257SCRIPT
258    $app->load_tmpl( 'reload_opener.tmpl', \%param );
259}
260
261sub js_add_category {
262    my $app = shift;
263    unless ( $app->validate_magic ) {
264        return $app->json_error( $app->translate("Invalid request.") );
265    }
266    my $user    = $app->user;
267    my $blog_id = $app->param('blog_id');
268    my $perms   = $app->permissions;
269    my $type    = $app->param('_type') || 'category';
270    my $class   = $app->model($type);
271    if ( !$class ) {
272        return $app->json_error( $app->translate("Invalid request.") );
273    }
274
275    my $label = $app->param('label');
276    my $enc   = $app->config->PublishCharset;
277
278    # XMLHttpRequest always send text in UTF-8... right?
279    if ( 'utf-8' ne lc($enc) ) {
280        $label = MT::I18N::encode_text( $label, 'utf-8', $enc );
281    }
282    my $basename = $app->param('basename');
283    if ( !defined($label) || ( $label =~ m/^\s*$/ ) ) {
284        return $app->json_error( $app->translate("Invalid request.") );
285    }
286
287    my $blog = $app->blog;
288    if ( !$blog ) {
289        return $app->json_error( $app->translate("Invalid request.") );
290    }
291
292    my $parent;
293    if ( my $parent_id = $app->param('parent') ) {
294        if ( $parent_id != -1 ) {    # special case for 'root' folder
295            $parent = $class->load( { id => $parent_id, blog_id => $blog_id } );
296            if ( !$parent ) {
297                return $app->json_error( $app->translate("Invalid request.") );
298            }
299        }
300    }
301
302    my $obj      = $class->new;
303    my $original = $obj->clone;
304
305    if (
306        !$app->run_callbacks(
307            'cms_save_permission.' . $type,
308            $app, $obj, $original
309        )
310      )
311    {
312        return $app->json_error( $app->translate("Permission denied.") );
313    }
314
315    $obj->label($label);
316    $obj->basename($basename)   if $basename;
317    $obj->parent( $parent->id ) if $parent;
318    $obj->blog_id($blog_id);
319    $obj->author_id( $user->id );
320    $obj->created_by( $user->id );
321
322    if (
323        !$app->run_callbacks( 'cms_pre_save.' . $type, $app, $obj, $original ) )
324    {
325        return $app->json_error( $app->errstr );
326    }
327
328    $obj->save;
329
330    $app->run_callbacks( 'cms_post_save.' . $type, $app, $obj, $original );
331
332    return $app->json_result(
333        {
334            id       => $obj->id,
335            basename => $obj->basename
336        }
337    );
338}
339
340sub can_view {
341    my ( $eh, $app, $id ) = @_;
342    my $perms = $app->permissions;
343    return $perms->can_edit_categories();
344}
345
346sub can_save {
347    my ( $eh, $app, $id ) = @_;
348    my $perms = $app->permissions;
349    return $perms->can_edit_categories();
350}
351
352sub can_delete {
353    my ( $eh, $app, $obj ) = @_;
354    return 1 if $app->user->is_superuser();
355    my $perms = $app->permissions;
356    return $perms && $perms->can_edit_categories();
357}
358
359sub pre_save {
360    my $eh = shift;
361    my ( $app, $obj ) = @_;
362    my $pkg = $app->model('category');
363    if ( defined( my $pass = $app->param('tb_passphrase') ) ) {
364        $obj->{__tb_passphrase} = $pass;
365    }
366    my @siblings = $pkg->load(
367        {
368            parent  => $obj->parent,
369            blog_id => $obj->blog_id
370        }
371    );
372    foreach (@siblings) {
373        next if $obj->id && ( $_->id == $obj->id );
374        return $eh->error(
375            $app->translate(
376"The category name '[_1]' conflicts with another category. Top-level categories and sub-categories with the same parent must have unique names.",
377                $_->label
378            )
379        ) if $_->label eq $obj->label;
380        return $eh->error(
381            $app->translate(
382"The category basename '[_1]' conflicts with another category. Top-level categories and sub-categories with the same parent must have unique basenames.",
383                $_->label
384            )
385        ) if $_->basename eq $obj->basename;
386    }
387    1;
388}
389
390sub post_save {
391    my $eh = shift;
392    my ( $app, $obj, $original ) = @_;
393
394    if ( !$original->id ) {
395        $app->log(
396            {
397                message => $app->translate(
398                    "Category '[_1]' created by '[_2]'", $obj->label,
399                    $app->user->name
400                ),
401                level    => MT::Log::INFO(),
402                class    => 'category',
403                category => 'new',
404            }
405        );
406    }
407    1;
408}
409
410sub save_filter {
411    my $eh = shift;
412    my ($app) = @_;
413    return $app->errtrans( "The name '[_1]' is too long!",
414        $app->param('label') )
415      if ( length( $app->param('label') ) > 100 );
416    return 1;
417}
418
419sub post_delete {
420    my ( $eh, $app, $obj ) = @_;
421
422    $app->log(
423        {
424            message => $app->translate(
425                "Category '[_1]' (ID:[_2]) deleted by '[_3]'",
426                $obj->label, $obj->id, $app->user->name
427            ),
428            level    => MT::Log::INFO(),
429            class    => 'system',
430            category => 'delete'
431        }
432    );
433}
434
435sub move_category {
436    my $app   = shift;
437    my $type  = $app->param('_type');
438    my $class = $app->model($type)
439      or return $app->errtrans("Invalid request.");
440    $app->validate_magic() or return;
441
442    my $cat        = $class->load( $app->param('move_cat_id') );
443    my $new_parent = $app->param('move-radio');
444
445    return 1 if ( $new_parent == $cat->parent );
446
447    $cat->parent($new_parent);
448    my @siblings = $class->load(
449        {
450            parent  => $cat->parent,
451            blog_id => $cat->blog_id
452        }
453    );
454    foreach (@siblings) {
455
456        # FIXME: Language should support both category / folder
457        return $app->errtrans(
458"The category name '[_1]' conflicts with another category. Top-level categories and sub-categories with the same parent must have unique names.",
459            $_->label
460        ) if $_->label eq $cat->label;
461    }
462
463    $cat->save
464      or return $app->error(
465        $app->translate( "Saving category failed: [_1]", $cat->errstr ) );
466}
467
4681;
Note: See TracBrowser for help on using the browser.