1<?php 2// help.php -- HotCRP help page 3// Copyright (c) 2006-2018 Eddie Kohler; see LICENSE. 4 5require_once("src/initweb.php"); 6 7$help_topics = new GroupedExtensions($Me, [ 8 '{"name":"topics","title":"Help topics","position":-1000000,"priority":1000000,"callback":"show_help_topics"}', 9 "etc/helptopics.json" 10], $Conf->opt("helpTopics")); 11 12if (!$Qreq->t && preg_match(',\A/(\w+)\z,i', Navigation::path())) 13 $Qreq->t = substr(Navigation::path(), 1); 14$topic = $Qreq->t ? : "topics"; 15$want_topic = $help_topics->canonical_group($topic); 16if (!$want_topic) 17 $want_topic = "topics"; 18if ($want_topic !== $topic) 19 SelfHref::redirect($Qreq, ["t" => $want_topic]); 20$topicj = $help_topics->get($topic); 21 22$Conf->header_head($topic === "topics" ? "Help" : "Help - {$topicj->title}"); 23$Conf->header_body("Help", "help"); 24 25class HtHead extends Ht { 26 public $conf; 27 public $user; 28 private $_tabletype; 29 private $_rowidx; 30 private $_help_topics; 31 private $_renderers = []; 32 function __construct($help_topics, Contact $user) { 33 $this->conf = $user->conf; 34 $this->user = $user; 35 $this->_help_topics = $help_topics; 36 } 37 static function subhead($title, $id = null) { 38 if ($id || $title) 39 return '<h3 class="helppage"' . ($id ? " id=\"{$id}\"" : "") . '>' . $title . "</h3>\n"; 40 else 41 return ""; 42 } 43 function table($tabletype = false) { 44 $this->_rowidx = 0; 45 $this->_tabletype = $tabletype; 46 return $this->_tabletype ? "" : '<table class="demargin"><tbody>'; 47 } 48 function tgroup($title, $id = null) { 49 $this->_rowidx = 0; 50 if ($this->_tabletype) 51 return $this->subhead($title, $id); 52 else 53 return '<tr><td class="sentry nw remargin-left remargin-right" colspan="2"><h4 class="helppage"' 54 . ($id ? " id=\"{$id}\"" : "") . '>' 55 . $title . "</h4></td></tr>\n"; 56 } 57 function trow($caption, $entry = null) { 58 if ($this->_tabletype) { 59 $t = "<div class=\"helplist-item demargin k{$this->_rowidx}\">" 60 . "<table><tbody><tr>" 61 . "<td class=\"helplist-dt remargin-left\">" 62 . $caption 63 . "</td><td class=\"helplist-dd remargin-right\">" 64 . $entry . "</td></tr></tbody></table></div>\n"; 65 } else { 66 $t = "<tr class=\"k{$this->_rowidx}\">" 67 . "<td class=\"sentry remargin-left"; 68 if ((string) $entry === "") 69 $t .= ' remargin-right" colspan="2">' . $caption; 70 else 71 $t .= '">' . $caption . '</td><td class="sentry remargin-right">' . $entry; 72 $t .= "</td></tr>\n"; 73 } 74 $this->_rowidx = 1 - $this->_rowidx; 75 return $t; 76 } 77 function end_table() { 78 return $this->_tabletype ? "" : "</tbody></table>\n"; 79 } 80 function search_link($html, $q = null) { 81 if ($q === null) 82 $q = $html; 83 if (is_string($q)) 84 $q = ["q" => $q]; 85 return '<a href="' . hoturl("search", $q) . '">' 86 . ($html ? : htmlspecialchars($q["q"])) . '</a>'; 87 } 88 function help_link($html, $topic = null) { 89 if ($topic === null) { 90 $topic = $html; 91 $html = "Learn more"; 92 } 93 if (is_string($topic) && ($hash = strpos($topic, "#")) !== false) 94 $topic = ["t" => substr($topic, 0, $hash), "anchor" => substr($topic, $hash + 1)]; 95 else if (is_string($topic)) 96 $topic = ["t" => $topic]; 97 if (isset($topic["t"]) && ($group = $this->_help_topics->canonical_group($topic["t"]))) 98 $topic["t"] = $group; 99 return '<a href="' . hoturl("help", $topic) . '">' . $html . '</a>'; 100 } 101 function settings_link($html, $group = null) { 102 if ($this->user->privChair) { 103 $pre = $post = ""; 104 if ($group === null) { 105 $group = $html; 106 $html = "Change this setting"; 107 $pre = " ("; 108 $post = ")"; 109 } 110 if (is_string($group) && ($hash = strpos($group, "#")) !== false) 111 $group = ["group" => substr($group, 0, $hash), "anchor" => substr($group, $hash + 1)]; 112 else if (is_string($group)) 113 $group = ["group" => $group]; 114 return $pre . '<a href="' . hoturl("settings", $group) . '">' . $html . '</a>' . $post; 115 } else { 116 if ($group === null) 117 return ''; 118 else 119 return $html; 120 } 121 } 122 function search_form($q, $size = 20) { 123 if (is_string($q)) 124 $q = ["q" => $q]; 125 $t = Ht::form(hoturl("search"), ["method" => "get", "class" => "nw"]) 126 . Ht::entry("q", $q["q"], ["size" => $size]) 127 . " " 128 . Ht::submit("go", "Search"); 129 foreach ($q as $k => $v) { 130 if ($k !== "q") 131 $t .= Ht::hidden($k, $v); 132 } 133 return $t . "</form>"; 134 } 135 function search_trow($q, $entry) { 136 return $this->trow($this->search_form($q, 36), $entry); 137 } 138 function example_tag($property) { 139 $vt = []; 140 if ($this->user->isPC) 141 $vt = $this->conf->tags()->filter($property); 142 return empty($vt) ? $property : current($vt)->tag; 143 } 144 function current_tag_list($property) { 145 $vt = []; 146 if ($this->user->isPC) 147 $vt = $this->conf->tags()->filter($property); 148 if (empty($vt)) 149 return ""; 150 else 151 return " (currently " . join(", ", array_map(function ($t) { 152 return $this->search_link($t->tag, "#{$t->tag}"); 153 }, $vt)) . ")"; 154 } 155 function render_group($topic) { 156 foreach ($this->_help_topics->members($topic) as $gj) { 157 Conf::xt_resolve_require($gj); 158 if (isset($gj->callback)) { 159 $cb = $gj->callback; 160 if ($cb[0] === "*") { 161 $colons = strpos($cb, ":"); 162 $klass = substr($cb, 1, $colons - 1); 163 if (!isset($this->_renderers[$klass])) 164 $this->_renderers[$klass] = new $klass($this, $gj); 165 $cb = [$this->_renderers[$klass], substr($cb, $colons + 2)]; 166 } 167 call_user_func($cb, $this, $gj); 168 } 169 } 170 } 171 function groups() { 172 return $this->_help_topics->groups(); 173 } 174} 175 176$hth = new HtHead($help_topics, $Me); 177 178 179function show_help_topics($hth) { 180 echo "<dl>\n"; 181 foreach ($hth->groups() as $ht) { 182 if ($ht->name !== "topics" && isset($ht->title)) { 183 echo '<dt><strong><a href="', hoturl("help", "t=$ht->name"), '">', $ht->title, '</a></strong></dt>'; 184 if (isset($ht->description)) 185 echo '<dd>', get($ht, "description", ""), '</dd>'; 186 echo "\n"; 187 } 188 } 189 echo "</dl>\n"; 190} 191 192 193function meaningful_pc_tag(Contact $user) { 194 if ($user->isPC) 195 foreach ($user->conf->pc_tags() as $tag) 196 if ($tag !== "pc") 197 return $tag; 198 return false; 199} 200 201function meaningful_round_name(Contact $user) { 202 if ($user->isPC) { 203 $rounds = $user->conf->round_list(); 204 for ($i = 1; $i < count($rounds); ++$i) 205 if ($rounds[$i] !== ";") 206 return $rounds[$i]; 207 } 208 return false; 209} 210 211 212echo '<div class="leftmenu-menu-container"><div class="leftmenu-list">'; 213foreach ($help_topics->groups() as $gj) { 214 if ($gj->name === $topic) 215 echo '<div class="leftmenu-item-on">', $gj->title, '</div>'; 216 else if (isset($gj->title)) 217 echo '<div class="leftmenu-item ui js-click-child">', 218 '<a href="', hoturl("help", "t=$gj->name"), '">', $gj->title, '</a></div>'; 219 if ($gj->name === "topics") 220 echo '<div class="c g"></div>'; 221} 222echo "</div></div>\n", 223 '<div class="leftmenu-content-container"><div id="helpcontent" class="leftmenu-content">'; 224 225echo '<h2 class="helppage">', $topicj->title, '</h2>'; 226$hth->render_group($topic); 227echo "</div></div>\n"; 228 229 230$Conf->footer(); 231