Changeset 752
- Timestamp:
- 11/16/06 16:42:32 (2 years ago)
- Files:
-
- branches/wheeljack/build/mt-dists/MT.mk (modified) (1 diff)
- branches/wheeljack/lib/MT.pm.pre (modified) (2 diffs)
- branches/wheeljack/lib/MT/App/CMS.pm (modified) (27 diffs)
- branches/wheeljack/lib/MT/App/Comments.pm (modified) (2 diffs)
- branches/wheeljack/lib/MT/Asset.pm (modified) (6 diffs)
- branches/wheeljack/lib/MT/Asset/Image.pm (modified) (2 diffs)
- branches/wheeljack/lib/MT/Entry.pm (modified) (1 diff)
- branches/wheeljack/lib/MT/FileInfo.pm (modified) (3 diffs)
- branches/wheeljack/lib/MT/Image.pm (modified) (2 diffs)
- branches/wheeljack/lib/MT/Object.pm (modified) (1 diff)
- branches/wheeljack/lib/MT/ObjectDriver/DBM.pm (modified) (1 diff)
- branches/wheeljack/lib/MT/Template/Context.pm (modified) (2 diffs)
- branches/wheeljack/lib/MT/Template/ContextHandlers.pm (modified) (17 diffs)
- branches/wheeljack/lib/MT/Upgrade.pm (modified) (1 diff)
- branches/wheeljack/mt-static/styles.css (modified) (2 diffs)
- branches/wheeljack/php/lib/MTUtil.php (modified) (6 diffs)
- branches/wheeljack/php/lib/block.MTCategories.php (modified) (2 diffs)
- branches/wheeljack/php/lib/block.MTEntries.php (modified) (1 diff)
- branches/wheeljack/php/lib/block.MTTags.php (modified) (2 diffs)
- branches/wheeljack/php/lib/function.MTBlogArchiveURL.php (modified) (1 diff)
- branches/wheeljack/php/lib/function.MTCategoryTrackbackCount.php (modified) (1 diff)
- branches/wheeljack/php/lib/function.MTCommentBody.php (modified) (1 diff)
- branches/wheeljack/php/lib/mtdb_base.php (modified) (7 diffs)
- branches/wheeljack/php/lib/mtdb_mysql.php (modified) (2 diffs)
- branches/wheeljack/plugins/WidgetManager/lib/WidgetManager/App.pm (modified) (2 diffs)
- branches/wheeljack/search_templates/default.tmpl (modified) (1 diff)
- branches/wheeljack/tmpl/cms/edit_admin_permissions.tmpl (deleted)
- branches/wheeljack/tmpl/cms/edit_author.tmpl (modified) (1 diff)
- branches/wheeljack/tmpl/cms/edit_permissions.tmpl (deleted)
- branches/wheeljack/tmpl/cms/edit_profile.tmpl (modified) (1 diff)
- branches/wheeljack/tmpl/cms/edit_role.tmpl (modified) (2 diffs)
- branches/wheeljack/tmpl/cms/list_asset.tmpl (modified) (8 diffs)
- branches/wheeljack/tmpl/cms/list_association.tmpl (modified) (1 diff)
- branches/wheeljack/tmpl/cms/list_blog.tmpl (modified) (1 diff)
- branches/wheeljack/tmpl/cms/list_role.tmpl (modified) (1 diff)
- branches/wheeljack/tools/convert-db (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/wheeljack/build/mt-dists/MT.mk
r731 r752 2 2 PRODUCT_CODE = MT 3 3 PRODUCT_VERSION = 3.3 4 SCHEMA_VERSION = 3.300 34 SCHEMA_VERSION = 3.3005 5 5 API_VERSION = 3.33 branches/wheeljack/lib/MT.pm.pre
r748 r752 1816 1816 1817 1817 Movable Type has a variety of hook points at which a plugin can attach 1818 a callback. The context and calling conventions of each one are 1819 documented here. 1818 a callback. 1820 1819 1821 1820 In each case, the first parameter is an L<MT::Callback> object which … … 1823 1822 1824 1823 The app-level callbacks related to rebuilding are documented 1825 in L<MT::WeblogPublisher>. The specific apps document the callbacks which1826 they invoke.1824 in L<MT::WeblogPublisher>. The specific apps document the callbacks 1825 which they invoke. 1827 1826 1828 1827 =head1 LICENSE branches/wheeljack/lib/MT/App/CMS.pm
r751 r752 887 887 my %args = ( sort => 'created_on', direction => 'descend' ); 888 888 889 my $ type_filter;889 my $class_filter; 890 890 my $filter = ($app->param('filter') || ''); 891 if ($filter eq ' archive_type') {892 $ type_filter = $app->param('filter_val');891 if ($filter eq 'class') { 892 $class_filter = $app->param('filter_val'); 893 893 } 894 894 … … 906 906 my %blogs; 907 907 require File::Basename; 908 require JSON; 908 909 my $auth_prefs = $app->user->entry_prefs; 909 910 my $tag_delim = chr($auth_prefs->{tag_delim}); … … 919 920 $row->{blog_name} = $blog ? $blog->name : '-'; 920 921 $row->{file_name} = File::Basename::basename($row->{file_path}); 922 my $meta = $obj->metadata; 921 923 if (-f $row->{file_path}) { 922 924 my @stat = stat($row->{file_path}); 923 925 my $size = $stat[7]; 924 $row->{asset_type} = $app->translate($obj->type_name); 926 $row->{thumbnail_url} = $meta->{thumbnail_url} = 927 $obj->thumbnail_url(Height => 230, Width => 164); 928 $row->{asset_class} = $obj->class_label; 925 929 $row->{file_size} = $size; 926 $row->{tags} = MT::Tag->join($tag_delim, $obj->tags);927 930 if ($size < 1024) { 928 931 } elsif ($size < 1024000) { … … 935 938 $ts = $stat[10]; 936 939 $ts = epoch2ts($blog, $ts); 940 } 941 if (my $by = $obj->created_by) { 942 my $user = MT::Author->load($by, { cached_ok => 1 }); 943 $row->{created_by} = $user ? $user->name : ''; 937 944 } 938 945 if ($ts) { … … 947 954 $row->{file_is_missing} = 1; 948 955 } 956 $row->{metadata_json} = JSON::objToJson($meta); 949 957 }; 950 958 951 if ($ type_filter) {952 my $asset_pkg = MT::Asset-> type_class($type_filter);953 $terms{ archive_type} = $asset_pkg->types;959 if ($class_filter) { 960 my $asset_pkg = MT::Asset->class_handler($class_filter); 961 $terms{class} = $asset_pkg->classes; 954 962 } else { 955 $terms{ archive_type} = MT::Asset->types;963 $terms{class} = MT::Asset->classes; 956 964 } 957 965 958 966 # identifier => name 959 my $ types = MT::Asset->type_names;960 my @ type_loop;961 foreach my $ type (keys %$types) {962 push @ type_loop, {963 type_id => $type,964 type_name => $types->{$type},967 my $classes = MT::Asset->class_labels; 968 my @class_loop; 969 foreach my $class (keys %$classes) { 970 push @class_loop, { 971 class_id => $class, 972 class_label => $classes->{$class}, 965 973 }; 966 974 } 967 975 # Now, sort it 968 @ type_loop = sort { $a->{type_name} cmp $b->{type_name} } @type_loop;976 @class_loop = sort { $a->{class_label} cmp $b->{class_label} } @class_loop; 969 977 970 978 $app->listing({ … … 979 987 edit_blog_id => $blog_id, 980 988 ) : ()), 981 type_loop => \@type_loop,989 class_loop => \@class_loop, 982 990 can_delete_files => $app->user->is_superuser, 983 991 nav_assets => 1, 992 has_expanded_mode => 1, 984 993 }, 985 994 }); … … 2266 2275 push @class_loop, { 2267 2276 class_name => $_, 2268 class_label => $ app->translate($MT::Log::Classes{$_}->class_label),2277 class_label => $MT::Log::Classes{$_}->class_label, 2269 2278 }; 2270 2279 } … … 2726 2735 $q->param($col) : $obj->$col(); 2727 2736 } 2737 # Make certain any blog-specific element matches the blog we're 2738 # dealing with. If not, call shenanigans. 2739 if (defined($blog_id) && (exists $param{blog_id}) && ($blog_id != $obj->blog_id)) { 2740 return $app->error($app->translate("Invalid parameter")); 2741 } 2742 2728 2743 # Set type-specific display parameters 2729 2744 if ($type eq 'entry') { … … 3110 3125 $param{core_itemset_action_loop} = $core_actions || []; 3111 3126 $param{has_itemset_actions} = 3112 ( $plugin_actions || $core_actions) ? 1 : 0;3127 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 3113 3128 3114 3129 # since MT::App::build_page clobbers it: … … 3177 3192 $param{core_itemset_action_loop} = $core_actions || []; 3178 3193 $param{has_itemset_actions} = 3179 ( $plugin_actions || $core_actions) ? 1 : 0;3194 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 3180 3195 } elsif ($type eq 'author') { 3181 3196 # TODO: Populate permissions / blogs for this user … … 5213 5228 $param{core_itemset_action_loop} = $core_actions || []; 5214 5229 $param{has_itemset_actions} = 5215 ( $plugin_actions || $core_actions) ? 1 : 0;5230 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 5216 5231 5217 5232 $param{saved} = $q->param('saved'); … … 5502 5517 5503 5518 require MT::Asset; 5504 my $img_pkg = MT::Asset-> type_class('asset:image');5519 my $img_pkg = MT::Asset->class_handler('image'); 5505 5520 my $asset = new $img_pkg; 5506 5521 $asset->blog_id($blog_id); 5507 $asset->url($thumb);5522 #$asset->url($thumb); 5508 5523 $asset->file_path($t_file); 5509 5524 $asset->file_name($basename); … … 5513 5528 $asset->image_width($thumb_width); 5514 5529 $asset->image_height($thumb_height); 5530 $asset->created_by($app->user->id); 5515 5531 $asset->save; 5516 5532 … … 5575 5591 $url .= $rel_url_ext; 5576 5592 5577 my $img_pkg = MT::Asset-> type_class('asset:image');5593 my $img_pkg = MT::Asset->class_handler('image'); 5578 5594 my $asset = new $img_pkg; 5579 5595 $asset->blog_id($blog_id); … … 5582 5598 $asset->file_name($basename); 5583 5599 $asset->file_ext($blog->file_extension); 5600 $asset->created_by($app->user->id); 5584 5601 $asset->save; 5585 5602 … … 6056 6073 $param->{commenter_table}[0]{core_itemset_action_loop} = $core_actions || []; 6057 6074 $param->{commenter_table}[0]{has_itemset_actions} = 6058 ( $plugin_actions || $core_actions) ? 1 : 0;6075 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 6059 6076 $param->{commenter_table}[0]{plugin_action_loop} = $app->plugin_actions('list_commenters') || []; 6060 6077 \@data; … … 6304 6321 $param->{template_table}[0]{core_itemset_action_loop} = $core_actions || []; 6305 6322 $param->{template_table}[0]{has_itemset_actions} = 6306 ( $plugin_actions || $core_actions) ? 1 : 0;6323 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 6307 6324 \@data; 6308 6325 } … … 6411 6428 $param->{comment_table}[0]{core_itemset_action_loop} = $core_actions || []; 6412 6429 $param->{comment_table}[0]{has_itemset_actions} = 6413 ( $plugin_actions || $core_actions) ? 1 : 0;6430 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 6414 6431 \@data; 6415 6432 } … … 6900 6917 $param->{ping_table}[0]{core_itemset_action_loop} = $core_actions || []; 6901 6918 $param->{ping_table}[0]{has_itemset_actions} = 6902 ( $plugin_actions || $core_actions) ? 1 : 0;6919 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 6903 6920 \@data; 6904 6921 } … … 7252 7269 $param->{entry_table}[0]{core_itemset_action_loop} = $core_actions || []; 7253 7270 $param->{entry_table}[0]{has_itemset_actions} = 7254 ( $plugin_actions || $core_actions) ? 1 : 0;7271 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 7255 7272 \@data; 7256 7273 } … … 7364 7381 $obj = MT::Entry->load($id) 7365 7382 || return $app->error($app->translate("No such entry.")); 7383 return $app->error($app->translate("Invalid parameter")) 7384 unless $obj->blog_id == $blog_id; 7366 7385 return $app->error($app->translate("Permission denied.")) 7367 7386 unless $perms->can_edit_entry($obj, $author); … … 7807 7826 $param{core_itemset_action_loop} = $core_actions || []; 7808 7827 $param{has_itemset_actions} = 7809 ( $plugin_actions || $core_actions) ? 1 : 0;7828 (scalar(@$plugin_actions) || scalar(@$core_actions)) ? 1 : 0; 7810 7829 $param{nav_categories} = 1; 7811 7830 $app->add_breadcrumb($app->translate('Categories')); … … 9273 9292 $param{is_image} = defined($w) && defined($h); 9274 9293 require File::Basename; 9275 $basename = File::Basename::basename($local_file);9294 my $local_basename = File::Basename::basename($local_file); 9276 9295 my $ext = ''; 9277 9296 if ($local_file =~ m/\.([A-Za-z]+)$/) { … … 9280 9299 9281 9300 require MT::Asset; 9282 my $img_pkg = MT::Asset-> type_class($param{is_image} ? 'asset:image' : 'asset');9301 my $img_pkg = MT::Asset->class_handler($param{is_image} ? 'image' : 'file'); 9283 9302 my $asset = new $img_pkg; 9284 9303 $asset->blog_id($blog_id); 9285 9304 $asset->url($url); 9286 9305 $asset->file_path($local_file); 9287 $asset->file_name($ basename);9306 $asset->file_name($local_basename); 9288 9307 $asset->file_ext($ext); 9289 9308 if ($param{is_image}) { … … 9291 9310 $asset->image_height($h); 9292 9311 } 9312 $asset->created_by($app->user->id); 9293 9313 $asset->save; 9294 9314 … … 9520 9540 ## on it if it's there. 9521 9541 if (defined $search) { 9542 my $enc = MT::ConfigMgr->instance->PublishCharset; 9543 $search = MT::I18N::encode_text($search, 'utf-8', $enc) if ($enc !~ m/utf-?8/i) && ('dialog_grant_role' eq $app->param('__mode')); 9522 9544 $search = quotemeta($search) unless $is_regex; 9523 9545 $search = '(?i)' . $search unless $case; … … 9535 9557 $terms{'type'} = MT::Author::AUTHOR(); 9536 9558 if ('dialog_grant_role' eq $app->param('__mode')) { 9537 @cols = qw(name );9559 @cols = qw(name nickname email url); 9538 9560 } elsif ($blog_id) { 9539 9561 $args{'join'} = MT::Permission->join_on('author_id', { blog_id => $blog_id } ); branches/wheeljack/lib/MT/App/Comments.pm
r717 r752 633 633 my %params = @_; 634 634 require MT::Author; 635 my $cmntr = MT::Author->load({ name => $params{n ickname},635 my $cmntr = MT::Author->load({ name => $params{name}, 636 636 type => MT::Author::COMMENTER }); 637 637 if (!$cmntr) { … … 647 647 } else { 648 648 $cmntr->set_values({email => $params{email}, 649 nickname => $params{n ame},649 nickname => $params{nickname}, 650 650 password => "(none)", 651 651 type => MT::Author::COMMENTER, branches/wheeljack/lib/MT/Asset.pm
r734 r752 9 9 use strict; 10 10 use MT::Tag; 11 use base qw(MT::FileInfo MT::Taggable); 11 use base qw(MT::Object MT::Taggable); 12 13 __PACKAGE__->install_properties({ 14 column_defs => { 15 'id' => 'integer not null auto_increment', 16 'class' => 'string(255)', 17 'blog_id' => 'integer not null', 18 'label' => 'string(255)', 19 'url' => 'string(255)', 20 'description' => 'text', 21 'file_path' => 'string(255)', 22 'file_name' => 'string(255)', 23 'file_ext' => 'string(20)', 24 'mime_type' => 'string(255)', 25 'image_width' => 'integer', 26 'image_height' => 'integer', 27 'duration' => 'integer', 28 'parent' => 'integer', 29 }, 30 indexes => { 31 blog_id => 1, 32 url => 1, 33 label => 1, 34 file_path => 1, 35 class => 1, 36 parent => 1, 37 created_by => 1, 38 created_on => 1, 39 }, 40 audit => 1, 41 datasource => 'asset', 42 primary_key => 'id', 43 }); 12 44 13 45 # A registry of mappings between asset identifiers and packages. 14 46 our %Classes = ( 15 'MT::Asset::Image' => 'asset:image', 47 'image' => 'MT::Asset::Image', 48 'file' => 'MT::Asset', 16 49 ); 17 50 our %Types = ( 18 'asset:image' => 'MT::Asset::Image', 51 'MT::Asset::Image' => 'image', 52 'MT::Asset' => 'file', 19 53 ); 54 55 sub set_defaults { 56 my $obj = shift; 57 my $pkg = ref $obj; 58 $obj->class($pkg->class); 59 } 60 61 sub class { 62 my $pkg = shift; 63 return $pkg->SUPER::class(@_) if ref $pkg; 64 $Types{ref $pkg || $pkg} || 'file'; 65 } 20 66 21 67 # Returns the list of registered asset identifiers for this class 22 68 # and those that derive from it. Also includes the type of the package 23 69 # invoked. 24 sub types { 25 my $pkg = shift; 26 my $this_type = $pkg->type; 27 my @types = keys %Types; 28 @types = grep { m/^\Q$this_type\E:/ } @types; 29 push @types, $this_type; 30 \@types; 70 sub classes { 71 my $pkg = shift; 72 my $this_class = $pkg->class; 73 my @classes = values %Types; 74 if ($this_class ne 'file') { 75 @classes = grep { m/^\Q$this_class\E:/ } @classes; 76 push @classes, $this_class; 77 } 78 \@classes; 31 79 } 32 80 33 81 # Allows registration (or replacement) of an asset type. 34 sub add_type { 35 my $pkg = shift; 36 my ($type, $class) = @_; 37 if (exists $Types{$type}) { 38 delete $Classes{$Types{$type}}; 39 } 40 $Types{$type} = $class; 41 $Classes{$class} = $type; 82 sub add_class { 83 my $pkg = shift; 84 my ($ident, $package) = @_; 85 if (exists $Classes{$ident}) { 86 delete $Types{$Classes{$ident}}; 87 } 88 $Classes{$ident} = $package; 89 $Types{$package} = $ident; 90 } 91 92 sub extensions { 93 undef; 94 } 95 96 # This property is a meta-property. 97 sub url { 98 my $asset = shift; 99 my $url = $asset->SUPER::url(@_); 100 return $url if defined $url; 101 102 return $asset->cache_property(sub { 103 my $blog = $asset->blog or return undef; 104 my $url = $blog->site_url; 105 $url .= '/' unless $url =~ m!/$!; 106 my $path = $asset->file_path; 107 $path =~ s!\\!/!g; 108 $url .= $path; 109 $url; 110 }, @_); 42 111 } 43 112 … … 48 117 # available, this will at least offer the generic package to access the 49 118 # asset.) 50 sub type_class { 51 my $pkg = shift; 52 my ($type) = @_; 53 return 'MT::Asset' if $type eq 'asset'; 54 my $class = $Types{$type}; 55 if ($class) { 56 eval "use $class;"; 57 return $class unless $@; 119 sub class_handler { 120 my $pkg = shift; 121 my ($class) = @_; 122 my $package = $Classes{$class}; 123 if ($package) { 124 if (defined *{$package.'::'}) { 125 return $package; 126 } else { 127 eval "use $package;"; 128 return $package unless $@; 129 } 58 130 } 59 131 __PACKAGE__; … … 61 133 62 134 # Returns a hashref of asset identifiers mapped to the localized string 63 # used to name them. (Ie, asset:image => 'Image').64 sub type_names {65 my $pkg = shift; 66 my %names = ($pkg->type => $pkg->type_name);67 foreach (keys % Types) {68 my $class = $pkg-> type_class($_);69 $names{$class-> type} = $class->type_name;135 # used to name them. (Ie, image => 'Image'). 136 sub class_labels { 137 my $pkg = shift; 138 my %names; 139 foreach (keys %Classes) { 140 my $class = $pkg->class_handler($_); 141 $names{$class->class} = $class->class_label; 70 142 } 71 143 \%names; 72 }73 74 # Initializes the MT::Asset object (which is actually a MT::FileInfo object),75 # assigning a generic asset_type to it.76 sub init {77 my $asset = shift;78 $asset->SUPER::init(@_);79 my $type = $asset->type;80 $asset->archive_type($asset->type);81 $asset;82 }83 84 # Returns the asset type identifier; for generic MT::Asset, this is just85 # 'asset'86 sub type {87 'asset';88 144 } 89 145 90 146 # Returns a localized name for the asset type. For MT::Asset, this is simply 91 147 # 'File'. 92 sub type_name{148 sub class_label { 93 149 MT->translate('File'); 94 150 } … … 99 155 my $obj = shift; 100 156 $obj->SUPER::set_values(@_); 101 my $ at = $obj->archive_type;102 if (my $pkg = $obj-> type_class($at)) {157 my $t = $obj->class; 158 if (my $pkg = $obj->class_handler($t)) { 103 159 bless $obj, $pkg; 104 160 } 105 161 $obj; 106 }107 108 # Calls the standard MT::Object::load routine, but sets the109 # archive_type, if unset. This restricts the load to include only110 # the assets that match the package requested. Note that this will111 # exclude by default all other asset types, even if you use112 # MT::Asset->load. To include all asset types, the archive_type113 # load term should be set to the value of MT::Asset->types.114 sub load {115 my $pkg = shift;116 my ($terms, $args) = @_;117 if ($terms && (!ref($terms))) {118 $terms = { id => $terms };119 } else {120 $terms ||= {};121 }122 $terms->{archive_type} ||= $pkg->type;123 $pkg->SUPER::load(@_);124 }125 126 # See notes for the load method.127 sub load_iter {128 my $pkg = shift;129 my ($terms, $args) = @_;130 if ($terms && (!ref($terms))) {131 $terms = { id => $terms };132 } else {133 $terms ||= {};134 }135 $terms->{archive_type} ||= $pkg->type;136 $pkg->SUPER::load_iter(@_);137 162 } 138 163 … … 147 172 148 173 # Removes the asset, associated tags and related file. 174 # TBD: Should we track and remove any generated thumbnail files here too? 149 175 sub remove { 150 176 my $asset = shift; … … 160 186 } 161 187 188 sub blog { 189 my $asset = shift; 190 $asset->cache_property(sub { 191 my $blog_id = $asset->blog_id or return undef; 192 require MT::Blog; 193 MT::Blog->load($blog_id, { cached_ok => 1 }); 194 }); 195 } 196 197 # Returns a true/false response based on whether the active package 198 # has extensions registered that match the requested filename. 199 sub can_handle { 200 my $pkg = shift; 201 my ($filename) = @_; 202 my $ext = lc $filename; 203 $ext =~ s/.*\.//; 204 my $extensions = $pkg->extensions or return 0; 205 foreach my $this_ext (@$extensions) { 206 if (ref $this_ext eq 'Regexp') { 207 return 1 if $ext =~ m/$this_ext/; 208 } elsif ($this_ext eq $ext) { 209 return 1; 210 } 211 } 212 0; 213 } 214 215 # Given a filename, returns an appropriate MT::Asset class to associate 216 # with it. This lookup is based purely on file extension! If none can 217 # be found, it returns MT::Asset. 218 sub handler_for_file { 219 my $pkg = shift; 220 my ($filename) = @_; 221 my $classes = $pkg->classes || []; 222 foreach my $class (@$classes) { 223 my $this_pkg = $pkg->class_handler($class); 224 if ($this_pkg->can_handle($filename)) { 225 return $this_pkg; 226 } 227 } 228 __PACKAGE__; 229 } 230 231 sub metadata { 232 my $asset = shift; 233 return { 234 MT->translate("Tags") => MT::Tag->join(',', $asset->tags), 235 url => $asset->url, 236 file => $asset->file_path, 237 name => $asset->file_name, 238 'class' => $asset->class, 239 ext => $asset->file_ext, 240 mime_type => $asset->mime_type, 241 duration => $asset->duration, 242 }; 243 } 244 245 sub thumbnail_file { 246 undef; 247 } 248 249 sub stock_icon_url { 250 undef; 251 } 252 253 sub thumbnail_url { 254 my $asset = shift; 255 my $file_path = $asset->thumbnail_file(@_); 256 if ((defined $file_path) && (-f $file_path)) { 257 require File::Basename; 258 my ($base) = File::Basename::basename($file_path); 259 my $url = $asset->url; 260 my $file = $asset->file_name; 261 $url =~ s/%([A-F0-9]{2})/chr(hex($1))/gei; 262 $url =~ s!\Q$file\E$!$base!; 263 return $url; 264 } 265 # Use a stock icon 266 return $asset->stock_icon_url(@_); 267 } 268 162 269 1; 270 271 __END__ 272 273 =head1 NAME 274 275 MT::Asset 276 277 =head1 SYNOPSIS 278 279 use MT::Asset; 280 281 # Example 282 283 =head1 DESCRIPTION 284 285 This module provides an object definition for a file that is placed under 286 MT's control for publishing. 287 288 =head1 METHODS 289 290 =head2 MT::Asset->new 291 292 Constructs a new asset object. The base class is the generic asset object, 293 which represents a generic file. 294 295 =head2 MT::Asset->handler_for_file($filename) 296 297 Returns a I<MT::Asset> package suitable for the filename given. This 298 determination is typically made based on the file's extension. 299 300 =head1 AUTHORS & COPYRIGHT 301 302 Please see the I<MT> manpage for author, copyright, and license information. 303 304 =cut branches/wheeljack/lib/MT/Asset/Image.pm
r733 r752 9 9 use base 'MT::Asset'; 10 10 11 sub type { 12 'asset:image'; 11 # List of supported file extensions (to aid the stock 'can_handle' method.) 12 sub extensions { 13 ['gif', 'jpg', 'jpeg', 'png']; 13 14 } 14 15 15 sub type_name{16 sub class_label { 16 17 MT->translate('Image'); 17 18 } … … 19 20 sub metadata { 20 21 my $obj = shift; 21 { height => $obj->image_height, width => $obj->image_width }; 22 my $meta = $obj->SUPER::metadata(@_); 23 $meta->{MT->translate("Dimensions")} = MT->translate("[_1] wide, [_2] high", 24 $obj->image_width, $obj->image_height); 25 $meta; 26 } 27 28 sub thumbnail_file { 29 my $asset = shift; 30 my (%param) = @_; 31 my $file_path = $asset->file_path; 32 my @imginfo = stat($file_path); 33 return undef unless @imginfo; 34 35 my $h = $param{Height}; 36 my $w = $param{Width}; 37 require File::Basename; 38 my $path = File::Basename::dirname($file_path); 39 my $file = $asset->file_name; 40 $file =~ s!\.[a-z]+$!!i; 41 $thumbnail = File::Spec->catfile($path, $file . '-thumb-' . $h . 'x' . $w . '.' . $asset->file_ext); 42 my @thumbinfo = stat($thumbnail); 43 44 # thumbnail file exists and is dated on or later than source image 45 if (@thumbinfo && ($thumbinfo[9] >= $imginfo[9])) { 46 return $thumbnail; 47 } 48 49 # stale or non-existent thumbnail. let's create one! 50 my $blog = $param{Blog}; 51 $blog ||= MT::Blog->load($asset->blog_id, { cached_ok => 1 }); 52 return undef unless $blog; 53 my $fmgr = $blog->file_mgr; 54 return undef unless $fmgr; 55 56 # create a thumbnail for this file 57 require MT::Image; 58 my $img = new MT::Image(Filename => $file_path) 59 or return $asset->error(MT::Image->errstr); 60 61 # 100000px wide image, 10px tall => 164x230 62 # scale the horizontal to fit 63 # 100000px tall image, 10px wide => 164x230 64 # scale the vertical to fit 65 # 100000px wide/tall => 164x230 66 # scale the horizontal to fit 67 68 # find the longest dimension of the image: 69 my ($i_h, $i_w) = ($img->{height}, $img->{width}); 70 my ($n_h, $n_w) = ($i_h, $i_w); 71 my $scale = ''; 72 if ($i_h > $i_w) { 73 # scale, if necessary, by height 74 if ($i_h > $h) { 75 $scale = 'h'; 76 } elsif ($i_w > $w) { 77 $scale = 'w'; 78 } 79 } else { 80 # scale, if necessary, by width 81 if ($i_w > $w) { 82 $scale = 'w'; 83 } elsif ($i_h > $h) { 84 $scale = 'h'; 85 } 86 } 87 if ($scale eq 'h') { 88 # scale by height 89 $n_w = int($i_h * $h / $i_h); 90 $n_h = $h; 91 } elsif ($scale eq 'w') { 92 # scale by width 93 $n_w = $w; 94 $n_h = int($i_h * $w / $i_w); 95 } 96 97 my ($data) = $img->scale(Height => $n_h, Width => $n_w) 98 or return $asset->error(MT->translate("Error scaling image: [_1]", $img->errstr)); 99 $fmgr->put_data($data, $thumbnail, 'upload') 100 or return $asset->error(MT->translate("Error creating thumbnail file: [_1]", $fmgr->errstr)); 101 return $thumbnail; 22 102 } 23 103 24 104 1; 105 106 __END__ 107 108 =head1 NAME 109 110 MT::Asset::Image 111 112 =head1 SYNOPSIS 113 114 use MT::Asset::Image; 115 116 # Example 117 118 =head1 DESCRIPTION 119 120 =head1 METHODS 121 122 =head2 MT::Asset::Image->class 123 124 Returns 'image', the identifier for this particular class of asset. 125 126 =head2 MT::Asset::Image->class_label 127 128 Returns the localized descriptive name for this type of asset. 129 130 =head2 MT::Asset::Image->extensions 131 132 Returns an arrayref of file extensions that are supported by this 133 package. 134 135 =head2 $asset->metadata 136 137 Returns a hashref of metadata values for this asset. 138 139 =head2 $asset->thumbnail_file(%param) 140 141 Creates or retrieves the file path to a thumbnail image appropriate for 142 the asset. If a thumbnail cannot be created, this routine will return 143 undef. 144 145 =head1 AUTHORS & COPYRIGHT 146 147 Please see the I<MT> manpage for author, copyright, and license information. 148 149 =cut branches/wheeljack/lib/MT/Entry.pm
r751 r752 178 178 my $entry = shift; 179 179 $entry->cache_property('trackback', sub { 180 MT::Trackback->load({ entry_id => $entry->id }); 180 if ($entry->id) { 181 return scalar MT::Trackback->load({ entry_id => $entry->id }); 182 } 181 183 }); 182 184 } branches/wheeljack/lib/MT/FileInfo.pm
r736 r752 14 14 'id' => 'integer not null auto_increment', 15 15 'blog_id' => 'integer not null', 16 'entry_id' => 'integer', 16 17 'url' => 'string(255)', 17 'file_path' => 'string(255)', 18 'file_name' => 'string(255)', 19 'file_ext' => 'string(20)', 20 'entry_id' => 'integer', 18 'file_path' => 'text', 21 19 'templatemap_id' => 'integer', 22 20 'template_id' => 'integer', … … 25 23 'startdate' => 'string(80)', 26 24 'virtual' => 'boolean', 27 'image_width' => 'integer',28 'image_height' => 'integer',29 25 }, 30 26 indexes => { … … 34 30 templatemap_id => 1, 35 31 url => 1, 36 file_path => 1,37 archive_type => 1,38 32 }, 39 audit => 1,40 33 datasource => 'fileinfo', 41 34 primary_key => 'id', branches/wheeljack/lib/MT/Image.pm
r717 r752 53 53 my $image = shift; 54 54 eval { require Image::Magick }; 55 return $image->error(MT->translate("Can't load Image::Magick: [_1]", $@)) 56 if $@; 55 if (my $err = $@) { 56 return $image->error(MT->translate("Can't load Image::Magick: [_1]", $err)); 57 } 57 58 1; 58 59 } … … 102 103 my $image = shift; 103 104 eval { require IPC::Run }; 104 return $image->error(MT->translate("Can't load IPC::Run: [_1]", $@)) 105 if $@; 105 if (my $err = $@) { 106 return $image->error(MT->translate("Can't load IPC::Run: [_1]", $err)); 107 } 106 108 my $pbm = $image->_find_pbm or return; 107 109 1; branches/wheeljack/lib/MT/Object.pm
r751 r752 342 342 sub cache_property { 343 343 my $obj = shift; 344 my ($key, $code) = @_; 345 return $obj->{__cache}{$key} if exists $obj->{__cache}{$key}; 346 return undef unless $code; 347 $obj->{__cache}{$key} = $code->(); 344 my $key = shift; 345 my $code = shift; 346 if (ref $key eq 'CODE') { 347 ($key, $code) = ($code, $key); 348 } 349 $key ||= (caller(1))[3]; 350 351 if (@_) { 352 $obj->{__cache}{$key} = $_[0]; 353 } else { 354 if ((!defined $obj->{__cache}{$key}) && $code) { 355 $obj->{__cache}{$key} = $code->($obj, @_); 356 } 357 } 358 return exists $obj->{__cache}{$key} ? $obj->{__cache}{$key} : undef; 348 359 } 349 360 branches/wheeljack/lib/MT/ObjectDriver/DBM.pm
r742 r752 657 657 $driver->run_callbacks($class . "::pre_update", $obj, $original); 658 658 } 659 my $class = ref $obj;660 659 delete $object_cache{$class}->{$id} if $id && exists $object_cache{$class}->{$id}; # invalidate the cache 661 660 $original->id($id); branches/wheeljack/lib/MT/Template/Context.pm
r717 r752 160 160 161 161 if ($cat_expr) { 162 my @cols = $cat_expr =~ m!/! ? qw(category_label_path label) : qw(label); 162 163 my %cats_used; 163 # sort in descending order by length164 if ($cat_expr =~ m!/!) {165 # add extra 'path' expression categories166 my @path_cats; 164 foreach my $col (@cols) { 165 my %cats_replaced; 166 @$cats = sort {length($b->$col) <=> length($a->$col)} @$cats; 167 167 168 foreach my $cat (@$cats) { 168 my $catp = $cat->category_label_path; 169 push @path_cats, { label => $catp, id => $cat->id, obj => $cat }; 170 } 171 @path_cats = sort {length($b->{label}) <=> length($a->{label})} @path_cats; 172 foreach (@path_cats) { 173 my $cat = $_->{obj}; 174 my $catp = $_->{label}; 175
