⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.pm

📁 网页留言本,比一般的留言簿管用
💻 PM
📖 第 1 页 / 共 2 页
字号:
    if ($app->{searchparam}{CommentSearchCutoff} &&        $app->{searchparam}{CommentSearchCutoff} != 9999999) {        my @ago = MT::Util::offset_time_list(time - 3600 * 24 *                  $app->{searchparam}{CommentSearchCutoff});        my $ago = sprintf "%04d%02d%02d%02d%02d%02d",            $ago[5]+1900, $ago[4]+1, @ago[3,2,1,0];        $args{'join'}->[2]{created_on} = [ $ago ];        $args{'join'}->[3]{range} = { created_on => 1 };    } elsif ($app->{searchparam}{MaxResults} &&             $app->{searchparam}{MaxResults} != 9999999) {        $args{limit} = $app->{searchparam}{MaxResults};    }    my $iter = MT::Entry->load_iter({ status => MT::Entry::RELEASE() }, \%args);    my %blogs;    my $include = $app->{searchparam}{IncludeBlogs};    while (my $entry = $iter->()) {        next unless $include->{ $entry->blog_id };        my $blog = $blogs{ $entry->blog_id } || MT::Blog->load($entry->blog_id);        $app->_store_hit_data($blog, $entry);    }    1;}sub _set_form_elements {    my($app, $tmpl) = @_;    ## Fill in user-defined template with proper form settings.    if ($app->{searchparam}{Type} eq 'newcomments') {        if ($app->{searchparam}{CommentSearchCutoff}) {            $tmpl =~ s/(<select name="CommentSearchCutoff">.*<option value="$app->{searchparam}{CommentSearchCutoff}")/$1 selected="selected"/si;        } else {            $tmpl =~ s/(<select name="CommentSearchCutoff">.*<option value="9999999")/$1 selected="selected"/si;        }    } else {        if ($app->{searchparam}{SearchCutoff}) {            $tmpl =~ s/(<select name="SearchCutoff">.*<option value="$app->{searchparam}{SearchCutoff}")/$1 selected="selected"/si;        } else {            $tmpl =~ s/(<select name="SearchCutoff">.*<option value="9999999")/$1 selected="selected"/si;        }        if ($app->{searchparam}{CaseSearch}) {            $tmpl =~ s/(<input type="checkbox"[^>]+name="CaseSearch")/$1 checked="checked"/g;        }        if ($app->{searchparam}{RegexSearch}) {            $tmpl =~ s/(<input type="checkbox"[^>]+name="RegexSearch")/$1 checked="checked"/g;        }        $tmpl =~ s/(<input type="radio"[^>]+?$app->{searchparam}{SearchElement}\")/$1 checked="checked"/g;        for my $type (qw( IncludeBlogs ExcludeBlogs )) {            for my $blog_id (keys %{ $app->{searchparam}{$type} }) {                $tmpl =~ s/(<input type="checkbox"[^>]+?$type" value="$blog_id")/$1 checked="checked"/g;    #"            }        }    }    if ($app->{searchparam}{MaxResults}) {        $tmpl =~ s/(<select name="MaxResults">.*<option value="$app->{searchparam}{MaxResults}")/$1 selected="selected"/si;    } else {        $tmpl =~ s/(<select name="MaxResults">.*<option value="9999999")/$1 selected="selected"/si;    }    $tmpl;}sub is_a_match {     my($app, $txt) = @_;    if ($app->{searchparam}{RegexSearch}) {        return unless $txt =~ m/$app->{search_string}/;    } else {        my $casemod = $app->{searchparam}{CaseSearch} ? '' : '(?i)';        for (@{$app->{searchparam}{search_keys}{AND}}) {            return unless $txt =~ /$casemod$_/;	}	for (@{$app->{searchparam}{search_keys}{NOT}}) {            return if $txt =~ /$casemod$_/;        }    }    1;}sub query_parse {    my $app = shift;    return unless $app->{search_string};    local $_ = $app->{search_string};    s/^\s//;            # Remove leading whitespace    s/\s$//;            # Remove trailing whitespace    s/\s+AND\s+/ /g;    # Remove AND because it's implied    s/\s{2,}/ /g;       # Remove contiguous spaces    my @search_keys;    my @tokens = split;    while (my $atom = shift @tokens) {        my($type);        if ($atom eq 'NOT' || $atom eq 'AND') {            $type = $atom;            $atom = shift @tokens;            $atom = find_phrase($atom, \@tokens) if $atom =~ /^\"/;        } elsif ($atom eq 'OR') {            $atom = shift @tokens;            $atom = find_phrase($atom, \@tokens) if $atom =~ /^\"/;            ## OR new atom with last atom            $search_keys[-1]{atom} =                '(?:' . $search_keys[-1]{atom} .'|' . quotemeta($atom) . ')';            next;        } elsif ($atom =~ /^-(.*)/) {            $type = 'NOT';            $atom = $1;            $atom = find_phrase($atom, \@tokens) if $atom =~ /^\"/;        } else {            $type = 'AND';            $atom = find_phrase($atom, \@tokens) if $atom =~ /^\"/;        }        push @search_keys, { atom => quotemeta($atom),                             type => $type };    }    $app->{searchparam}{search_keys} = \@search_keys;    $app->query_optimize;}sub find_phrase {    my($atom, $tokenref) = @_;    while (my $next = shift @$tokenref) {	$atom = $atom . ' ' . $next;        last if $atom =~ /\"$/;    }    $atom =~ s/^"(.*)"$/$1/;    $atom;}sub query_optimize {    my $app = shift;    ## Sort keys longest to shortest for search efficiency.    $app->{searchparam}{search_keys} = [        reverse sort { length($a->{atom}) <=> length($b->{atom}) }        @{ $app->{searchparam}{search_keys} }    ];        ## Sort keys by contents. Any ORs immediately get a lower priority.    my %terms;    for my $key (@{ $app->{searchparam}{search_keys} }) {        if ($key->{atom} =~ /\(.*\|.*\)/) {            push(@{ $terms{$key->{type}}{low} }, $key);        } else {            push(@{ $terms{$key->{type}}{high} }, $key);        }    }    ## Final priority: AND long, AND short, AND with OR (long/short),    ## NOT long/short    ##  This should give us the most efficient search in that it is    ##  searching for the harder-to-match keys first.    my %regex;    for my $type (qw( AND NOT )) {        for my $pri (qw( high low )) {            for my $obj (@{ $terms{$type}{$pri} }) {                push(@{ $regex{$type} }, $obj->{atom});            }        }    }    $app->{searchparam}{search_keys} = \%regex;}sub _search_hit {    my($app, $entry) = @_;    my @text_elements;    if ($app->{searchparam}{SearchElement} ne 'comments') {        @text_elements = ($entry->title, $entry->text, $entry->text_more,                          $entry->keywords);    }    if ($app->{searchparam}{SearchElement} ne 'entries') {        my $comments = $entry->comments;        for my $comment (@$comments) {            push @text_elements, $comment->text, $comment->author,                                 $comment->url;        }    }    return 1 if $app->is_a_match(join("\n", map $_ || '', @text_elements));}sub _store_hit_data {    my $app = shift;    my($blog, $entry, $banner_seen) = @_;    my %result_data = (blog => $blog);    ## Need to create entry excerpt here, because we can't rely on    ## the user's per-blog setting.    unless ($entry->excerpt) {        $entry->excerpt($entry->get_excerpt($app->{searchparam}{ExcerptWords}));    }    $result_data{entry} = $entry;    if ($app->{searchparam}{Type} eq 'newcomments') {        push @{ $app->{results} }, \%result_data;    } else {        push(@{ $app->{results}{ $blog->name } }, \%result_data);    }}package MT::App::Search::Context;use MT::Template::Context;@MT::App::Search::Context::ISA = qw( MT::Template::Context );sub init {    my $ctx = shift;    $ctx->SUPER::init(@_);    $ctx->register_handler(EntryEditLink => \&_hdlr_entry_edit_link);    $ctx->register_handler(SearchResults => [ \&_hdlr_results, 1 ]);    $ctx->register_handler(SearchResultCount => \&_hdlr_result_count);    $ctx->register_handler(SearchString => \&_hdlr_search_string);    $ctx->register_handler(NoSearchResults =>        [ \&MT::Template::Context::_hdlr_pass_tokens, 1 ]);    $ctx->register_handler(NoSearch =>        [ \&MT::Template::Context::_hdlr_pass_tokens, 1 ]);    $ctx->register_handler(BlogResultHeader =>        [ \&MT::Template::Context::_hdlr_pass_tokens, 1 ]);    $ctx->register_handler(BlogResultFooter =>        [ \&MT::Template::Context::_hdlr_pass_tokens, 1 ]);    $ctx;}sub _hdlr_search_string { $_[0]->stash('search_string') || '' }sub _hdlr_result_count {    my $results = $_[0]->stash('results');    $results && ref($results) eq 'ARRAY' ? scalar @$results : 0;}sub _hdlr_results {    my($ctx, $args) = @_;    ## If there are no results, return the empty string, knowing    ## that the handler for <MTNoSearchResults> will fill in the    ## no results message.    my $results = $ctx->stash('results') or return '';    my $output = '';    my $build = $ctx->stash('builder');    my $tokens = $ctx->stash('tokens');    for my $res (@$results) {        $ctx->stash('entry', $res->{entry});        local $ctx->{__stash}{blog} = $res->{blog};        $ctx->stash('result', $res);        local $ctx->{current_timestamp} = $res->{entry}->created_on;        defined(my $out = $build->build($ctx, $tokens,            { BlogResultHeader => $res->{blogheader} ? 1 : 0 }            )) or return $ctx->error( $build->errstr );        $output .= $out;    }    $output;}sub _hdlr_entry_edit_link {       my($ctx, $args) = @_;    my $user = $ctx->stash('user') or return '';    my $entry = $ctx->stash('entry')        or return $ctx->error(MT->translate(            'You used an [_1] tag outside of the proper context.',            '<$MTEntryEditLink$>' ));    my $blog_id = $entry->blog_id;    my $cfg = MT::ConfigMgr->instance;    my $url = $cfg->AdminCGIPath || $cfg->CGIPath;    $url .= '/' unless $url =~ m!/$!;    require MT::Permission;    my $perms = MT::Permission->load({ author_id => $user->id,                                       blog_id => $blog_id });    return '' unless $perms && $perms->can_edit_entry($entry, $user);    sprintf      q([<a href="%s%s?__mode=view&_type=entry&id=%d&blog_id=%d">Edit</a>]),      $url, $cfg->AdminScript, $entry->id, $blog_id;}1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -