| | 1996 | sub save_widget { |
| | 1997 | my $app = shift; |
| | 1998 | my $q = $app->param; |
| | 1999 | |
| | 2000 | $app->validate_magic() or return; |
| | 2001 | my $author = $app->user; |
| | 2002 | |
| | 2003 | my $id = $q->param('id'); |
| | 2004 | |
| | 2005 | if ( !$author->is_superuser ) { |
| | 2006 | $app->run_callbacks( 'cms_save_permission_filter.template', $app, $id ) |
| | 2007 | || return $app->error( |
| | 2008 | $app->translate( "Permission denied: [_1]", $app->errstr() ) ); |
| | 2009 | } |
| | 2010 | |
| | 2011 | my $filter_result = $app->run_callbacks( 'cms_save_filter.widgetset', $app ); |
| | 2012 | |
| | 2013 | if ( !$filter_result ) { |
| | 2014 | return edit_widget( $app, { error => $app->translate( "Save failed: [_1]", $app->errstr ) } ); |
| | 2015 | } |
| | 2016 | |
| | 2017 | my $class = $app->model('template'); |
| | 2018 | my $obj; |
| | 2019 | if ( $id ) { |
| | 2020 | $obj = $class->load($id) |
| | 2021 | or return $app->error($app->translate("Invalid ID [_1]", $id)); |
| | 2022 | } |
| | 2023 | else { |
| | 2024 | $obj = $class->new; |
| | 2025 | } |
| | 2026 | |
| | 2027 | my $original = $obj->clone(); |
| | 2028 | $obj->name($q->param('name')); |
| | 2029 | $obj->type('widgetset'); |
| | 2030 | $obj->blog_id( $q->param('blog_id') || 0 ); |
| | 2031 | $obj->modulesets($q->param('modules')); |
| | 2032 | |
| | 2033 | unless ( |
| | 2034 | $app->run_callbacks( 'cms_pre_save.template', $app, $obj, $original ) ) |
| | 2035 | { |
| | 2036 | return edit_widget( $app, { error => $app->translate( "Save failed: [_1]", $app->errstr ) } ); |
| | 2037 | } |
| | 2038 | |
| | 2039 | $obj->save |
| | 2040 | or return $app->error( |
| | 2041 | $app->translate( "Saving object failed: [_1]", $obj->errstr ) ); |
| | 2042 | |
| | 2043 | $app->run_callbacks( 'cms_post_save.template', $app, $obj, $original ) |
| | 2044 | or return $app->error( $app->errstr() ); |
| | 2045 | |
| | 2046 | $app->redirect( |
| | 2047 | $app->uri( |
| | 2048 | 'mode' => 'edit_widget', |
| | 2049 | args => |
| | 2050 | { blog_id => $obj->blog_id, 'saved' => 1, rebuild => 1, id => $obj->id } |
| | 2051 | ) |
| | 2052 | ); |
| | 2053 | } |
| | 2054 | |
| | 2055 | sub edit_widget { |
| | 2056 | my $app = shift; |
| | 2057 | my (%opt) = @_; |
| | 2058 | |
| | 2059 | my $q = $app->param(); |
| | 2060 | my $id = scalar($q->param('id')) || $opt{id}; |
| | 2061 | my $blog_id = scalar $q->param('blog_id') || 0; |
| | 2062 | |
| | 2063 | my $tmpl_class = $app->model('template'); |
| | 2064 | require MT::Promise; |
| | 2065 | my $obj_promise = MT::Promise::delay( |
| | 2066 | sub { |
| | 2067 | return $tmpl_class->load($id) || undef; |
| | 2068 | } |
| | 2069 | ); |
| | 2070 | |
| | 2071 | if ( !$app->user->is_superuser ) { |
| | 2072 | $app->run_callbacks( 'cms_view_permission_filter.template', |
| | 2073 | $app, $id, $obj_promise ) |
| | 2074 | || return $app->error( |
| | 2075 | $app->translate( "Permission denied: [_1]", $app->errstr() ) ); |
| | 2076 | } |
| | 2077 | |
| | 2078 | my $param = { |
| | 2079 | blog_id => $blog_id, |
| | 2080 | search_type => "template", |
| | 2081 | search_label => MT::Template->class_label_plural, |
| | 2082 | $id ? ( id => $id ) : (), |
| | 2083 | exists($opt{rebuild}) ? ( rebuild => $opt{rebuild} ) : (), |
| | 2084 | exists($opt{error}) ? ( error => $opt{error} ) : (), |
| | 2085 | exists($opt{saved}) ? ( saved => $opt{saved} ) : () |
| | 2086 | }; |
| | 2087 | if ($blog_id) { |
| | 2088 | my $blog = $app->blog; |
| | 2089 | # include_system/include_cache are only applicable |
| | 2090 | # to blog-level templates |
| | 2091 | $param->{include_system} = $blog->include_system; |
| | 2092 | $param->{include_cache} = $blog->include_cache; |
| | 2093 | $param->{include_with_ssi} = 0; |
| | 2094 | $param->{cache_path} = ''; |
| | 2095 | $param->{cache_enabled} = 0; |
| | 2096 | $param->{cache_expire_type} = 0; |
| | 2097 | $param->{cache_expire_period} = ''; |
| | 2098 | $param->{cache_expire_interval} = 0; |
| | 2099 | $param->{ssi_type} = uc $blog->include_system; |
| | 2100 | } |
| | 2101 | |
| | 2102 | my $iter = $tmpl_class->load_iter( |
| | 2103 | { type => 'widget', blog_id => $blog_id ? [ $blog_id, 0 ] : 0 }, |
| | 2104 | { sort => 'name', direction => 'ascend' } |
| | 2105 | ); |
| | 2106 | |
| | 2107 | my %all_widgets; |
| | 2108 | while (my $m = $iter->()) { |
| | 2109 | next unless $m; |
| | 2110 | $all_widgets{ $m->id } = $m->name; |
| | 2111 | } |
| | 2112 | |
| | 2113 | my @inst_modules; |
| | 2114 | my $wtmpl; |
| | 2115 | if ( $id ) { |
| | 2116 | $wtmpl = $obj_promise->force() |
| | 2117 | or return $app->error( |
| | 2118 | $app->translate( |
| | 2119 | "Load failed: [_1]", |
| | 2120 | $tmpl_class->errstr || $app->translate("(no reason given)") |
| | 2121 | ) |
| | 2122 | ); |
| | 2123 | $param->{name} = $wtmpl->name; |
| | 2124 | $param->{include_with_ssi} = $wtmpl->include_with_ssi |
| | 2125 | if defined $wtmpl->include_with_ssi; |
| | 2126 | $param->{cache_path} = $wtmpl->cache_path |
| | 2127 | if defined $wtmpl->cache_path; |
| | 2128 | $param->{cache_expire_type} = $wtmpl->cache_expire_type |
| | 2129 | if defined $wtmpl->cache_expire_type; |
| | 2130 | my ( $period, $interval ) = |
| | 2131 | _get_schedule( $wtmpl->cache_expire_interval ); |
| | 2132 | $param->{cache_expire_period} = $period if defined $period; |
| | 2133 | $param->{cache_expire_interval} = $interval if defined $interval; |
| | 2134 | my @events = split ',', $wtmpl->cache_expire_event; |
| | 2135 | foreach my $name (@events) { |
| | 2136 | $param->{ 'cache_expire_event_' . $name } = 1; |
| | 2137 | } |
| | 2138 | my $modulesets = $wtmpl->modulesets; |
| | 2139 | if ( $modulesets ) { |
| | 2140 | my @modules = split ',', $modulesets; |
| | 2141 | foreach my $mid ( @modules ) { |
| | 2142 | push @inst_modules, { id => $mid, name => $all_widgets{$mid} }; |
| | 2143 | delete $all_widgets{$mid}; |
| | 2144 | } |
| | 2145 | } |
| | 2146 | } |
| | 2147 | $param->{installed} = \@inst_modules if @inst_modules; |
| | 2148 | my @avail_modules = map { { id => $_, name => $all_widgets{$_} } } |
| | 2149 | keys %all_widgets; |
| | 2150 | $param->{available} = \@avail_modules; |
| | 2151 | |
| | 2152 | my $res = $app->run_callbacks('cms_edit.widgetset', $app, $id, $wtmpl, $param); |
| | 2153 | if (!$res) { |
| | 2154 | return $app->error($app->callback_errstr()); |
| | 2155 | } |
| | 2156 | |
| | 2157 | $app->load_tmpl('edit_widget.tmpl', $param); |
| | 2158 | } |
| | 2159 | |
| | 2160 | sub list_widget { |
| | 2161 | my $app = shift; |
| | 2162 | my (%opt) = @_; |
| | 2163 | my $q = $app->param; |
| | 2164 | |
| | 2165 | my $perms = $app->blog ? $app->permissions : $app->user->permissions; |
| | 2166 | return $app->return_to_dashboard( redirect => 1 ) |
| | 2167 | unless $perms || $app->user->is_superuser; |
| | 2168 | if ( $perms && !$perms->can_edit_templates ) { |
| | 2169 | return $app->return_to_dashboard( permission => 1 ); |
| | 2170 | } |
| | 2171 | my $blog_id = $q->param('blog_id') || 0; |
| | 2172 | |
| | 2173 | my $widget_loop = &build_template_table( $app, |
| | 2174 | load_args => [ |
| | 2175 | { type => 'widget', blog_id => $blog_id ? [ $blog_id, 0 ] : 0 }, |
| | 2176 | { sort => 'name', direction => 'ascend' } |
| | 2177 | ], |
| | 2178 | ); |
| | 2179 | |
| | 2180 | my $param = { |
| | 2181 | widget_table => $widget_loop, |
| | 2182 | object_type => "widgetset", |
| | 2183 | search_type => "template", |
| | 2184 | search_label => MT::Template->class_label_plural, |
| | 2185 | listing_screen => 1, |
| | 2186 | screen_id => "list-widget-set", |
| | 2187 | $blog_id ? ( blog_view => 1, blog_id => $blog_id ) : (), |
| | 2188 | exists($opt{rebuild}) ? ( rebuild => $opt{rebuild} ) : (), |
| | 2189 | exists($opt{error}) ? ( error => $opt{error} ) : (), |
| | 2190 | exists($opt{deleted}) ? ( saved => $opt{deleted} ) : () |
| | 2191 | }; |
| | 2192 | |
| | 2193 | my $iter = $app->model('template')->load_iter( |
| | 2194 | { type => 'widgetset', blog_id => $blog_id ? [ $blog_id, 0 ] : 0 }, |
| | 2195 | { sort => 'name', direction => 'ascend' } |
| | 2196 | ); |
| | 2197 | my @widgetmanagers; |
| | 2198 | while ( my $widgetset = $iter->() ) { |
| | 2199 | next unless $widgetset; |
| | 2200 | my $ws = { |
| | 2201 | id => $widgetset->id, |
| | 2202 | widgetmanager => $widgetset->name, |
| | 2203 | }; |
| | 2204 | if ( my $modulesets = $widgetset->modulesets ) { |
| | 2205 | $ws->{widgets} = $modulesets; |
| | 2206 | my @names; |
| | 2207 | foreach my $module ( split ',', $modulesets ) { |
| | 2208 | my ( $widget ) = grep { $_->{id} eq $module } @$widget_loop; |
| | 2209 | push @names, $widget->{name} if $widget; |
| | 2210 | } |
| | 2211 | $ws->{names} = join(', ', @names) if @names; |
| | 2212 | } |
| | 2213 | push @widgetmanagers, $ws; |
| | 2214 | } |
| | 2215 | $param->{object_loop} = \@widgetmanagers if @widgetmanagers; |
| | 2216 | |
| | 2217 | $app->load_tmpl('list_widget.tmpl', $param); |
| | 2218 | } |
| | 2219 | |
| | 2220 | sub delete_widget { |
| | 2221 | my $app = shift; |
| | 2222 | my $q = $app->param; |
| | 2223 | my $type = $q->param('_type'); |
| | 2224 | |
| | 2225 | return $app->errtrans("Invalid request.") |
| | 2226 | unless $type; |
| | 2227 | |
| | 2228 | return $app->error( $app->translate("Invalid request.") ) |
| | 2229 | if $app->request_method() ne 'POST'; |
| | 2230 | |
| | 2231 | $app->validate_magic() or return; |
| | 2232 | |
| | 2233 | my $tmpl_class = $app->model('template'); |
| | 2234 | |
| | 2235 | for my $id ( $q->param('id') ) { |
| | 2236 | next unless $id; # avoid 'empty' ids |
| | 2237 | |
| | 2238 | my $obj = $tmpl_class->load($id); |
| | 2239 | next unless $obj; |
| | 2240 | $app->run_callbacks( 'cms_delete_permission_filter.template', |
| | 2241 | $app, $obj ) |
| | 2242 | || return $app->error( |
| | 2243 | $app->translate( "Permission denied: [_1]", $app->errstr() ) ); |
| | 2244 | |
| | 2245 | $obj->remove |
| | 2246 | or return $app->errtrans( |
| | 2247 | 'Removing [_1] failed: [_2]', |
| | 2248 | $app->translate('template'), |
| | 2249 | $obj->errstr |
| | 2250 | ); |
| | 2251 | $app->run_callbacks( 'cms_post_delete.template', $app, $obj ); |
| | 2252 | } |
| | 2253 | $app->call_return; |
| | 2254 | } |
| | 2255 | |
| | 2256 | sub restore_widgetmanagers { |
| | 2257 | my ($cb, $objects, $deferred, $errors, $callback) = @_; |
| | 2258 | my @keys = grep { $_ =~ /^MT::Template#/ } keys( %$objects ); |
| | 2259 | foreach my $key ( @keys ) { |
| | 2260 | my $tmpl = $objects->{$key}; |
| | 2261 | next unless 'widgetset' eq $tmpl->type; |
| | 2262 | my $modulesets = $tmpl->modulesets; |
| | 2263 | next unless $modulesets; |
| | 2264 | $callback->( MT->translate( 'Restoring widget set [_1]... ', $tmpl->name ) ); |
| | 2265 | |
| | 2266 | my @tmpl_ids = split ',', $modulesets; |
| | 2267 | my @new_ids; |
| | 2268 | foreach my $id ( @tmpl_ids ) { |
| | 2269 | my $new_tmpl = $objects->{"MT::Template#$id"}; |
| | 2270 | next unless $new_tmpl; |
| | 2271 | push @new_ids, $new_tmpl->id; |
| | 2272 | } |
| | 2273 | if ( @new_ids ) { |
| | 2274 | $tmpl->modulesets( join(',', @new_ids) ); |
| | 2275 | $tmpl->save; |
| | 2276 | $callback->( MT->translate("Done.") . "\n" ); |
| | 2277 | } |
| | 2278 | else { |
| | 2279 | $callback->( MT->translate("Failed.") . "\n" ); |
| | 2280 | } |
| | 2281 | } |
| | 2282 | 1; |
| | 2283 | } |
| | 2284 | |