Path: blob/master/src/applications/chatlog/controller/PhabricatorChatLogChannelLogController.php
12242 views
<?php12final class PhabricatorChatLogChannelLogController3extends PhabricatorChatLogController {45public function shouldAllowPublic() {6return true;7}89public function handleRequest(AphrontRequest $request) {10$viewer = $request->getViewer();11$id = $request->getURIData('channelID');1213$uri = new PhutilURI($request->getPath());1415$pager = new AphrontCursorPagerView();16$pager->setURI($uri);17$pager->setPageSize(250);1819$query = id(new PhabricatorChatLogQuery())20->setViewer($viewer)21->withChannelIDs(array($id));2223$channel = id(new PhabricatorChatLogChannelQuery())24->setViewer($viewer)25->withIDs(array($id))26->executeOne();2728if (!$channel) {29return new Aphront404Response();30}3132list($after, $before, $map) = $this->getPagingParameters($request, $query);3334$pager->setAfterID($after);35$pager->setBeforeID($before);3637$logs = $query->executeWithCursorPager($pager);3839// Show chat logs oldest-first.40$logs = array_reverse($logs);414243// Divide all the logs into blocks, where a block is the same author saying44// several things in a row. A block ends when another user speaks, or when45// two minutes pass without the author speaking.4647$blocks = array();48$block = null;4950$last_author = null;51$last_epoch = null;52foreach ($logs as $log) {53$this_author = $log->getAuthor();54$this_epoch = $log->getEpoch();5556// Decide whether we should start a new block or not.57$new_block = ($this_author !== $last_author) ||58($this_epoch - (60 * 2) > $last_epoch);5960if ($new_block) {61if ($block) {62$blocks[] = $block;63}64$block = array(65'id' => $log->getID(),66'epoch' => $this_epoch,67'author' => $this_author,68'logs' => array($log),69);70} else {71$block['logs'][] = $log;72}7374$last_author = $this_author;75$last_epoch = $this_epoch;76}77if ($block) {78$blocks[] = $block;79}8081// Figure out CSS classes for the blocks. We alternate colors between82// lines, and highlight the entire block which contains the target ID or83// date, if applicable.8485foreach ($blocks as $key => $block) {86$classes = array();87if ($key % 2) {88$classes[] = 'alternate';89}90$ids = mpull($block['logs'], 'getID', 'getID');91if (array_intersect_key($ids, $map)) {92$classes[] = 'highlight';93}94$blocks[$key]['class'] = $classes ? implode(' ', $classes) : null;95}969798require_celerity_resource('phabricator-chatlog-css');99100$out = array();101foreach ($blocks as $block) {102$author = $block['author'];103$author = id(new PhutilUTF8StringTruncator())104->setMaximumGlyphs(18)105->truncateString($author);106$author = phutil_tag('td', array('class' => 'author'), $author);107108$href = $uri->alter('at', $block['id']);109$timestamp = $block['epoch'];110$timestamp = phabricator_datetime($timestamp, $viewer);111$timestamp = phutil_tag(112'a',113array(114'href' => $href,115'class' => 'timestamp',116),117$timestamp);118119$message = mpull($block['logs'], 'getMessage');120$message = implode("\n", $message);121$message = phutil_tag(122'td',123array(124'class' => 'message',125),126array(127$timestamp,128$message,129));130131$out[] = phutil_tag(132'tr',133array(134'class' => $block['class'],135),136array(137$author,138$message,139));140}141142$links = array();143144$first_uri = $pager->getFirstPageURI();145if ($first_uri) {146$links[] = phutil_tag(147'a',148array(149'href' => $first_uri,150),151"\xC2\xAB ".pht('Newest'));152}153154$prev_uri = $pager->getPrevPageURI();155if ($prev_uri) {156$links[] = phutil_tag(157'a',158array(159'href' => $prev_uri,160),161"\xE2\x80\xB9 ".pht('Newer'));162}163164$next_uri = $pager->getNextPageURI();165if ($next_uri) {166$links[] = phutil_tag(167'a',168array(169'href' => $next_uri,170),171pht('Older')." \xE2\x80\xBA");172}173174$pager_bottom = phutil_tag(175'div',176array('class' => 'phabricator-chat-log-pager-bottom'),177$links);178179$crumbs = $this180->buildApplicationCrumbs()181->addTextCrumb($channel->getChannelName(), $uri);182183$form = id(new AphrontFormView())184->setUser($viewer)185->setMethod('GET')186->setAction($uri)187->appendChild(188id(new AphrontFormTextControl())189->setLabel(pht('Date'))190->setName('date')191->setValue($request->getStr('date')))192->appendChild(193id(new AphrontFormSubmitControl())194->setValue(pht('Jump')));195196$table = phutil_tag(197'table',198array(199'class' => 'phabricator-chat-log',200),201$out);202203$log = phutil_tag(204'div',205array(206'class' => 'phabricator-chat-log-panel',207),208$table);209210$jump_link = id(new PHUIButtonView())211->setTag('a')212->setHref('#latest')213->setText(pht('Jump to Bottom'))214->setIcon('fa-arrow-circle-down');215216$jump_target = phutil_tag(217'div',218array(219'id' => 'latest',220));221222$content = phutil_tag(223'div',224array(225'class' => 'phabricator-chat-log-wrap',226),227array(228$log,229$jump_target,230$pager_bottom,231));232233$header = id(new PHUIHeaderView())234->setHeader($channel->getChannelName())235->setSubHeader($channel->getServiceName())236->addActionLink($jump_link);237238$box = id(new PHUIObjectBoxView())239->setHeader($header)240->setCollapsed(true)241->appendChild($content);242243$box->setShowHide(244pht('Search Dates'),245pht('Hide Dates'),246$form,247'#');248249return $this->newPage()250->setTitle(pht('Channel Log'))251->setCrumbs($crumbs)252->appendChild($box);253254}255256/**257* From request parameters, figure out where we should jump to in the log.258* We jump to either a date or log ID, but load a few lines of context before259* it so the user can see the nearby conversation.260*/261private function getPagingParameters(262AphrontRequest $request,263PhabricatorChatLogQuery $query) {264265$viewer = $request->getViewer();266267$at_id = $request->getInt('at');268$at_date = $request->getStr('date');269270$context_log = null;271$map = array();272273$query = clone $query;274$query->setLimit(8);275276if ($at_id) {277// Jump to the log in question, and load a few lines of context before278// it.279$context_logs = $query280->setAfterID($at_id)281->execute();282283$context_log = last($context_logs);284285$map = array(286$at_id => true,287);288289} else if ($at_date) {290$timestamp = PhabricatorTime::parseLocalTime($at_date, $viewer);291292if ($timestamp) {293$context_logs = $query294->withMaximumEpoch($timestamp)295->execute();296297$context_log = last($context_logs);298299$target_log = head($context_logs);300if ($target_log) {301$map = array(302$target_log->getID() => true,303);304}305}306}307308if ($context_log) {309$after = null;310$before = $context_log->getID() - 1;311} else {312$after = $request->getInt('after');313$before = $request->getInt('before');314}315316return array($after, $before, $map);317}318319}320321322