protected function initContent() { $request = $this->getContext()->getRequest(); $resultsID = $request->getInt('item'); $this->setTitle('Run result'); $this->setRobots('noindex,nofollow'); $this->bodyScripts[] = swarmpath('js/result.js'); $error = $this->getAction()->getError(); $data = $this->getAction()->getData(); $html = ''; if ($error) { $html .= html_tag('div', array('class' => 'alert alert-error'), $error['info']); return $html; } $this->setSubTitle('#' . $data['info']['id']); if ($data['job']) { $html = '<p><em>' . html_tag_open('a', array('href' => $data['job']['url'], 'title' => 'Back to Job #' . $data['job']['id'])) . '« Back to Job #' . $data['job']['id'] . '</a>' . '</em></p>'; } else { $html = '<p><em>Run #' . $data['info']['runID'] . ' has been deleted. Job info unavailable.</em></p>'; } if ($data['otherRuns']) { $html .= '<table class="table table-bordered swarm-results"><thead>' . JobPage::getUaHtmlHeader($data['otherRuns']['userAgents']) . '</thead><tbody>' . JobPage::getUaRunsHtmlRows($data['otherRuns']['runs'], $data['otherRuns']['userAgents']) . '</tbody></table>'; } $html .= '<h3>Information</h3>' . '<table class="table table-striped">' . '<tbody>' . '<tr><th>Run</th><td>' . ($data['job'] ? html_tag('a', array('href' => $data['job']['url']), 'Job #' . $data['job']['id']) . ' / ' : '') . 'Run #' . htmlspecialchars($data['info']['runID']) . '</td></tr>' . '<tr><th>Client</th><td>' . html_tag('a', array('href' => $data['client']['viewUrl']), 'Client #' . $data['info']['clientID']) . ' / ' . htmlspecialchars($data['client']['name']) . '</td></tr>' . '<tr><th>UA ID</th><td>' . '<code>' . htmlspecialchars($data['client']['uaID']) . '</code>' . '<tr><th>User-Agent</th><td>' . '<tt>' . htmlspecialchars($data['client']['uaRaw']) . '</tt>' . '</td></tr>' . '<tr><th>Run time</th><td>' . (isset($data['info']['runTime']) ? number_format(intval($data['info']['runTime'])) . 's' : '?') . '</td></tr>' . '<tr><th>Status</th><td>' . htmlspecialchars($data['info']['status']) . '</td></tr>' . '<tr><th>Started</th><td>' . self::getPrettyDateHtml($data['info'], 'started') . '</td></tr>' . (isset($data['info']['savedLocalFormatted']) ? '<tr><th>Saved</th><td>' . self::getPrettyDateHtml($data['info'], 'saved') . '</td></tr>' : '') . '</tbody></table>'; $html .= '<h3>Results</h3>' . '<p class="swarm-toollinks">' . html_tag('a', array('href' => swarmpath('index.php') . '?' . http_build_query(array('action' => 'result', 'item' => $data['info']['id'], 'raw' => '')), 'target' => '_blank', 'class' => 'swarm-popuplink'), 'Open in new window') . '</p>' . html_tag('iframe', array('src' => swarmpath('index.php') . '?' . http_build_query(array('action' => 'result', 'item' => $data['info']['id'], 'raw' => '')), 'width' => '100%', 'class' => 'swarm-result-frame')); return $html; }
public static function getUaRunsHtmlRows($runs, $userAgents) { $html = ''; foreach ($runs as $run) { $html .= '<tr><th><a href="' . htmlspecialchars($run['info']['url']) . '">' . $run['info']['name'] . '</a></th>'; // Looping over $userAgents instead of $run["uaRuns"], // to avoid shifts in the table (github.com/jquery/testswarm/issues/13) foreach ($userAgents as $uaID => $uaInfo) { if (isset($run['uaRuns'][$uaID])) { $uaRun = $run['uaRuns'][$uaID]; $html .= html_tag_open('td', array('class' => 'swarm-status swarm-status-' . $uaRun['runStatus'], 'data-run-id' => $run['info']['id'], 'data-run-status' => $uaRun['runStatus'], 'data-useragent-id' => $uaID, 'data-client-id' => isset($uaRun['clientID']) ? $uaRun['clientID'] : '')); if (isset($uaRun['runResultsUrl']) && isset($uaRun['runResultsLabel'])) { $html .= html_tag_open('a', array('rel' => 'nofollow', 'href' => $uaRun['runResultsUrl'])) . ($uaRun['runResultsLabel'] ? $uaRun['runResultsLabel'] : UserPage::getStatusIconHtml($uaRun['runStatus'])) . '<i class="icon-list-alt pull-right" title="' . htmlspecialchars("Open run results for {$userAgents[$uaID]['displaytitle']}") . '"></i>' . '</a>'; } else { $html .= UserPage::getStatusIconHtml($uaRun['runStatus']); } $html .= '</td>'; } else { // This run isn't schedules to be ran in this UA $html .= '<td class="swarm-status swarm-status-notscheduled"></td>'; } } } return $html; }
/** @return bool: Whether the current user was found in the swarm */ public function getBrowsersOnlineHtml() { $conf = $this->getContext()->getConf(); $db = $this->getContext()->getDB(); $browserInfo = $this->getContext()->getBrowserInfo(); $data = $this->getAction()->getData(); $html = ''; $itemsPerRow = 6; $browsersHtml = '<h2>State of the Swarm</h2>'; $browserItemCount = 0; foreach ($data['userAgents'] as $uaID => $userAgent) { $isCurr = $uaID == $browserInfo->getSwarmUaID(); $displayInfo = $userAgent['data']['displayInfo']; $item = '' . '<div class="span2">' . '<div class="well well-swarm-icon' . ($isCurr ? ' alert-info' : '') . '">' . html_tag('div', array('class' => $displayInfo['class'], 'title' => $displayInfo['title'])) . '<br>' . html_tag_open('span', array('class' => 'label swarm-browsername')) . $displayInfo['labelHtml'] . '</span>' . '<br>' . html_tag('span', array('class' => 'swarm-onlineclients ' . ($userAgent["stats"]["onlineClients"] > 0 ? "badge" : ($userAgent['stats']['pendingRuns'] > 0 ? 'badge badge-important' : 'badge')), "title" => $userAgent["stats"]["onlineClients"] . ' clients online'), $userAgent["stats"]["onlineClients"]) . html_tag("span", array("class" => "swarm-pendingruns " . ($userAgent["stats"]["pendingRuns"] > 0 ? $userAgent["stats"]["onlineClients"] > 0 ? "badge badge-info" : "badge badge-warning" : "badge badge-success")), $userAgent["stats"]["pendingRuns"] . ' runs') . ($userAgent["stats"]["pendingReRuns"] > 0 ? ' ' . html_tag("span", array("class" => "swarm-pendingreruns " . ($userAgent["stats"]["onlineClients"] > 0 ? "badge badge-info" : "badge badge-warning")), $userAgent["stats"]["pendingReRuns"] . ' re-runs') : "") . '</div>' . '</div>'; // Properly close and start new rows if ($browserItemCount % $itemsPerRow === 0) { $browsersHtml .= '<div class="row">'; } $browserItemCount += 1; $browsersHtml .= $item; if ($browserItemCount % $itemsPerRow === 0) { $browsersHtml .= '</div><!--/.row -->'; } } // Close un-even items rows if ($browserItemCount % $itemsPerRow !== 0) { $browsersHtml .= '</div><!--/.row -->'; } if ($browserItemCount === 0) { $browsersHtml .= '<p><em>This swarm is empty!</em></p>'; } $html .= $browsersHtml; return $html; }
protected function initContent() { $request = $this->getContext()->getRequest(); $resultsID = $request->getInt('item'); $this->setTitle('Run result'); $this->setRobots('noindex,nofollow'); $this->bodyScripts[] = swarmpath('js/result.js'); $error = $this->getAction()->getError(); $data = $this->getAction()->getData(); $html = ''; if ($error) { $html .= html_tag('div', array('class' => 'alert alert-error'), $error['info']); return $html; } $this->setSubTitle('#' . $data['resultInfo']['id']); if ($data['job']) { $html = '<p><em>' . html_tag_open('a', array('href' => $data['job']['url'], 'title' => 'Back to Job #' . $data['job']['id'])) . '« Back to Job #' . $data['job']['id'] . '</a>' . '</em></p>'; } else { $html = '<p><em>Run #' . $data['resultInfo']['runID'] . ' has been deleted. Job info unavailable.</em></p>'; } if ($data['otherRuns']) { $html .= '<table class="table table-bordered swarm-results"><thead>' . JobPage::getUaHtmlHeader($data['otherRuns']['userAgents']) . '</thead><tbody>' . JobPage::getUaRunsHtmlRows($data['otherRuns']['runs'], $data['otherRuns']['userAgents']) . '</tbody></table>'; } $html .= '<h3>Information</h3>' . '<table class="table table-striped">' . '<colgroup><col class="span2"/><col/></colgroup>' . '<tbody>' . '<tr><th>Run</th><td>' . ($data['job'] ? html_tag('a', array('href' => $data['job']['url']), 'Job #' . $data['job']['id']) . ' / ' : '') . 'Run #' . htmlspecialchars($data['resultInfo']['runID']) . '</td></tr>' . '<tr><th>Client</th><td>' . html_tag('a', array('href' => $data['client']['userUrl']), $data['client']['userName']) . ' / Client #' . htmlspecialchars($data['resultInfo']['clientID']) . '</td></tr>' . ($data['client']['deviceName'] !== null ? '<tr><th>Device name</th><td>' . $data['client']['deviceName'] . ' / ' . html_tag('a', array('target' => '_blank', 'href' => 'http://wiki.blinkbox.local/wiki/index.php?profile=default&search=' . htmlspecialchars($data['client']['deviceName'])), 'search for ' . $data['client']['deviceName'] . ' on blinkbox wiki') . '</td></tr>' : '') . '<tr><th>User-Agent</th><td>' . '<code>' . htmlspecialchars($data['client']['uaID']) . '</code><br/>' . 'Raw: <br><code>' . htmlspecialchars($data['client']['userAgent']) . '</code><br/>' . html_tag('a', array('target' => '_blank', 'href' => 'http://wiki.blinkbox.local/wiki/index.php?profile=default&search=' . htmlspecialchars($data['client']['userAgent'])), 'search for this user agent on blinkbox wiki') . '</td></tr>' . '<tr><th>Run time</th><td>' . (isset($data['resultInfo']['runTime']) ? number_format(intval($data['resultInfo']['runTime'])) . 's' : '?') . '</td></tr>' . '<tr><th>Status</th><td>' . htmlspecialchars($data['resultInfo']['status']) . '</td></tr>' . '<tr><th>Total</th><td>' . htmlspecialchars($data['resultInfo']['total']) . '</td></tr>' . '<tr><th>Fail</th><td>' . htmlspecialchars($data['resultInfo']['fail']) . '</td></tr>' . '<tr><th>Error</th><td>' . htmlspecialchars($data['resultInfo']['error']) . '</td></tr>' . '<tr><th>Started</th><td>' . self::getPrettyDateHtml($data['resultInfo'], 'started') . '</td></tr>' . (isset($data['resultInfo']['savedLocalFormatted']) ? '<tr><th>Saved</th><td>' . self::getPrettyDateHtml($data['resultInfo'], 'saved') . '</td></tr>' : '') . '<tr><th>Results size</th><td>' . 'compressed: ' . self::formatBytes($data['resultInfo']['reportHtmlCompressedSize']) . ' / uncompressed: ' . self::formatBytes($data['resultInfo']['reportHtmlSize']) . ' / ratio: ' . $data['resultInfo']['reportHtmlCompressionRatio'] . '%' . '</td></tr>' . '</tbody></table>'; $html .= '<h3>Results</h3>' . '<p class="swarm-toollinks">' . html_tag('a', array('href' => swarmpath('index.php') . '?' . http_build_query(array('action' => 'result', 'item' => $data['resultInfo']['id'], 'raw' => '')), 'target' => '_blank', 'class' => 'swarm-popuplink'), 'Open in new window') . '</p>' . html_tag('iframe', array('src' => swarmpath('index.php') . '?' . http_build_query(array('action' => 'result', 'item' => $data['resultInfo']['id'], 'raw' => '')), 'width' => '100%', 'class' => 'swarm-result-frame')); return $html; }
function html_tag($tagName, array $attribs = array(), $content = '') { static $voidElements = array('area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source'); $html = html_tag_open($tagName, $attribs); if (!in_array($tagName, $voidElements)) { $content = strtr($content, array('&' => '&', '<' => '<')); $html .= "{$content}</{$tagName}>"; } return $html; }
protected function initContent() { $request = $this->getContext()->getRequest(); $this->setTitle("Job status"); $this->setRobots("noindex,nofollow"); $this->bodyScripts[] = swarmpath("js/job.js"); $error = $this->getAction()->getError(); $data = $this->getAction()->getData(); $html = ''; if ($error) { $html .= html_tag('div', array('class' => 'alert alert-error'), $error['info']); } if (!isset($data["jobInfo"])) { return $html; } $this->setSubTitle('#' . $data["jobInfo"]["id"]); $html .= '<h2>' . $data["jobInfo"]["name"] . '</h2>' . '<p><em>Submitted by ' . html_tag("a", array("href" => swarmpath("user/{$data["jobInfo"]["ownerName"]}")), $data["jobInfo"]["ownerName"]) . ' on ' . htmlspecialchars(date("Y-m-d H:i:s", gmstrtotime($data["jobInfo"]["creationTimestamp"]))) . ' (UTC)' . '</em>.</p>'; if ($request->getSessionData("auth") === "yes" && $data["jobInfo"]["ownerName"] == $request->getSessionData("username")) { $html .= '<script>SWARM.jobInfo = ' . json_encode($data["jobInfo"]) . ';</script>' . '<div class="form-actions">' . ' <button id="swarm-job-delete" class="btn btn-danger">Delete job</button>' . ' <button id="swarm-job-reset" class="btn btn-info">Reset job</button>' . '</div>' . '<div class="alert alert-error" id="swarm-wipejob-error" style="display: none;"></div>'; } $html .= '<table class="table table-bordered swarm-results"><thead><tr><th> </th>'; // Header with user agents foreach ($data["userAgents"] as $userAgent) { $html .= '<th><img src="' . swarmpath("img/" . $userAgent["displayicon"]) . '.sm.png" class="swarm-browsericon ' . '" alt="' . htmlspecialchars($userAgent["displaytitle"]) . '" title="' . htmlspecialchars($userAgent["displaytitle"]) . '"><br>' . htmlspecialchars(preg_replace("/\\w+ /", "", $userAgent["displaytitle"])) . '</th>'; } $html .= '</tr></thead><tbody>'; foreach ($data["runs"] as $run) { $html .= '<tr><th><a href="' . htmlspecialchars($run["info"]["url"]) . '">' . $run["info"]["name"] . '</a></th>'; // Looping over $data["userAgents"] instead of $run["uaRuns"], // to avoid shifts in the table (github.com/jquery/testswarm/issues/13) foreach ($data["userAgents"] as $uaID => $uaInfo) { if (isset($run["uaRuns"][$uaID])) { $uaRun = $run["uaRuns"][$uaID]; $html .= html_tag_open("td", array("class" => "swarm-status swarm-status-" . $uaRun["runStatus"], "data-job-id" => $data["jobInfo"]["id"], "data-run-id" => $run["info"]["id"], "data-run-status" => $uaRun["runStatus"], "data-useragent-id" => $uaID, "data-client-id" => isset($uaRun["clientID"]) ? $uaRun["clientID"] : "")); if (isset($uaRun["runResultsUrl"]) && $uaRun["runResultsLabel"]) { $html .= html_tag_open('a', array("rel" => "nofollow", "href" => $uaRun["runResultsUrl"])) . $uaRun["runResultsLabel"] . '<i class="icon-list-alt pull-right" title="' . htmlspecialchars("Open run results for {$data["userAgents"][$uaID]["displaytitle"]}") . '"></i>' . '</a>'; } else { $html .= UserPage::getStatusIconHtml($uaRun["runStatus"]); } $html .= '</td>'; } else { // This run isn't schedules to be ran in this UA $html .= '<td class="swarm-status swarm-status-notscheduled"></td>'; } } } $html .= '</tbody></table>'; return $html; }
protected function initContent() { $this->setTitle("Project"); $html = ""; $error = $this->getAction()->getError(); $data = $this->getAction()->getData(); if ($error) { $html .= html_tag("div", array("class" => "alert alert-error"), $error["info"]); return $html; } $this->setSubTitle($data['info']['display_title']); $info = array(); if ($data['info']['site_url']) { $info[] = 'Homepage: ' . html_tag('a', array('href' => $data['info']['site_url']), parse_url($data['info']['site_url'], PHP_URL_HOST) ?: $data['info']['site_url']); } $info[] = 'Created: ' . self::getPrettyDateHtml($data['info'], 'created'); $info[] = 'Last updated: ' . self::getPrettyDateHtml($data['info'], 'updated'); $html .= '<div class="well well-small">' . implode(' <span class="muted">|</span> ', $info) . '</div>'; if (!count($data['jobs'])) { $html .= '<div class="alert alert-info">No jobs found.</div>'; } else { $html .= '<h2>Jobs</h2><ul class="pager">'; if ($data['pagination']['prev']) { $html .= '<li class="previous">' . html_tag_open('a', array('href' => $data['pagination']['prev']['viewUrl'])) . '← Previous</a></li>'; } else { $html .= '<li class="previous disabled" title="No previous page"><a href="#">← Previous</a></span>'; } if ($data['pagination']['next']) { $html .= '<li class="next">' . html_tag_open('a', array('href' => $data['pagination']['next']['viewUrl'])) . 'Next →</a></li>'; } else { $html .= '<li class="next disabled" title="No next page"><a href="#">Next →</a></span>'; } $html .= '</ul>'; $html .= '<table class="table table-bordered swarm-results">'; $html .= '<thead>'; $html .= JobPage::getUaHtmlHeader($data['userAgents']); $html .= '</thead><tbody>'; foreach ($data['jobs'] as $job) { $html .= JobPage::getJobHtmlRow($job, $data['userAgents']); } $html .= '</tbody></table>'; } return $html; }
/** * Create table rows for a table of ua run results. * This is used on the JobPage. * * @param Array $runs List of runs, from JobAction. * @param Array $userAgents List of uaData objects. * @param bool $showResetRun: Whether to show the reset buttons for individual runs. * This does not check authororisation or load related javascript for the buttons. */ public static function getUaRunsHtmlRows($runs, $userAgents, $showResetRun = false) { $html = ''; foreach ($runs as $run) { $html .= '<tr><th>' . $run['info']['name'] . '</th>'; // Looping over $userAgents instead of $run["uaRuns"], // to avoid shifts in the table (github.com/jquery/testswarm/issues/13) foreach ($userAgents as $uaID => $uaInfo) { if (isset($run['uaRuns'][$uaID])) { $uaRun = $run['uaRuns'][$uaID]; $html .= html_tag_open('td', array('class' => 'swarm-status swarm-status-' . $uaRun['runStatus'], 'data-run-id' => $run['info']['id'], 'data-run-status' => $uaRun['runStatus'], 'data-useragent-id' => $uaID, 'data-client-id' => isset($uaRun['clientID']) ? $uaRun['clientID'] : '')); if (isset($uaRun['runResultsUrl']) && isset($uaRun['runResultsLabel'])) { $title = $userAgents[$uaID]['displayInfo']['title']; $runResultsTooltip = "Open run results for {$title}"; $runResultsTagOpen = html_tag_open('a', array('rel' => 'nofollow', 'href' => $uaRun['runResultsUrl'], 'title' => $runResultsTooltip)); $html .= $runResultsTagOpen . self::getStatusIconHtml($uaRun['runStatus']) . '</a>' . ($showResetRun ? html_tag('i', array('class' => 'swarm-reset-run-single icon-remove-circle pull-right', 'title' => "Re-schedule run for {$title}")) : ''); } else { $html .= self::getStatusIconHtml($uaRun['runStatus']); } $html .= '</td>'; } else { // This run isn't schedules to be ran in this UA $html .= '<td class="swarm-status swarm-status-notscheduled"></td>'; } } } return $html; }
protected function getPageLink($path, $label) { return html_tag_open('li', array('class' => strpos($this->getSelfPath(), $path) === 0 ? 'active' : null)) . html_tag('a', array('href' => swarmpath($path === 'home' ? '' : $path)), $label) . '</li>' . "\n"; }
/** * @param Array $data Details data from ClientsAction * @return string: HTML */ protected function showDetails($data) { $html = '<div class="row">'; foreach ($data['clients'] as $client) { $displayInfo = $client['uaData']['displayInfo']; $html .= '<div class="span4 swarm-client"><div class="well">' . '<div class="swarm-client-icon">' . BrowserInfo::buildIconHtml($displayInfo, array('wrap' => false)) . '</div>' . '<div class="swarm-client-info">' . '<p class="swarm-client-title">' . htmlspecialchars($displayInfo['title']) . '</p>' . '<table class="table table-condensed">' . '<tbody>' . '<tr><th>Last ping</th><td>' . self::getPrettyDateHtml($client, 'pinged') . '</td></tr>' . '<tr><th>Run</th>' . (!$client['lastResult'] ? '<td><span class="muted">Waiting for runs...</span></td>' : '<td class="swarm-status-' . $client['lastResult']['status'] . '">' . html_tag_open('a', array('href' => $client['lastResult']['viewUrl'])) . htmlspecialchars("#{$client['lastResult']['id']}") . ' ' . JobPage::getStatusIconHtml($client['lastResult']['status']) . '</a></td>') . '</tr>' . '<tr><th>Connected</th><td>' . self::getPrettyDateHtml($client, 'connected') . '</td></tr>' . '</tbody>' . '</table>' . '</div>' . '<div class="clearfix"><a href="' . htmlspecialchars($client['viewUrl']) . '" class="pull-right">Details »</a></div>' . '</div></div>'; } return $html . '</div>'; }
/** @return string: HTML */ public static function buildIconHtml(array $displayInfo, array $options = null) { $classes = ''; $afterHtml = ''; if (isset($options['size']) && $options['size'] === 'small') { $classes .= ' swarm-icon-small'; } $labelHtml = isset($options['label']) ? $options['label'] : $displayInfo['labelHtml']; if ($labelHtml) { $afterHtml .= '<br>' . html_tag_open('span', array('class' => 'badge swarm-browsername')) . $labelHtml . '</span>'; } if (isset($options['wrap']) && !$options['wrap']) { return html_tag('div', array('class' => $displayInfo['class'] . $classes, 'title' => $displayInfo['title'])); } return '' . html_tag_open('div', array('class' => 'well well-swarm-icon')) . html_tag('div', array('class' => $displayInfo['class'] . $classes, 'title' => $displayInfo['title'])) . $afterHtml . '</div>'; }