4 * This handles link creation for the wiki..
6 * it get's registered by MTrackWeb as the link handler..
9 require_once 'MTrack/Interface/WikiLinkHandler.php';
12 class MTrackWeb_LinkHandler implements MTrack_Interface_WikiLinkHandler
14 function MTrackWeb_LinkHandler()
16 $ff = HTML_FlexyFramework::get();
18 $this->baseURL = $ff->cli ? $ff->MTrackCLI['baseURL'] : $ff->page->baseURL;
25 * [display] = text to display
28 function ticket($no, $extras=array())
31 if ($no instanceof MTrackIssue) {
33 } else if (is_string($no) || is_int($no)) {
34 static $cache = array();
40 if (!isset($cache[$no])) {
41 $tkt = MTrackIssue::loadByNSIdent($no);
43 $tkt = MTrackIssue::loadById($no);
50 // FIXME: hinted data from reports
52 $tkt->tid = $no['ticket'];
53 $tkt->summary = $no['summary'];
56 if (isset($no['state'])) {
57 $tkt->status = $no['state'];
58 } elseif (isset($no['status'])) {
59 $tkt->status = $no['status'];
60 } elseif (isset($no['__status__'])) {
61 $tkt->status = $no['__status__'];
68 $tkt->summary = 'No such ticket';
69 $tkt->status = 'No such ticket';
71 $html = "<a class='ticketlink";
72 if ($tkt->status == 'closed') {
73 $html .= ' completed';
75 if (!empty($tkt->nsident)) {
76 $ident = $tkt->nsident;
80 if (isset($extras['#'])) {
81 $anchor = '#' . $extras['#'];
85 $html .= "' href=\"{$this->baseURL}/Ticket/$ident$anchor\">";
86 if (isset($extras['display'])) {
87 $html .= htmlspecialchars($extras['display']);
89 $html .= '#' . htmlspecialchars($ident);
95 function milestone( $target, $label)
97 // silly but we assume target is urlencoded???...
98 $ms = MTrack_Milestone::loadByName($target);
100 return '<span class="milestone' .
101 (($ms->deleted || $ms->completed) ? ' completed' : '') .
102 '"><a href="'. $this->baseURL . '/Milestone/'. $target .'">'.
103 htmlspecialchars(urldecode($target)) .
107 function help($target, $label, $anchor = '')
111 $target .= !empty($anchor) ? "#$anchor" : '';
113 return '<a class="wikilink"
114 href="'.$this->baseURL . '/Help/' . htmlspecialchars($target) .
115 '">' . htmlspecialchars($label) . '</a>';
118 function username($target, $opts=array())
120 if (is_object($target)) {
122 $target = $userinfo->userid;
124 $userinfo = MTrack_DataObjects_Userinfo::findString($target);
127 if (is_string($opts)) {
128 parse_str($opts, $opts);
131 //print_R($userinfo);
133 // we did not find the ysers...
134 // we currently ignore all the formating....
136 href="'. $this->baseURL .'/User/'. urlencode($target) . '" class="userlink">' .
137 htmlspecialchars($target).
141 if (!ctype_alnum($username)) {
142 $target = "{$ABSWEB}user.php?user=" . urlencode($username);
143 if (isset($opts['edit'])) {
144 $target .= '&edit=1';
151 '<a title="' . htmlspecialchars($userinfo->fullname) . '"
153 $this->baseURL .'/User/'.
154 urlencode($userinfo->userid) .
155 (empty($opts['edit']) ? '' : '?edit=1') .
158 (isset($opts['class']) ? ' ' . $opts['class'] : '') .
161 $dispname = $userinfo->fullname;
162 //$dispname = preg_match("/^([^+]*)(\+.*)?@(.*)$/", $target) ? $target : $userinfo->userid;
165 $size = empty($opts['size']) ? 24 : (int) $opts['size'];
168 (!empty($opts['no_image']) ? '' : ($open_a .
169 '<img class="gravatar"
170 width="' . $size . '" height="' . $size . '"
171 src="' . $this->baseURL . '/Avatar.png?u=' .
172 urlencode($userinfo->userid) . '&s='. $size . '">
175 // at this point the old code tries to chop it...
176 // I'm not sure that is a great idea....
177 (!empty($opts['no_name']) ? '' : ($open_a . htmlspecialchars($dispname) . '</a>'));
178 //var_dump( htmlspecialchars($ret));
182 function browse($target, $label)
184 return '<a href="'. $this->baseURL . '/Browse/'. htmlspecialchars($target) .'">'.
185 htmlspecialchars($label) .
188 function log($target, $label) // what does this do...
190 return '<a href="'. $this->baseURL . '/Log/'. htmlspecialchars($target) .'">'.
191 htmlspecialchars($label) .
195 function branch($branch, $repo = null)
197 return "<span class='branchname'>" . htmlspecialchars($branch) . "</span>";
203 function changeset($cs, $repo = null)
205 $display = substr($cs, 0, 12);
207 $repo = MTrackRepo::loadByChangeSet($cs);
209 if (is_string($repo)) {
210 $repo = MTrackRepo::loadByName($rep);
212 if (!is_a($repo, 'MTrackRepo')) {
213 $repo = MTrackRepo::defaultRepo();
215 $p = $repo->getBrowseRootName() . '/'. $cs;
218 return '<a class="changesetlink"
219 href="'. $this->baseURL . '/Changeset/'. htmlspecialchars($p) .'">[' . substr($cs, 0, 12) . ']</a>';
223 function wiki($pagename, $extras = array())
226 if ($pagename instanceof MTrack_Wiki_Item) {
228 } else if (is_string($pagename)) {
229 $wiki = null;//MTrackWikiItem::loadByPageName($pagename);
231 // FIXME: hinted data from reports
232 throw new Exception("FIXME: wiki");
236 $pagename = $wiki->pagename;
238 $pagename .= empty( $extras['#']) ? '' : '#' . $extras['#'];
240 return '<a class="wikilink"
241 href="'.$this->baseURL . '/Wiki/'. htmlspecialchars($pagename) .'">'.
242 htmlspecialchars(empty($extras['display']) ? $pagename : $extras['display']) .
246 // all these are prtty much the same..
247 function query($target, $label)
250 return '<a href="'. $this->baseURL . '/Query/'. htmlspecialchars($target) .'">'.
251 htmlspecialchars($label) .
254 function report($target, $label)
256 return '<a href="'. $this->baseURL . '/Report/'. htmlspecialchars($target) .'">'.
257 htmlspecialchars($label) .
261 // technically not a link....
262 function date($tstring, $show_full = false)
264 /* database time is always relative to UTC */
265 $d = date_create($tstring, new DateTimeZone('UTC'));
266 if (!is_object($d)) {
267 throw new Exception("could not represent $tstring as a datetime object");
269 $iso8601 = $d->format(DateTime::W3C);
270 /* but we want to render relative to user prefs */
271 date_timezone_set($d, new DateTimeZone(date_default_timezone_get()));
272 $full = $d->format('D, M d Y H:i');
275 return "<abbr title=\"$iso8601\" class='timeinterval'>$full</abbr>";
278 return "<abbr title='$iso8601' class='timeinterval'>$full</abbr> <span class='fulldate'>$full</span>";