1<?php
2// search/st_author.php -- HotCRP helper class for searching for papers
3// Copyright (c) 2006-2018 Eddie Kohler; see LICENSE.
4
5class Author_SearchTerm extends SearchTerm {
6    private $csm;
7    private $regex;
8
9    function __construct($countexpr, $contacts, $match, $quoted) {
10        parent::__construct("au");
11        $this->csm = new ContactCountMatcher($countexpr, $contacts);
12        if (!$contacts && $match)
13            $this->regex = Text::star_text_pregexes($match, $quoted);
14    }
15    static function parse($word, SearchWord $sword, PaperSearch $srch) {
16        $count = ">0";
17        if (preg_match('/\A(.*?)(?::|\A|(?=[^\d]))((?:[=!<>]=?|≠|≤|≥|)\d+)\z/s', $word, $m)) {
18            $word = $m[1];
19            $count = $m[2];
20        }
21        $cids = null;
22        if ($sword->kwexplicit && !$sword->quoted) {
23            if ($word === "any")
24                $word = null;
25            else if ($word === "none" && $count === ">0") {
26                $word = null;
27                $count = "=0";
28            } else if (trim($word) !== "")
29                $cids = $srch->matching_special_contacts($word, false, false);
30        }
31        return new Author_SearchTerm($count, $cids, $word, $sword->quoted);
32    }
33    function trivial_rights(Contact $user, PaperSearch $srch) {
34        return $this->csm->has_sole_contact($user->contactId)
35            && !$this->csm->test(0);
36    }
37    function sqlexpr(SearchQueryInfo $sqi) {
38        if ($this->csm->has_contacts() && !$this->csm->test(0)) {
39            return "exists (select * from PaperConflict where PaperConflict.paperId=Paper.paperId and " . $this->csm->contact_match_sql("contactId") . " and conflictType>=" . CONFLICT_AUTHOR . ")";
40        } else if ($this->csm->has_contacts()) {
41            $sqi->add_allConflictType_column();
42            return "true";
43        } else {
44            $sqi->add_column("authorInformation", "Paper.authorInformation");
45            return $this->csm->test(0) ? "true" : "Paper.authorInformation!=''";
46        }
47    }
48    function exec(PaperInfo $row, PaperSearch $srch) {
49        $n = 0;
50        $can_view = $srch->user->allow_view_authors($row);
51        if ($this->csm->has_contacts()) {
52            foreach ($this->csm->contact_set() as $cid) {
53                if (($cid === $srch->cid || $can_view)
54                    && $row->has_author($cid))
55                    ++$n;
56            }
57        } else if ($can_view) {
58            foreach ($row->author_list() as $au) {
59                if ($this->regex) {
60                    $text = $au->name_email_aff_text();
61                    if (!Text::match_pregexes($this->regex, $text,
62                                              UnicodeHelper::deaccent($text)))
63                        continue;
64                }
65                ++$n;
66            }
67        }
68        return $this->csm->test($n);
69    }
70    function extract_metadata($top, PaperSearch $srch) {
71        parent::extract_metadata($top, $srch);
72        if ($this->regex)
73            $srch->regex["au"][] = $this->regex;
74    }
75}
76
77class AuthorMatch_SearchTerm extends SearchTerm {
78    private $field;
79    private $matcher;
80
81    function __construct($type, $matcher) {
82        parent::__construct($type);
83        $this->field = TextMatch_SearchTerm::$map[substr($type, 0, 2)];
84        $this->matcher = $matcher;
85    }
86    static function parse($word, SearchWord $sword) {
87        $type = $sword->kwdef->name;
88        if ($word === "any" && $sword->kwexplicit && !$sword->quoted)
89            return new TextMatch_SearchTerm(substr($type, 0, 2), true, false);
90        if (($matcher = AuthorMatcher::make_string_guess($word)))
91            return new AuthorMatch_SearchTerm($type, $matcher);
92        else
93            return new False_SearchTerm;
94    }
95
96    function sqlexpr(SearchQueryInfo $sqi) {
97        $sqi->add_column($this->field, "Paper.{$this->field}");
98        return "Paper.{$this->field}!=''";
99    }
100    function exec(PaperInfo $row, PaperSearch $srch) {
101        $field = $this->field;
102        if ($row->$field === ""
103            || !$srch->user->allow_view_authors($row))
104            return false;
105        if (!$row->field_match_pregexes($this->matcher->general_pregexes(), $field))
106            return false;
107        $l = $this->type === "aumatch" ? $row->author_list() : $row->collaborator_list();
108        foreach ($l as $au)
109            if ($this->matcher->test($au, true))
110                return true;
111        return false;
112    }
113    function extract_metadata($top, PaperSearch $srch) {
114        parent::extract_metadata($top, $srch);
115        $srch->regex[substr($this->type, 0, 2)][] = $this->matcher->general_pregexes();
116    }
117}
118