1<?php
2// listactions/la_get_sub.php -- HotCRP helper classes for list actions
3// Copyright (c) 2006-2018 Eddie Kohler; see LICENSE.
4
5class Get_ListAction extends ListAction {
6    static function render(PaperList $pl) {
7        $actions = array_values($pl->displayable_list_actions("get/"));
8        foreach ($pl->user->user_option_list() as $o)
9            if ($pl->user->can_view_some_paper_option($o)
10                && $o->is_document()
11                && $pl->has($o->field_key()))
12                $actions[] = GetDocument_ListAction::make_list_action($o);
13        usort($actions, "Conf::xt_position_compare");
14        $last_group = null;
15        foreach ($actions as $fj) {
16            $as = strpos($fj->selector, "/");
17            if ($as === false) {
18                if ($last_group)
19                    $sel_opt[] = ["optgroup", false];
20                $last_group = null;
21                $sel_opt[] = ["value" => substr($fj->name, 4), "label" => $fj->selector];
22            } else {
23                $group = substr($fj->selector, 0, $as);
24                if ($group !== $last_group) {
25                    $sel_opt[] = ["optgroup", $group];
26                    $last_group = $group;
27                }
28                $sel_opt[] = ["value" => substr($fj->name, 4), "label" => substr($fj->selector, $as + 1)];
29            }
30        }
31        if (!empty($sel_opt)) {
32            return Ht::select("getfn", $sel_opt, $pl->qreq->getfn,
33                              ["class" => "want-focus js-submit-action-info-get", "style" => "max-width:10em"])
34                . "&nbsp; " . Ht::submit("fn", "Go", ["value" => "get", "data-default-submit-all" => 1, "class" => "btn uix js-submit-mark"]);
35        } else
36            return null;
37    }
38    function run(Contact $user, $qreq, $ssel) {
39        if (($opts = $user->conf->paper_opts->find_all($qreq->getfn))
40            && count($opts) == 1
41            && ($o = current($opts))
42            && $user->can_view_some_paper_option($o)) {
43            $ga = new GetDocument_ListAction($o->id);
44            return $ga->run($user, $qreq, $ssel);
45        } else
46            return self::ENOENT;
47    }
48}
49
50class GetCheckFormat_ListAction extends ListAction {
51    function run(Contact $user, $qreq, $ssel) {
52        $papers = [];
53        foreach ($user->paper_set($ssel) as $prow)
54            if ($user->can_view_pdf($prow))
55                $papers[$prow->paperId] = $prow;
56        $csvg = $user->conf->make_csvg("formatcheck")->select(["paper", "title", "pages", "format"]);
57        $csvg->download_headers();
58        echo $csvg->headerline;
59        $cf = new CheckFormat($user->conf);
60        foreach ($ssel->reorder($papers) as $prow) {
61            $pages = "?";
62            if ($prow->mimetype == "application/pdf") {
63                $dtype = $prow->finalPaperStorageId ? DTYPE_FINAL : DTYPE_SUBMISSION;
64                if (($doc = $cf->fetch_document($prow, $dtype)))
65                    $cf->check_document($prow, $doc);
66                if ($doc && !$cf->failed) {
67                    $errf = $cf->problem_fields();
68                    $format = empty($errf) ? "ok" : join(",", $errf);
69                    $pages = $cf->pages;
70                } else
71                    $format = "error";
72            } else
73                $format = "notpdf";
74            echo $prow->paperId, ",", CsvGenerator::quote($prow->title), ",", $pages, ",", CsvGenerator::quote($format), "\n";
75            ob_flush();
76            flush();
77        }
78        exit;
79    }
80}
81
82class GetAbstract_ListAction extends ListAction {
83    const WIDTH = 96;
84    static private function render_option(PaperOption $o, $otxt) {
85        $dtype = array_shift($otxt);
86        if ($dtype === PaperOption::PAGE_HTML_NAME)
87            $n = join(" ", $otxt);
88        else
89            $n = $o->title;
90        $text = prefix_word_wrap("", $n, 0, self::WIDTH);
91        $text .= str_repeat("-", min(self::WIDTH, strlen($text) - 1)) . "\n";
92        if ($dtype === PaperOption::PAGE_HTML_DATA && !empty($otxt)) {
93            if (count($otxt) === 1)
94                $text .= rtrim($otxt[0]);
95            else
96                $text .= join("", array_map(function ($t) { return "* " . rtrim($t) . "\n"; }, $otxt));
97            $text .= "\n";
98        }
99        return $text . "\n";
100    }
101    static function render_displayed_options(PaperInfo $prow, Contact $user, $display) {
102        $text = "";
103        foreach ($prow->options() as $ov) {
104            if ($ov->option->display() === $display
105                && $user->can_view_paper_option($prow, $ov->option)
106                && ($otxt = $ov->option->unparse_page_text($prow, $ov)))
107                $text .= self::render_option($ov->option, $otxt);
108        }
109        return $text;
110    }
111    static function render(PaperInfo $prow, Contact $user) {
112        $n = prefix_word_wrap("", "Submission #{$prow->paperId}: {$prow->title}", 0, self::WIDTH);
113        $text = $n . str_repeat("=", min(self::WIDTH, strlen($n) - 1)) . "\n\n";
114
115        $text .= self::render_displayed_options($prow, $user, PaperOption::DISP_SUBMISSION);
116
117        if ($user->can_view_authors($prow) && ($alist = $prow->author_list())) {
118            if (count($alist) == 1)
119                $text .= "Author\n------\n"
120                    . prefix_word_wrap("", $alist[0]->name_email_aff_text(), 0, self::WIDTH);
121            else {
122                $text .= "Authors\n-------\n";
123                foreach ($alist as $i => $au) {
124                    $marker = ($i + 1) . ". ";
125                    $text .= prefix_word_wrap($marker, $au->name_email_aff_text(), strlen($marker), self::WIDTH);
126                }
127            }
128            $text .= "\n";
129        }
130
131        if ($prow->abstract)
132            $text .= "Abstract\n--------\n" . rtrim($prow->abstract) . "\n\n";
133
134        $text .= self::render_displayed_options($prow, $user, PaperOption::DISP_PROMINENT);
135
136        if (($tlist = $prow->named_topic_map())) {
137            $text .= "Topics\n------\n";
138            foreach ($tlist as $t)
139                $text .= prefix_word_wrap("* ", $t, 2, self::WIDTH);
140            $text .= "\n";
141        }
142
143        $text .= self::render_displayed_options($prow, $user, PaperOption::DISP_TOPICS);
144
145        return $text . "\n";
146    }
147    function run(Contact $user, $qreq, $ssel) {
148        $texts = array();
149        foreach ($user->paper_set($ssel, ["topics" => 1]) as $prow) {
150            if (($whyNot = $user->perm_view_paper($prow)))
151                Conf::msg_error(whyNotText($whyNot));
152            else {
153                defappend($texts[$prow->paperId], $this->render($prow, $user));
154                $rfSuffix = (count($texts) == 1 ? $prow->paperId : "s");
155            }
156        }
157        if (count($texts))
158            downloadText(join("", $ssel->reorder($texts)), "abstract$rfSuffix");
159    }
160}
161
162class GetAuthors_ListAction extends ListAction {
163    static function contact_map(Conf $conf, $ssel) {
164        $result = $conf->qe_raw("select ContactInfo.contactId, firstName, lastName, affiliation, email from ContactInfo join PaperConflict on (PaperConflict.contactId=ContactInfo.contactId) where conflictType>=" . CONFLICT_AUTHOR . " and paperId" . $ssel->sql_predicate() . " group by ContactInfo.contactId");
165        $contact_map = [];
166        while (($row = edb_orow($result))) {
167            $row->contactId = (int) $row->contactId;
168            $contact_map[$row->contactId] = $row;
169        }
170        return $contact_map;
171    }
172    function allow(Contact $user) {
173        return $user->can_view_some_authors();
174    }
175    function run(Contact $user, $qreq, $ssel) {
176        $contact_map = self::contact_map($user->conf, $ssel);
177        $texts = array();
178        $want_contacttype = false;
179        foreach ($user->paper_set($ssel, ["allConflictType" => 1]) as $prow) {
180            if (!$user->allow_view_authors($prow))
181                continue;
182            $admin = $user->allow_administer($prow);
183            $contact_emails = [];
184            if ($admin) {
185                $want_contacttype = true;
186                foreach ($prow->contacts() as $cid => $c) {
187                    $c = $contact_map[$cid];
188                    $contact_emails[strtolower($c->email)] = $c;
189                }
190            }
191            foreach ($prow->author_list() as $au) {
192                $line = [$prow->paperId, $prow->title, $au->firstName, $au->lastName, $au->email, $au->affiliation];
193                $lemail = strtolower($au->email);
194                if ($admin && $lemail && isset($contact_emails[$lemail])) {
195                    $line[] = "yes";
196                    unset($contact_emails[$lemail]);
197                } else if ($admin)
198                    $line[] = "no";
199                arrayappend($texts[$prow->paperId], $line);
200            }
201            foreach ($contact_emails as $c)
202                arrayappend($texts[$prow->paperId], [$prow->paperId, $prow->title, $c->firstName, $c->lastName, $c->email, $c->affiliation, "contact_only"]);
203        }
204        $header = ["paper", "title", "first", "last", "email", "affiliation"];
205        if ($want_contacttype)
206            $header[] = "iscontact";
207        return $user->conf->make_csvg("authors")->select($header)
208            ->add($ssel->reorder($texts));
209    }
210}
211
212/* NB this search action is actually unavailable via the UI */
213class GetContacts_ListAction extends ListAction {
214    function allow(Contact $user) {
215        return $user->is_manager();
216    }
217    function run(Contact $user, $qreq, $ssel) {
218        $contact_map = GetAuthors_ListAction::contact_map($user->conf, $ssel);
219        foreach ($user->paper_set($ssel, ["allConflictType" => 1]) as $prow)
220            if ($user->allow_administer($prow))
221                foreach ($prow->contacts() as $cid => $c) {
222                    $a = $contact_map[$cid];
223                    $aa = $prow->author_by_email($a->email) ? : $a;
224                    arrayappend($texts[$prow->paperId], [$prow->paperId, $prow->title, $aa->firstName, $aa->lastName, $aa->email, $aa->affiliation]);
225                }
226        return $user->conf->make_csvg("contacts")
227            ->select(["paper", "title", "first", "last", "email", "affiliation"])
228            ->add($ssel->reorder($texts));
229    }
230}
231
232class GetPcconflicts_ListAction extends ListAction {
233    function allow(Contact $user) {
234        return $user->is_manager();
235    }
236    function run(Contact $user, $qreq, $ssel) {
237        $allConflictTypes = Conflict::$type_descriptions;
238        $allConflictTypes[CONFLICT_CHAIRMARK] = "Chair-confirmed";
239        $allConflictTypes[CONFLICT_AUTHOR] = "Author";
240        $allConflictTypes[CONFLICT_CONTACTAUTHOR] = "Contact";
241        $pcm = $user->conf->pc_members();
242        $texts = array();
243        $old_overrides = $user->add_overrides(Contact::OVERRIDE_CONFLICT);
244        foreach ($user->paper_set($ssel, ["allConflictType" => 1]) as $prow) {
245            if ($user->can_view_conflicts($prow)) {
246                $m = [];
247                foreach ($prow->conflicts() as $cid => $c)
248                    if (isset($pcm[$cid])) {
249                        $pc = $pcm[$cid];
250                        $m[$pc->sort_position] = [$prow->paperId, $prow->title, $pc->firstName, $pc->lastName, $pc->email, get($allConflictTypes, $c->conflictType, "Conflict")];
251                    }
252                if ($m) {
253                    ksort($m);
254                    $texts[$prow->paperId] = $m;
255                }
256            }
257        }
258        $user->set_overrides($old_overrides);
259        return $user->conf->make_csvg("pcconflicts")
260            ->select(["paper", "title", "first", "last", "email", "conflicttype"])
261            ->add($ssel->reorder($texts));
262    }
263}
264
265class GetTopics_ListAction extends ListAction {
266    function run(Contact $user, $qreq, $ssel) {
267        $texts = array();
268        foreach ($user->paper_set($ssel, ["topics" => 1]) as $row)
269            if ($user->can_view_paper($row)) {
270                $out = array();
271                foreach ($row->named_topic_map() as $t)
272                    $out[] = [$row->paperId, $row->title, $t];
273                if (empty($out))
274                    $out[] = [$row->paperId, $row->title, "<none>"];
275                arrayappend($texts[$row->paperId], $out);
276            }
277        return $user->conf->make_csvg("topics")
278            ->select(["paper", "title", "topic"])
279            ->add($ssel->reorder($texts));
280    }
281}
282
283class GetCSV_ListAction extends ListAction {
284    function run(Contact $user, $qreq, $ssel) {
285        $search = new PaperSearch($user, $qreq);
286        $search->restrict_match([$ssel, "is_selected"]);
287        $pl = new PaperList($search, ["sort" => true, "report" => "pl", "display" => $qreq->display], $qreq);
288        $pl->set_view("sel", false);
289        list($header, $data) = $pl->text_csv($qreq->t);
290        return $user->conf->make_csvg("data", CsvGenerator::FLAG_ITEM_COMMENTS)
291            ->select($header)->add($data);
292    }
293}
294