# # EntryImages # 2006/08/05 1.00 First Version # 2006/08/22 1.01 Add "this_entry" attribute # 2006/09/12 1.02 Add random function # 2007/03/21 1.03 Add "include_cats"/"exclude_cats" attribute # 2007/05/24 1.04 Add tag function # # Copyright(c) 2006 By H.Fujimoto # package MT::Plugin::EntryImages; use strict; use MT; use base qw(MT::Plugin); use MT::Template::Context; use MT::Plugin; use MT::Entry; use MT::ObjectTag; # show plugin information to main menu my $plugin = MT::Plugin::EntryImages->new({ name => 'EntryImages', version => '1.04', author_name => 'Hajime Fujimoto', author_link => 'http://www.h-fj.com/blog/', description => 'エントリー内のimgタグの情報をリストアップします', blog_config_template => \&_blog_config_template, system_config_template => \&_system_config_template, settings => new MT::PluginSettings([ ['ei_exclude', { Default => '' }], ['ei_include', { Default => '' }], ]), }); MT->add_plugin($plugin); # add tag MT::Template::Context->add_container_tag(EntriesHaveImages => \&entries_have_images); MT::Template::Context->add_container_tag(EntryImages => \&entry_images); MT::Template::Context->add_tag(EntriesHaveImagesCount => \&entries_have_images_count); MT::Template::Context->add_tag(EntryImageTotalCount => \&entry_image_total_count); MT::Template::Context->add_tag(EntryImageCount => \&entry_image_count); MT::Template::Context->add_tag(EntryImageSrc => \&entry_image_src); MT::Template::Context->add_tag(EntryImageWidth => \&entry_image_width); MT::Template::Context->add_tag(EntryImageHeight => \&entry_image_height); MT::Template::Context->add_tag(EntryImageAlt => \&entry_image_alt); MT::Template::Context->add_tag(EntryImageTitle => \&entry_image_title); MT::Template::Context->add_tag(EntryImageID => \&entry_image_id); MT::Template::Context->add_tag(EntryImageClass => \&entry_image_class); MT::Template::Context->add_container_tag(EntryImageEntry => \&entry_image_entry); MT::Template::Context->add_conditional_tag(EntryImageHeader => \&entry_image_header); MT::Template::Context->add_conditional_tag(EntryImageFooter => \&entry_image_footer); MT::Template::Context->add_conditional_tag(EntryImageRowHeader => \&entry_image_row_header); MT::Template::Context->add_conditional_tag(EntryImageRowFooter => \&entry_image_row_footer); MT::Template::Context->add_conditional_tag(EntryImageIfEmptyCell => \&entry_image_if_empty_cell); MT::Template::Context->add_conditional_tag(EntriesIfHaveImages => \&entries_if_have_images); MT::Template::Context->add_conditional_tag(EntryIfHaveImages => \&entry_if_have_images); # entry_images main sub entries_have_images { my ($ctx, $args, $cond) = @_; my $tokens = $ctx->stash('tokens'); my $builder = $ctx->stash('builder'); my @data; my $res = ''; &_load_entries_and_images($ctx, $args, \@data); my $ctr = 0; my ($last_day, $next_day) = ('00000000') x 2; for my $a_data (@data) { my $entry = $a_data->{entry}; my $images = $a_data->{images}; local $ctx->{__stash}{entry} = $entry; local $ctx->{current_timestamp} = $entry->created_on; local $ctx->{modification_timestamp} = $entry->modified_on; $ctx->stash('images', $images); $ctx->stash('image_count', scalar(@$images)); my $this_day = substr $entry->created_on, 0, 8; my $next_day = $this_day; my $footer = 0; if (defined $data[$ctr + 1]) { $next_day = substr($data[$ctr + 1]->{entry}->created_on, 0, 8); $footer = $this_day ne $next_day; } else { $footer++ } defined(my $out = $builder->build($ctx, $tokens, { %$cond, DateHeader => ($this_day ne $last_day), DateFooter => $footer, EntriesHeader => !$ctr, EntriesFooter => !defined $data[$ctr + 1] })) or return $ctx->error($builder->errstr); $res .= $out; $ctr++; $last_day = $this_day; } $ctx->stash('images', undef); $res; } sub entry_images { my ($ctx, $args, $cond) = @_; my $tokens = $ctx->stash('tokens'); my $builder = $ctx->stash('builder'); my $columns; my ($mode, $img_lastn); my @data; my $res = ''; # get attribute $columns = $args->{'columns'} or $columns = 0; $img_lastn = $args->{'img_lastn'} or $img_lastn = 0; # load entries and images my $is_entry; if (defined($ctx->stash('images'))) { push @data, { entry => $ctx->stash('entry'), images => $ctx->stash('images') }; $is_entry = 1; } else { &_load_entries_and_images($ctx, $args, \@data); $is_entry = 0; } # random images if ($args->{sort_order} eq 'random') { # extract data my @tmpdata; my $count; for my $a_data (@data) { my $entry = $a_data->{entry}; my $images = $a_data->{images}; for my $a_image (@$images) { push @tmpdata, { entry => $entry, images => [$a_image] }; $count++; } } # random data srand(time | $$); my $random_lastn = $args->{random_lastn} || 0; $random_lastn = $count if $count < $random_lastn; my @tmpdata2; my @is_exist; for (my $i = 0; $i < $random_lastn; $i++) { my $num; while () { $num = int(rand($count)); last if ($is_exist[$num] == 0); } $is_exist[$num] = 1; if ($is_entry) { push @tmpdata2, $tmpdata[$num]->{images}->[0]; } else { push @tmpdata2, $tmpdata[$num]; } } if ($is_entry) { $data[0] = { entry => $ctx->stash('entry'), images => \@tmpdata2 }; } else { @data = @tmpdata2; } } # out images my $count = 0; my $total_count = 0; my $total_data = scalar @data; for my $a_data (@data) { my $entry = $a_data->{entry}; my $images = $a_data->{images}; my $img_count = scalar @$images; my $loop_count = ($img_count > $img_lastn && $img_lastn) ? $img_lastn : $img_count; for (my $i = 0; $i < $loop_count; $i++) { local $ctx->{__stash}{entry} = $entry; local $ctx->{current_timestamp} = $entry->created_on; local $ctx->{modification_timestamp} = $entry->modified_on; $ctx->stash('image', $images->[$i]); $ctx->stash('image_header', ($total_count == 0 && $i == 0) ? 1 : 0); $ctx->stash('image_footer', 0); if ($total_count == $total_data - 1 && $i == $loop_count - 1) { if ($columns) { $ctx->stash('image_footer', 1) if ($count % $columns == $columns - 1); } else { $ctx->stash('image_footer', 1); } } $ctx->stash('row_header', ($columns && $count % $columns == 0) ? 1 : 0); $ctx->stash('row_footer', ($columns && $count % $columns == $columns - 1) ? 1 : 0); $ctx->stash('empty_cell', 0); defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $res .= $out; $count++; } $total_count++; } # out empty cells if ($columns) { for ( ; $count % $columns != 0; $count++) { $ctx->stash('empty_cell', 1); $ctx->stash('row_header', ($count % $columns == 0) ? 1 : 0); $ctx->stash('row_footer', ($count % $columns == $columns - 1) ? 1 : 0); $ctx->stash('image_header', ($count % $columns == 0) ? 1 : 0); $ctx->stash('image_footer', ($count % $columns == $columns - 1) ? 1 : 0); defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $res .= $out; } } $ctx->stash('empty_cell', undef); $res; } sub entries_have_images_count { my ($ctx, $args) = @_; my @data; &_load_entries_and_images($ctx, $args, \@data); scalar @data; } sub entry_image_count { my ($ctx, $args) = @_; if ($args->{this_entry}) { my @data; &_load_entries_and_images($ctx, $args, \@data); my $images = $data[0]->{images}; return scalar(@$images); } else { return $ctx->stash('image_count'); } } sub entry_image_total_count { my ($ctx, $args) = @_; my $count = 0; my @data; &_load_entries_and_images($ctx, $args, \@data); for my $a_data (@data) { my $images = $a_data->{images}; $count += scalar(@$images); } $count; } sub entry_image_src { my ($ctx, $args) = @_; my $regex = $args->{regex} || ''; my $src = _get_attr($ctx, 'src\s*?=\s*?\"(.*?)\"'); if ($regex) { eval "\$src =~ $regex"; } $src; } sub entry_image_width { my ($ctx, $args) = @_; my $default = $args->{default} || 0; return $ctx->error('default size must be plus value') if ($default < 0); my $cellsize = $args->{cell_size} || '0,0'; my @cellxy = split ",", $cellsize; return $ctx->error('cell size must be plus value') if ($cellxy[0] < 0 || $cellxy[1] < 0); my $width = _get_attr($ctx, 'width\s*?=\s*?\"(.*?)\"'); my $height = _get_attr($ctx, 'height\s*?=\s*?\"(.*?)\"'); if ($cellxy[0] == 0 || $cellxy[1] == 0) { if ($width == 0 && $default) { return $default; } else { return $width; } } elsif ($width == 0 || $height == 0 || $width / $height > $cellxy[0] / $cellxy[1]) { return $cellxy[0]; } else { return int($width * $cellxy[1] / $height); } } sub entry_image_height { my ($ctx, $args) = @_; my $default = $args->{default} || 0; return $ctx->error('default size must be plus value') if ($default < 0); my $cellsize = $args->{cell_size} || '0,0'; my @cellxy = split ",", $cellsize; return $ctx->error('cell size must be plus value') if ($cellxy[0] < 0 || $cellxy[1] < 0); my $width = _get_attr($ctx, 'width\s*?=\s*?\"(.*?)\"'); my $height = _get_attr($ctx, 'height\s*?=\s*?\"(.*?)\"'); if ($cellxy[0] == 0 || $cellxy[1] == 0) { if ($height == 0 && $default) { return $default; } else { return $height; } } elsif ($width == 0 || $height == 0 || $width / $height < $cellxy[0] / $cellxy[1]) { return $cellxy[1]; } else { return int($height * $cellxy[0] / $width); } } sub entry_image_alt { my ($ctx, $args) = @_; _get_attr($ctx, 'alt\s*?=\s*?\"(.*?)\"'); } sub entry_image_title { my ($ctx, $args) = @_; _get_attr($ctx, 'title\s*?=\s*?\"(.*?)\"'); } sub entry_image_id { my ($ctx, $args) = @_; _get_attr($ctx, 'id\s*?=\s*?\"(.*?)\"'); } sub entry_image_class { my ($ctx, $args) = @_; _get_attr($ctx, 'class\s*?=\s*?\"(.*?)\"'); } sub entry_image_entry { my ($ctx, $args, $cond) = @_; my $entry = $ctx->stash('entry'); local $ctx->{current_timestamp} = $entry->created_on; $ctx->stash('builder')->build($ctx, $ctx->stash('tokens'), $cond); } sub entry_image_header { my ($ctx, $args, $cond) = @_; $ctx->stash('image_header'); } sub entry_image_footer { my ($ctx, $args, $cond) = @_; $ctx->stash('image_footer'); } sub entry_image_row_header { my ($ctx, $args, $cond) = @_; $ctx->stash('row_header'); } sub entry_image_row_footer { my ($ctx, $args, $cond) = @_; $ctx->stash('row_footer'); } sub entry_image_if_empty_cell { my ($ctx, $args, $cond) = @_; $ctx->stash('empty_cell'); } sub entries_if_have_images { my ($ctx, $args) = @_; my @data; local $args->{'img_lastn'} = 1; &_load_entries_and_images($ctx, $args, \@data); scalar @data; } sub entry_if_have_images { my ($ctx, $args) = @_; $args->{this_entry} = 1; return &entry_image_count($ctx, $args); } sub _load_entries_and_images { my ($ctx, $args, $data) = @_; my ($lastn, $img_lastn, $limit_per_entry, $force); my ($img_sort_order, $sort_order); my ($category, $date_start, $date_end); my (%terms, %args); return if ($args->{'use_cache'} == 1); @$data = (); my $blog = $ctx->stash('blog'); # get attributes $lastn = $args->{'lastn'} or $lastn = 0; $img_lastn = $args->{'img_lastn'} or $img_lastn = 0; $limit_per_entry = $args->{'limit_per_entry'} or $limit_per_entry = 0; $force = $args->{'force'} or $force = 0; $sort_order = $args->{'sort_order'}; if ($sort_order ne 'ascend' && $sort_order ne 'descend') { $sort_order = 'descend'; } $img_sort_order = $args->{'img_sort_order'}; if ($img_sort_order ne 'ascend' && $img_sort_order ne 'descend') { $img_sort_order = 'descend'; } my (@in_cats, @ex_cats); if ($args->{'include_cats'}) { for my $catname (split '\|', $args->{'include_cats'}) { my $cat = MT::Category->load({ label => $catname }); push @in_cats, $cat; } } if ($args->{'exclude_cats'}) { for my $catname (split '\|', $args->{'exclude_cats'}) { my $cat = MT::Category->load({ label => $catname }); push @ex_cats, $cat; } } my (@in_or_tags, @in_and_tags, @ex_or_tags, @ex_and_tags); if ($args->{'include_or_tags'}) { @in_or_tags = split '\|', $args->{'include_or_tags'}; } if ($args->{'exclude_or_tags'}) { @ex_or_tags = split '\|', $args->{'exclude_or_tags'}; } if ($args->{'include_and_tags'}) { @in_and_tags = split '\|', $args->{'include_and_tags'}; } if ($args->{'exclude_and_tags'}) { @ex_and_tags = split '\|', $args->{'exclude_and_tags'}; } if (@in_or_tags || @in_and_tags || @ex_or_tags || @ex_and_tags) { local $ctx->{__stash}{tag_max_count} = undef; local $ctx->{__stash}{tag_min_count} = undef; } # get setting my $exclude_urls_str = $plugin->get_config_value('ei_exclude', 'blog:' . $blog->id) || ''; my @exclude_urls = split /\r?\n/, $exclude_urls_str; my $include_urls_str = $plugin->get_config_value('ei_include', 'blog:' . $blog->id) || ''; my @include_urls = split /\r?\n/, $include_urls_str; # get template context $category = $ctx->stash('archive_category') || $ctx->stash('category'); $date_start = $ctx->{'current_timestamp'}; $date_end = $ctx->{'current_timestamp_end'}; # load entries $terms{blog_id} = $ctx->stash('blog_id'); $terms{status} = MT::Entry::RELEASE(); if ($args->{this_entry}) { $terms{id} = $ctx->stash('entry')->id; } else { $args{sort} = 'created_on'; $args{direction} = $sort_order; if (!$force) { if ($date_start && $date_end) { $args{range} = { created_on => 1 }; $terms{created_on} = [ $date_start, $date_end ]; } elsif ($category) { $args{join} = [ 'MT::Placement', 'entry_id', { category_id => $category->id } ]; } } } my $iter = MT::Entry->load_iter(\%terms, \%args); # loop each entry and search image my $count = 0; my $entry_count = 0; while (my $entry = $iter->()) { if (@in_cats) { my $is_skip = 1; for my $cat (@in_cats) { if ($entry->is_in_category($cat)) { $is_skip = 0; last; } } next if ($is_skip); } if (@ex_cats) { my $is_skip = 0; for my $cat (@ex_cats) { if ($entry->is_in_category($cat)) { $is_skip = 1; last; } } next if ($is_skip); } if (@in_or_tags || @in_and_tags || @ex_or_tags || @ex_and_tags) { my $iter = MT::Tag->load_iter(undef, { 'sort' => 'name', join => ['MT::ObjectTag', 'tag_id', { object_id => $entry->id, blog_id => $entry->blog_id, object_datasource => MT::Entry->datasource }, { unique => 1 } ]}); my @tags; while (my $tag = $iter->()) { next if $tag->is_private; push @tags, $tag->name; } if (@in_or_tags) { next if (!&_check_or_tags(\@tags, \@in_or_tags)); } if (@in_and_tags) { next if (!&_check_and_tags(\@tags, \@in_and_tags)); } if (@ex_or_tags) { next if (&_check_or_tags(\@tags, \@ex_or_tags)); } if (@ex_and_tags) { next if (&_check_and_tags(\@tags, \@ex_and_tags)); } } my @images = (); my $count_per_entry = 0; my $text = $entry->text . $entry->text_more; for ($text =~ /<\s*?img(.*?)>/sg) { my $img = $_; my $img_src = ''; if ($img =~ /src\s*?=\s*?\"(.*?)\"/) { $img_src = $1; } my $is_exclude = 0; if ($img_src) { for my $exclude_url (@exclude_urls) { if ($exclude_url && $exclude_url !~ /^#/) { if ($exclude_url =~ /^(\/.*)$/) { my $tmp; eval "\$tmp = (\$img_src =~ $1)"; if ($tmp) { $is_exclude = 1; last; } } elsif ($img_src eq $exclude_url) { $is_exclude = 1; last; } } } for my $include_url (@include_urls) { if ($include_url && $include_url !~ /^#/) { if ($include_url =~ /^(\/.*)$/) { my $tmp; eval "\$tmp = (\$img_src =~ $1)"; if ($tmp) { $is_exclude = 0; last; } } elsif ($img_src eq $include_url) { $is_exclude = 0; last; } } } } else { $is_exclude = 1; } if (!$is_exclude) { push @images, $img; $count++; $count_per_entry++; last if ($count == $img_lastn || $count_per_entry == $limit_per_entry); } } if (@images) { push @$data, { entry => $entry, images => \@images }; $entry_count++; } last if (($count == $img_lastn && $img_lastn != 0) || ($entry_count == $lastn && $lastn != 0)); } # if this entry and no images push @$data, { entry => $ctx->stash('entry'), images => [] } if ($args->{this_entry} && !@$data); # sort images if ($img_sort_order eq 'ascend') { @$data = sort { $a->{entry}->created_on <=> $b->{entry}->created_on } @$data; } elsif ($img_sort_order eq 'descend') { @$data = sort { $b->{entry}->created_on <=> $a->{entry}->created_on } @$data; } } sub _get_attr { my ($ctx, $pattern) = @_; my $image = $ctx->stash('image'); if ($image =~ /$pattern/s) { return $1; } else { return ''; } } sub _check_or_tags { my ($tags, $or_tags) = @_; for my $or_tag (@$or_tags) { for my $tag (@$tags) { return 1 if ($or_tag eq $tag); } } return 0; } sub _check_and_tags { my ($tags, $and_tags) = @_; for my $and_tag (@$and_tags) { my $is_exist = 0; for my $tag (@$tags) { if ($and_tag eq $tag) { $is_exist = 1; last; } } return 0 if (!$is_exist); } return 1; } # blog config template sub _blog_config_template { return <
除外するイメージのURL
含めるイメージのURL
HERE } # system config template sub _system_config_template { my $admin_script = MT::ConfigMgr->instance->AdminScript; my ($setting_link, @setting_links, @blogs); my $app = MT->instance; @blogs = MT::Blog->load; foreach my $blog (@blogs) { push @setting_links, '「'. $blog->name . '」の「プラグイン」タブを開く'; } $setting_link = join "
\n", @setting_links; return <

設定は、以下のリンクをクリックして、個々のBlogの設定ページの「プラグイン」タブで行ってください。

$setting_link

HERE } 1;