| | 142 | sub xsearch_tags { |
| | 143 | my ($ctx, $args, $cond) = @_; |
| | 144 | |
| | 145 | return '' unless defined $ctx->stash('xsearch_tags'); |
| | 146 | my $tags = $ctx->stash('xsearch_tags'); |
| | 147 | return '' unless scalar @$tags; |
| | 148 | |
| | 149 | my @res; |
| | 150 | my $builder = $ctx->stash('builder'); |
| | 151 | my $tokens = $ctx->stash('tokens'); |
| | 152 | foreach (@$tags) { |
| | 153 | local $ctx->{__stash}{'Tag'} = $_; |
| | 154 | local $ctx->{__stash}{tag_count} = undef; |
| | 155 | defined(my $out = $builder->build($ctx, $tokens, $cond)) |
| | 156 | or return $ctx->error($ctx->errstr); |
| | 157 | push @res, $out; |
| | 158 | } |
| | 159 | my $glue = $args->{glue} || ''; |
| | 160 | join $glue, @res; |
| | 161 | } |
| | 162 | |
| | 163 | sub xsearch_on_stash { |
| | 164 | my ($ctx, $val, $self) = @_; |
| | 165 | $ctx->stash('entry', $val); |
| | 166 | $ctx->{current_timestamp} = $val->created_on; |
| | 167 | $ctx->{modification_timestamp} = $val->modified_on; |
| | 168 | $ctx->stash('xsearch_tags', $self->{xsearch_tags}); |
| | 169 | } |
| | 170 | |
| | 171 | sub xsearch_on_execute { |
| | 172 | my ($args, $self) = @_; |
| | 173 | |
| | 174 | my $blog_id = $args->{blog_id} or MT->error('Blog ID is required.'); |
| | 175 | my $delimiter = $args->{delimiter} || ','; |
| | 176 | my $sort_by = $args->{sort_by} || 'created_on'; |
| | 177 | my $sort_order = $args->{sort_order} || 'descend'; |
| | 178 | my $lastn = $args->{lastn} || 0; |
| | 179 | |
| | 180 | my $tags = $args->{search} or MT->error('Search string is required.'); |
| | 181 | my @tag_names = MT::Tag->split($delimiter, $tags) |
| | 182 | or return []; |
| | 183 | my $tag_count = scalar @tag_names; |
| | 184 | |
| | 185 | my @tags = MT::Tag->load_by_datasource(MT::Entry->datasource, { |
| | 186 | is_private => 0, |
| | 187 | $blog_id ? (blog_id => $blog_id) : (), |
| | 188 | name => \@tag_names, |
| | 189 | }); |
| | 190 | $self->{xsearch_tags} = \@tags; |
| | 191 | my @tag_ids = map { $_->id } @tags; |
| | 192 | |
| | 193 | my @eids; |
| | 194 | if (MT::Object->driver->can('count_group_by')) { |
| | 195 | my $iter = MT::ObjectTag->count_group_by({ |
| | 196 | blog_id => $blog_id, |
| | 197 | tag_id => \@tag_ids, |
| | 198 | object_datasource => MT::Entry->datasource, |
| | 199 | }, { |
| | 200 | group => ['object_id'], |
| | 201 | }); |
| | 202 | while (my ($count, $object_id) = $iter->()) { |
| | 203 | push @eids, $object_id if $count == $tag_count; |
| | 204 | } |
| | 205 | } else { |
| | 206 | my $iter = MT::ObjectTag->load_iter({ |
| | 207 | blog_id => $blog_id, |
| | 208 | tag_id => \@tag_ids, |
| | 209 | object_datasource => MT::Entry->datasource, |
| | 210 | }); |
| | 211 | my %count; |
| | 212 | while (my $otag = $iter->()) { |
| | 213 | $count{$otag->object_id}++; |
| | 214 | } |
| | 215 | foreach (keys %count) { |
| | 216 | push @eids, $_ if $count{$_} == $tag_count; |
| | 217 | } |
| | 218 | } |
| | 219 | return [] unless scalar @eids; |
| | 220 | |
| | 221 | my @entries; |
| | 222 | map { push @entries, MT::Entry->load($_) } @eids; |
| | 223 | @entries = $sort_order eq 'descend' ? |
| | 224 | sort { $b->created_on <=> $a->created_on } @entries : |
| | 225 | sort { $a->created_on <=> $b->created_on } @entries; |
| | 226 | splice(@entries, $lastn) if $lastn && (scalar @entries > $lastn); |
| | 227 | |
| | 228 | \@entries; |
| | 229 | } |
| | 230 | |