root/branches/release-32/plugins/WidgetManager/lib/WidgetManager/CMS.pm @ 1623

Revision 1623, 12.5 kB (checked in by bchoate, 20 months ago)

Changes to combine widget set/widget listing together.

  • Property svn:keywords set to Id Revision
Line 
1# Widget Manager plugin for Movable Type
2# Author: Byrne Reese, Six Apart (http://www.sixapart.com)
3# Released under the Artistic License
4#
5# $Id$
6
7package WidgetManager::CMS;
8
9use strict;
10
11sub plugin {
12    return MT->component('WidgetManager');
13}
14
15sub _permission_check {
16    my $app = MT->instance;
17    return ($app->user && $app->user->blog_perm($app->param('blog_id'))->can_edit_templates);
18}
19
20sub save {
21    my $app = shift;
22
23    return $app->error($app->translate('Permission denied.'))
24        unless _permission_check();
25
26    my $q = $app->param();
27
28    my $blog_id = scalar $q->param('blog_id');
29
30    my $str = build_module_list($q->param('modules'));
31
32    # Load the current widgetmanager data
33    my $current = $q->param('widgetmanager') || '';
34    $current = $q->param('name') if $current eq 'New Widget Manager';
35    my $modulesets = plugin()->load_selected_modules($blog_id);
36    $modulesets = {} unless $modulesets;
37
38    # delete old set
39    delete $modulesets->{$q->param('widgetmanager') || ''};
40    # Handle renaming: Delete the entry that has changed names.
41    delete $modulesets->{$q->param('old_name')}; # unless $q->param('old_name') eq $q->param('name');
42    if(exists $modulesets->{$q->param('name')}) {
43        return $app->error($app->translate(
44            "Can't duplicate the existing '[_1]' Widget Manager. Please go back and enter a unique name.",
45            $q->param('name')))
46    }
47    # add it back with a potential new name
48    $modulesets->{$q->param('name')} = $str;
49
50    plugin()->set_config_value('modulesets',$modulesets,"blog:$blog_id");
51
52    return $app->redirect( $app->uri( mode => 'list_widget', args => { blog_id => $blog_id, rebuild => 1 } ) );
53}
54
55sub delete {
56    my $app = shift;
57
58    return $app->error($app->translate('Permission denied.'))
59        unless _permission_check();
60
61    my $q = $app->param();
62    my $blog_id = scalar $q->param('blog_id');
63
64    my $modulesets = plugin()->load_selected_modules($blog_id);
65    $modulesets = {} unless $modulesets;
66
67    my @ids = $q->param('id');
68    delete $modulesets->{$_} for @ids;
69
70    plugin()->set_config_value('modulesets',$modulesets,"blog:$blog_id");
71   
72    return $app->redirect( $app->uri( mode => 'list_widget', args => { blog_id => $blog_id, deleted => 1 } ) );
73}
74
75sub edit {
76    my $app = shift;
77    my (%opt) = @_;
78
79    return $app->error($app->translate('Permission denied.'))
80        unless _permission_check();
81
82      my $q = $app->param();
83      my $blog_id = scalar $q->param('blog_id');
84
85      install_default_widgets($blog_id, 1);
86
87      my $tmpl = $app->load_tmpl('edit.tmpl');
88      $tmpl->param('blog_id'  => $blog_id);
89      $app->add_breadcrumb($app->translate('Main Menu'),$app->{mtscript_url});
90      require MT::Blog;
91      my $blog = MT::Blog->load ($blog_id);
92      $app->add_breadcrumb($blog->name, $app->mt_uri(mode => 'menu', args => { blog_id => $blog_id }));
93      $app->add_breadcrumb($app->translate('Widget Manager'),'?__mode=list_widget&blog_id='.$blog_id);
94      $app->add_breadcrumb($q->param('widgetmanager'));
95
96      my $modulesets = plugin()->load_selected_modules($blog_id);
97      $modulesets = {} unless $modulesets;
98
99      my @names = sort keys %$modulesets;
100      my $widgetmanager = $q->param('widgetmanager') || $names[0] || '';
101
102      # Find non-conflicting name for new Widget Manager
103      if ($widgetmanager eq $app->translate('New Widget Set')) { 
104          $widgetmanager = $app->translate('Widget Manager');
105          if (grep(/^\Q$widgetmanager\E$/, @names)) {
106              my $i = 1;
107              while (grep(/^\Q$widgetmanager $i\E$/, @names)) {
108                  $i++;
109              }
110              # $widgetmanager = "$widgetmanager $i";
111              $widgetmanager = "";
112          }
113      }
114
115      my @selected = exists($modulesets->{$widgetmanager})
116        ? split(/\s*,\s*/,$modulesets->{$widgetmanager})
117        : ();
118
119      my %constraints;
120      $constraints{blog_id} = $blog_id;
121      $constraints{type}    = 'widget';
122      my %options;
123      $options{sort}      = 'name';
124      $options{direction} = 'ascend';
125      require MT::Template;
126      my $iter = MT::Template->load_iter( \%constraints, \%options );
127      my @avail_modules;
128      my @inst_modules;
129      while (my $m = $iter->()) {
130          my $name = $m->name();
131          push @avail_modules, {
132            id => $m->id(),
133            name => $name,
134            selected => in_array($m->id,@selected),
135          };
136      }
137      foreach my $mid (@selected) {
138          for (my $i = 0; $i <= $#avail_modules; $i++) {
139              if ($avail_modules[$i]->{id} == $mid) {
140                  push @inst_modules,$avail_modules[$i];
141                  splice(@avail_modules,$i,1);
142              }
143          }
144      }
145
146      my @widgetmanagers = map { { widgetmanager => $_ } } keys %$modulesets;
147      $tmpl->param(object_loop => \@widgetmanagers);
148
149      $tmpl->param(available => \@avail_modules);
150      $tmpl->param(installed => \@inst_modules);
151      $tmpl->param(name      => $widgetmanager);
152
153      $app->{breadcrumbs}[-1]{is_last} = 1;
154      $tmpl->param(breadcrumbs       => $app->{breadcrumbs});
155      $tmpl->param(plugin_version    => $MT::Plugin::WidgetManager::VERSION);
156      $tmpl->param(rebuild           => $opt{rebuild});
157      return $app->build_page($tmpl);
158}
159
160sub list {
161    my $app = shift;
162    my (%opt) = @_;
163
164    return $app->return_to_dashboard(redirect => 1)
165        unless $app->param('blog_id');
166
167    return $app->return_to_dashboard(permission => 1)
168        unless _permission_check();
169
170      my $q = $app->param;
171      my $blog_id = int(scalar $q->param('blog_id'));
172
173      my $tmpl = $app->load_tmpl('list.tmpl');
174      $tmpl->param('blog_id'  => $blog_id);
175      $app->add_breadcrumb($app->translate("Main Menu"),$app->{mtscript_url});
176      require MT::Blog;
177      my $blog = MT::Blog->load ($blog_id);
178      $app->add_breadcrumb($blog->name,$app->mt_uri( mode => 'menu', args => { blog_id => $blog_id }));
179      $app->add_breadcrumb($app->translate("Widget Manager"));
180
181      my $modulesets = plugin()->load_selected_modules($blog_id) || {};
182
183      my (%constraints, %options);
184      $constraints{blog_id} = $blog_id;
185      $constraints{type}    = 'widget';
186      $options{sort}        = 'name';
187      $options{direction}   = 'ascend';
188
189      require MT::Template;
190      my $iter = MT::Template->load_iter( \%constraints, \%options );
191      my %avail;
192      while (my $m = $iter->()) {
193          my $name = $m->name();
194          $avail{$m->id()} = $name;
195      }
196
197      my @names = sort keys %$modulesets;
198      my $widgetmanager = $q->param('widgetmanager') || $names[0] || '';
199
200      my @widgetmanagers;
201      my @keys = sort keys %$modulesets;
202
203      my $offset = $app->param('offset') || 0;
204      $tmpl->param( list_start => $offset + 1 );
205      $tmpl->param( list_end   => $offset + scalar @keys );
206
207      foreach my $key (@keys) {
208          # Collect the available widgets for this key.
209          my @w = ();
210          for my $w ( split /\s*,\s*/, $modulesets->{$key} ) {
211              push @w, $avail{$w} if $avail{$w};
212          }
213          push @widgetmanagers,{
214            widgetmanager => $key,
215            names   => join(', ', @w),
216            widgets => $modulesets->{$key}
217          };
218    }
219    if ($widgetmanager eq 'New Widget Manager') {
220        $widgetmanager = $q->param('name');
221    }
222
223    require MT::CMS::Template;
224    my $widget_loop = MT::CMS::Template::build_template_table( $app,
225        load_args => [ { type => 'widget', blog_id => $blog_id },
226        { sort => 'name', direction => 'ascend' } ],
227    );
228    $tmpl->param('widget_table', $widget_loop);
229    $tmpl->param('blog_view', 1) if $blog_id;
230
231    $tmpl->param(object_loop => \@widgetmanagers);
232    $tmpl->param(object_type => "widgetset");
233
234    $app->{breadcrumbs}[-1]{is_last} = 1;
235    $tmpl->param(breadcrumbs       => $app->{breadcrumbs});
236    $tmpl->param(plugin_version    => $MT::Plugin::WidgetManager::VERSION);
237    $tmpl->param(rebuild           => $app->param('rebuild') || 0);
238    $tmpl->param(deleted           => $app->param('deleted') || 0);
239    $tmpl->param(listing_screen => 1);
240    $tmpl->param(screen_id => "list-widget-set");
241
242    return $app->build_page($tmpl);
243}
244
245sub build_module_list {
246    my $str = shift;
247    my @mods = split /;/, $str;
248    my @inst;
249    for (@mods) {
250        my ($id, $col) = /(\d+)=(\d+)\.(\d+)/;
251        push @inst, $id if $col == 1;
252    }
253    return join ',', @inst;
254}
255
256sub in_array {
257    my ($needle, @haystack) = @_;
258    for (@haystack) {
259        return 1 if $_ eq $needle;
260    }
261    return 0;
262}
263
264sub install_module {
265    my($blog_id, $name, $text) = @_;
266    my $app = MT->instance;
267    require MT::Template;
268    my $tmpl = MT::Template->new;
269    $tmpl->blog_id($blog_id);
270    $tmpl->type('widget');
271    $tmpl->name($app->translate($name));
272    $tmpl->text($app->translate_templatized($text));
273    $tmpl->save;
274    return $tmpl;
275}
276
277sub create_default_widgetsets {
278    my $app = MT->instance;
279    my ($blog_id) = @_;
280
281    my ( %constraints, %options );
282    $constraints{blog_id} = $blog_id;
283    $constraints{type}    = 'widget';
284    $options{sort}        = 'name';
285    $options{direction}   = 'ascend';
286
287    require MT::Template;
288    my $iter = MT::Template->load_iter( \%constraints, \%options );
289    my %widgets;
290    while ( my $tmpl = $iter->() ) {
291        my $name = $tmpl->name();
292        $widgets{$name} = $tmpl->id();
293    }
294
295    my $widgetsets = [
296        {
297            label   => '2-column layout - Sidebar',
298            widgets => [
299                'Search',
300                'About This Page',
301                'Home Page Widgets Group',
302                'Archive Widgets Group',
303                'Page Listing',
304                'Syndication',
305                'Powered By',
306            ],
307        },
308        {
309            label   => '3-column layout - Primary Sidebar',
310            widgets => [
311                'Archive Widgets Group',
312                'Page Listing',
313                'Syndication',
314                'Powered By',
315            ],
316        },
317        {
318            label   => '3-column layout - Secondary Sidebar',
319            widgets => [
320                'Search',
321                'Home Page Widgets Group',
322                'About This Page',
323            ],
324        },
325    ];
326
327    my $modulesets = plugin()->load_selected_modules($blog_id);
328    $modulesets = {} unless $modulesets;
329
330    foreach my $widgetset ( @{$widgetsets} ) {
331        my $label = plugin()->translate( $widgetset->{label} );
332        my @ids;
333        foreach my $widget ( @{ $widgetset->{widgets} } ) {
334            my $name = plugin()->translate($widget);
335            push @ids, $widgets{$name} if $widgets{$name};
336        }
337        $modulesets->{$label} = join ',', @ids;
338    }
339
340    plugin()->set_config_value( 'modulesets', $modulesets, "blog:$blog_id" );
341}
342
343sub install_default_widgets {
344    my $app = MT->instance;
345    my ( $blog_id, $reinstall ) = @_;
346    my ($tmpl,$default_widget_templates);
347
348    # Gather the existing modules.
349    my $modules = {};
350    require MT::Template;
351    for ( MT::Template->load({ blog_id => $blog_id, type => 'widget' }) ) {
352        my $name = $_->name();
353        $modules->{$name} = $_->linked_file();  # XXX The linked_file is undef for this plugin modules for some reason.
354    }
355
356    use File::Spec;
357    my $widgets_dir = File::Spec->catfile(plugin()->{full_path}, 'default_widgets');
358    my $cfg_file = File::Spec->catfile($widgets_dir, 'widgets.cfg');
359
360    local(*FH, $_, $/);
361    $/ = "\n";
362    open FH, $cfg_file or
363        return $app->error(MT->translate(
364            "Error opening file '[_1]': [_2]", $cfg_file, "$!" ));
365    my $cfg = join('',<FH>);
366    eval "$cfg;";
367    close FH;
368
369    foreach (@$default_widget_templates) {
370        next if exists $modules->{plugin()->translate($_->{label})};
371        open(TMPL, File::Spec->catfile($widgets_dir, $_->{template})) or die "Error: $!\n";
372        while (my $line = <TMPL>) {
373            $_->{text} .= $line;
374        }
375        close TMPL;
376        $tmpl = install_module($blog_id, $_->{label}, $_->{text});
377    }
378
379    unless( $reinstall ) {
380        # Set the 'installed' bit in the config
381        installed($blog_id, 1);
382
383        # Now that the plugin is installed for this blog, create a default widget sets
384        # with all modules pre-installed.
385        create_default_widgetsets($blog_id);
386    }
387}
388
389sub installed {
390    my $config = {};
391    my $app = MT->instance;
392    my ( $blog_id, $save ) = @_;
393
394    my $plugin = plugin();
395    if ($save) {
396        # Set the installed bit, save and return
397        return $plugin->set_config_value('installed',1,"blog:$blog_id");
398    } else {
399        # Return early if status check
400        return $plugin->get_config_value('installed',"blog:$blog_id");
401    }
402}
403
4041;
Note: See TracBrowser for help on using the browser.