1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

Remove Chatlog entirely

Summary:
This commit removes ChatLog entirely.  All of the application files are removed, and the migrations used are stubbed out. I stubbed the migrations as that allows for existing installs to make no changes, but new installs will not create the database.

Fixes T15126

Test Plan: Loaded up http://phorge.local/chatlog and confirmed the 404.  Loaded up http://phorge.local/applications/view/PhabricatorChatLogApplication and confirmed the 404.  Created a new database prefix and ran `bin/storage upgrade` against it, confirmed that the chatlog database was not created.  Restored another prefix (an old one) and ran `bin/storage upgrade` and confirmed database was not deleted.

Reviewers: O1 Blessed Committers, avivey

Reviewed By: O1 Blessed Committers, avivey

Subscribers: avivey, tobiaswiese, valerio.bozzolan, Cigaryno

Maniphest Tasks: T15126

Differential Revision: https://we.phorge.it/D25480
This commit is contained in:
Matthew Bowker 2023-11-27 11:36:12 -07:00
parent cf8d5d60a5
commit 4d4712b58d
25 changed files with 5 additions and 1080 deletions

View file

@ -42,7 +42,6 @@ return array(
'rsrc/css/application/base/notification-menu.css' => '4df1ee30', 'rsrc/css/application/base/notification-menu.css' => '4df1ee30',
'rsrc/css/application/base/phui-theme.css' => '35883b37', 'rsrc/css/application/base/phui-theme.css' => '35883b37',
'rsrc/css/application/base/standard-page-view.css' => 'e08c7462', 'rsrc/css/application/base/standard-page-view.css' => 'e08c7462',
'rsrc/css/application/chatlog/chatlog.css' => 'abdc76ee',
'rsrc/css/application/conduit/conduit-api.css' => 'ce2cfc41', 'rsrc/css/application/conduit/conduit-api.css' => 'ce2cfc41',
'rsrc/css/application/config/config-options.css' => '16c920ae', 'rsrc/css/application/config/config-options.css' => '16c920ae',
'rsrc/css/application/config/config-template.css' => 'e689dbbd', 'rsrc/css/application/config/config-template.css' => 'e689dbbd',
@ -770,7 +769,6 @@ return array(
'people-profile-css' => '2ea2daa1', 'people-profile-css' => '2ea2daa1',
'phabricator-action-list-view-css' => '1b0085b2', 'phabricator-action-list-view-css' => '1b0085b2',
'phabricator-busy' => '5202e831', 'phabricator-busy' => '5202e831',
'phabricator-chatlog-css' => 'abdc76ee',
'phabricator-content-source-view-css' => 'cdf0d579', 'phabricator-content-source-view-css' => 'cdf0d579',
'phabricator-core-css' => 'b3a5928e', 'phabricator-core-css' => 'b3a5928e',
'phabricator-countdown-css' => 'bff8012f', 'phabricator-countdown-css' => 'bff8012f',

View file

@ -4,7 +4,6 @@ $applications = array(
'Audit', 'Audit',
'Auth', 'Auth',
'Calendar', 'Calendar',
'ChatLog',
'Conduit', 'Conduit',
'Config', 'Config',
'Conpherence', 'Conpherence',

View file

@ -1,10 +1 @@
CREATE TABLE {$NAMESPACE}_chatlog.chatlog_event ( /* This file is intentionally left empty, see T15126 */
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
channel VARCHAR(64) BINARY NOT NULL,
epoch INT UNSIGNED NOT NULL,
author VARCHAR(64) BINARY NOT NULL,
type VARCHAR(4) NOT NULL,
message LONGBLOB NOT NULL,
loggedByPHID VARCHAR(64) BINARY NOT NULL,
KEY (channel, epoch)
);

View file

@ -16,24 +16,6 @@ ALTER TABLE `{$NAMESPACE}_audit`.`audit_comment`
ALTER DATABASE `{$NAMESPACE}_chatlog` COLLATE utf8_general_ci;
ALTER TABLE `{$NAMESPACE}_chatlog`.`chatlog_event`
MODIFY `channel` varchar(64) CHARACTER SET binary,
MODIFY `author` varchar(64) CHARACTER SET binary,
MODIFY `type` varchar(4) CHARACTER SET binary,
MODIFY `message` longtext CHARACTER SET binary,
MODIFY `loggedByPHID` varchar(64) CHARACTER SET binary;
ALTER TABLE `{$NAMESPACE}_chatlog`.`chatlog_event`
COLLATE utf8_general_ci,
MODIFY `channel` varchar(64) COLLATE utf8_bin NOT NULL,
MODIFY `author` varchar(64) COLLATE utf8_bin NOT NULL,
MODIFY `type` varchar(4) COLLATE utf8_general_ci NOT NULL,
MODIFY `message` longtext COLLATE utf8_bin NOT NULL,
MODIFY `loggedByPHID` varchar(64) COLLATE utf8_bin NOT NULL;
ALTER DATABASE `{$NAMESPACE}_conduit` COLLATE utf8_general_ci; ALTER DATABASE `{$NAMESPACE}_conduit` COLLATE utf8_general_ci;
ALTER TABLE `{$NAMESPACE}_conduit`.`conduit_certificatetoken` ALTER TABLE `{$NAMESPACE}_conduit`.`conduit_certificatetoken`

View file

@ -1,11 +1 @@
CREATE TABLE {$NAMESPACE}_chatlog.chatlog_channel ( /* This file is intentionally left empty, see T15126 */
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
serviceName VARCHAR(64) COLLATE utf8_bin NOT NULL,
serviceType VARCHAR(32) COLLATE utf8_bin NOT NULL,
channelName VARCHAR(64) COLLATE utf8_bin NOT NULL,
viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL,
editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_channel` (channelName, serviceType, serviceName)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -1,2 +1 @@
ALTER TABLE `{$NAMESPACE}_chatlog`.`chatlog_event` /* This file is intentionally left empty, see T15126 */
ADD `channelID` INT UNSIGNED NOT NULL;

View file

@ -1,64 +1,3 @@
<?php <?php
echo pht('Updating channel IDs of previous chatlog events...')."\n"; /* This file is intentionally left empty, see T15126 */
$event_table = new PhabricatorChatLogEvent();
$channel_table = new PhabricatorChatLogChannel();
$event_table->openTransaction();
$channel_table->openTransaction();
$event_table->beginReadLocking();
$channel_table->beginReadLocking();
$events = new LiskMigrationIterator($event_table);
$conn_w = $channel_table->establishConnection('w');
foreach ($events as $event) {
if ($event->getChannelID()) {
continue;
}
$event_row = queryfx_one(
$conn_w,
'SELECT channel FROM %T WHERE id = %d',
$event->getTableName(),
$event->getID());
$event_channel = $event_row['channel'];
$matched = queryfx_one(
$conn_w,
'SELECT * FROM %T WHERE
channelName = %s AND serviceName = %s AND serviceType = %s',
$channel_table->getTableName(),
$event_channel,
'',
'');
if (!$matched) {
$matched = id(new PhabricatorChatLogChannel())
->setChannelName($event_channel)
->setServiceType('')
->setServiceName('')
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
->setEditPolicy(PhabricatorPolicies::POLICY_USER)
->save();
$matched_id = $matched->getID();
} else {
$matched_id = $matched['id'];
}
queryfx(
$event->establishConnection('w'),
'UPDATE %T SET channelID = %d WHERE id = %d',
$event->getTableName(),
$matched_id,
$event->getID());
}
$event_table->endReadLocking();
$channel_table->endReadLocking();
$event_table->saveTransaction();
$channel_table->saveTransaction();
echo "\n".pht('Done.')."\n";

View file

@ -1,2 +1 @@
ALTER TABLE `{$NAMESPACE}_chatlog`.`chatlog_event` /* This file is intentionally left empty, see T15126 */
DROP channel;

View file

@ -1477,45 +1477,6 @@ CREATE TABLE `edgedata` (
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_chatlog` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */;
USE `{$NAMESPACE}_chatlog`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `chatlog_channel` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`serviceName` varchar(64) CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`serviceType` varchar(32) CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`channelName` varchar(64) CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`viewPolicy` varbinary(64) NOT NULL,
`editPolicy` varbinary(64) NOT NULL,
`dateCreated` int(10) unsigned NOT NULL,
`dateModified` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `key_channel` (`channelName`,`serviceType`,`serviceName`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
USE `{$NAMESPACE}_chatlog`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `chatlog_event` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`epoch` int(10) unsigned NOT NULL,
`author` varchar(64) CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`type` varchar(4) CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`message` longtext CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`loggedByPHID` varbinary(64) NOT NULL,
`channelID` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `channel` (`epoch`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_conduit` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */; CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_conduit` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */;
USE `{$NAMESPACE}_conduit`; USE `{$NAMESPACE}_conduit`;

View file

@ -339,9 +339,6 @@ phutil_register_library_map(array(
'CelerityResourcesOnDisk' => 'applications/celerity/resources/CelerityResourcesOnDisk.php', 'CelerityResourcesOnDisk' => 'applications/celerity/resources/CelerityResourcesOnDisk.php',
'CeleritySpriteGenerator' => 'applications/celerity/CeleritySpriteGenerator.php', 'CeleritySpriteGenerator' => 'applications/celerity/CeleritySpriteGenerator.php',
'CelerityStaticResourceResponse' => 'applications/celerity/CelerityStaticResourceResponse.php', 'CelerityStaticResourceResponse' => 'applications/celerity/CelerityStaticResourceResponse.php',
'ChatLogConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogConduitAPIMethod.php',
'ChatLogQueryConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogQueryConduitAPIMethod.php',
'ChatLogRecordConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogRecordConduitAPIMethod.php',
'ConduitAPIDocumentationPage' => 'applications/conduit/data/ConduitAPIDocumentationPage.php', 'ConduitAPIDocumentationPage' => 'applications/conduit/data/ConduitAPIDocumentationPage.php',
'ConduitAPIMethod' => 'applications/conduit/method/ConduitAPIMethod.php', 'ConduitAPIMethod' => 'applications/conduit/method/ConduitAPIMethod.php',
'ConduitAPIMethodTestCase' => 'applications/conduit/method/__tests__/ConduitAPIMethodTestCase.php', 'ConduitAPIMethodTestCase' => 'applications/conduit/method/__tests__/ConduitAPIMethodTestCase.php',
@ -2808,15 +2805,6 @@ phutil_register_library_map(array(
'PhabricatorChartInterval' => 'applications/fact/chart/PhabricatorChartInterval.php', 'PhabricatorChartInterval' => 'applications/fact/chart/PhabricatorChartInterval.php',
'PhabricatorChartRenderingEngine' => 'applications/fact/engine/PhabricatorChartRenderingEngine.php', 'PhabricatorChartRenderingEngine' => 'applications/fact/engine/PhabricatorChartRenderingEngine.php',
'PhabricatorChartStackedAreaDataset' => 'applications/fact/chart/PhabricatorChartStackedAreaDataset.php', 'PhabricatorChartStackedAreaDataset' => 'applications/fact/chart/PhabricatorChartStackedAreaDataset.php',
'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php',
'PhabricatorChatLogChannel' => 'applications/chatlog/storage/PhabricatorChatLogChannel.php',
'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/PhabricatorChatLogChannelListController.php',
'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/PhabricatorChatLogChannelLogController.php',
'PhabricatorChatLogChannelQuery' => 'applications/chatlog/query/PhabricatorChatLogChannelQuery.php',
'PhabricatorChatLogController' => 'applications/chatlog/controller/PhabricatorChatLogController.php',
'PhabricatorChatLogDAO' => 'applications/chatlog/storage/PhabricatorChatLogDAO.php',
'PhabricatorChatLogEvent' => 'applications/chatlog/storage/PhabricatorChatLogEvent.php',
'PhabricatorChatLogQuery' => 'applications/chatlog/query/PhabricatorChatLogQuery.php',
'PhabricatorCheckboxesEditField' => 'applications/transactions/editfield/PhabricatorCheckboxesEditField.php', 'PhabricatorCheckboxesEditField' => 'applications/transactions/editfield/PhabricatorCheckboxesEditField.php',
'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php', 'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php',
'PhabricatorClassConfigType' => 'applications/config/type/PhabricatorClassConfigType.php', 'PhabricatorClassConfigType' => 'applications/config/type/PhabricatorClassConfigType.php',
@ -6339,9 +6327,6 @@ phutil_register_library_map(array(
'CelerityResourcesOnDisk' => 'CelerityPhysicalResources', 'CelerityResourcesOnDisk' => 'CelerityPhysicalResources',
'CeleritySpriteGenerator' => 'Phobject', 'CeleritySpriteGenerator' => 'Phobject',
'CelerityStaticResourceResponse' => 'Phobject', 'CelerityStaticResourceResponse' => 'Phobject',
'ChatLogConduitAPIMethod' => 'ConduitAPIMethod',
'ChatLogQueryConduitAPIMethod' => 'ChatLogConduitAPIMethod',
'ChatLogRecordConduitAPIMethod' => 'ChatLogConduitAPIMethod',
'ConduitAPIDocumentationPage' => 'Phobject', 'ConduitAPIDocumentationPage' => 'Phobject',
'ConduitAPIMethod' => array( 'ConduitAPIMethod' => array(
'Phobject', 'Phobject',
@ -9191,21 +9176,6 @@ phutil_register_library_map(array(
'PhabricatorChartInterval' => 'Phobject', 'PhabricatorChartInterval' => 'Phobject',
'PhabricatorChartRenderingEngine' => 'Phobject', 'PhabricatorChartRenderingEngine' => 'Phobject',
'PhabricatorChartStackedAreaDataset' => 'PhabricatorChartDataset', 'PhabricatorChartStackedAreaDataset' => 'PhabricatorChartDataset',
'PhabricatorChatLogApplication' => 'PhabricatorApplication',
'PhabricatorChatLogChannel' => array(
'PhabricatorChatLogDAO',
'PhabricatorPolicyInterface',
),
'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController',
'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController',
'PhabricatorChatLogChannelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorChatLogController' => 'PhabricatorController',
'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO',
'PhabricatorChatLogEvent' => array(
'PhabricatorChatLogDAO',
'PhabricatorPolicyInterface',
),
'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorCheckboxesEditField' => 'PhabricatorEditField', 'PhabricatorCheckboxesEditField' => 'PhabricatorEditField',
'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorClassConfigType' => 'PhabricatorTextConfigType', 'PhabricatorClassConfigType' => 'PhabricatorTextConfigType',

View file

@ -1,47 +0,0 @@
<?php
final class PhabricatorChatLogApplication extends PhabricatorApplication {
public function getBaseURI() {
return '/chatlog/';
}
public function getName() {
return pht('ChatLog');
}
public function getShortDescription() {
return pht('IRC Logs');
}
public function getIcon() {
return 'fa-coffee';
}
public function isPrototype() {
return true;
}
public function isDeprecated() {
return true;
}
public function getTitleGlyph() {
return "\xE0\xBC\x84";
}
public function getApplicationGroup() {
return self::GROUP_UTILITIES;
}
public function getRoutes() {
return array(
'/chatlog/' => array(
'' => 'PhabricatorChatLogChannelListController',
'channel/(?P<channelID>[^/]+)/'
=> 'PhabricatorChatLogChannelLogController',
),
);
}
}

View file

@ -1,9 +0,0 @@
<?php
abstract class ChatLogConduitAPIMethod extends ConduitAPIMethod {
final public function getApplication() {
return PhabricatorApplication::getByClass('PhabricatorChatLogApplication');
}
}

View file

@ -1,59 +0,0 @@
<?php
final class ChatLogQueryConduitAPIMethod extends ChatLogConduitAPIMethod {
public function getAPIMethodName() {
return 'chatlog.query';
}
public function getMethodStatus() {
return self::METHOD_STATUS_UNSTABLE;
}
public function getMethodDescription() {
return pht('Retrieve chatter.');
}
protected function defineParamTypes() {
return array(
'channels' => 'optional list<string>',
'limit' => 'optional int (default = 100)',
);
}
protected function defineReturnType() {
return 'nonempty list<dict>';
}
protected function execute(ConduitAPIRequest $request) {
$query = new PhabricatorChatLogQuery();
$channel_ids = $request->getValue('channelIDs');
if ($channel_ids) {
$query->withChannelIDs($channel_ids);
}
$limit = $request->getValue('limit');
if (!$limit) {
$limit = 100;
}
$query->setLimit($limit);
$logs = $query->execute();
$results = array();
foreach ($logs as $log) {
$results[] = array(
'channelID' => $log->getChannelID(),
'epoch' => $log->getEpoch(),
'author' => $log->getAuthor(),
'type' => $log->getType(),
'message' => $log->getMessage(),
'loggedByPHID' => $log->getLoggedByPHID(),
);
}
return $results;
}
}

View file

@ -1,72 +0,0 @@
<?php
final class ChatLogRecordConduitAPIMethod extends ChatLogConduitAPIMethod {
public function getAPIMethodName() {
return 'chatlog.record';
}
public function getMethodStatus() {
return self::METHOD_STATUS_UNSTABLE;
}
public function getMethodDescription() {
return pht('Record chatter.');
}
protected function defineParamTypes() {
return array(
'logs' => 'required list<dict>',
);
}
protected function defineReturnType() {
return 'list<id>';
}
protected function execute(ConduitAPIRequest $request) {
$logs = $request->getValue('logs');
if (!is_array($logs)) {
$logs = array();
}
$template = new PhabricatorChatLogEvent();
$template->setLoggedByPHID($request->getUser()->getPHID());
$objs = array();
foreach ($logs as $log) {
$channel_name = idx($log, 'channel');
$service_name = idx($log, 'serviceName');
$service_type = idx($log, 'serviceType');
$channel = id(new PhabricatorChatLogChannel())->loadOneWhere(
'channelName = %s AND serviceName = %s AND serviceType = %s',
$channel_name,
$service_name,
$service_type);
if (!$channel) {
$channel = id(new PhabricatorChatLogChannel())
->setChannelName($channel_name)
->setserviceName($service_name)
->setServiceType($service_type)
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
->setEditPolicy(PhabricatorPolicies::POLICY_USER)
->save();
}
$obj = clone $template;
$obj->setChannelID($channel->getID());
$obj->setType(idx($log, 'type'));
$obj->setAuthor(idx($log, 'author'));
$obj->setEpoch(idx($log, 'epoch'));
$obj->setMessage(idx($log, 'message'));
$obj->save();
$objs[] = $obj;
}
return array_values(mpull($objs, 'getID'));
}
}

View file

@ -1,41 +0,0 @@
<?php
final class PhabricatorChatLogChannelListController
extends PhabricatorChatLogController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$channels = id(new PhabricatorChatLogChannelQuery())
->setViewer($viewer)
->execute();
$list = new PHUIObjectItemListView();
foreach ($channels as $channel) {
$item = id(new PHUIObjectItemView())
->setHeader($channel->getChannelName())
->setHref('/chatlog/channel/'.$channel->getID().'/')
->addAttribute($channel->getServiceName())
->addAttribute($channel->getServiceType());
$list->addItem($item);
}
$crumbs = $this
->buildApplicationCrumbs()
->addTextCrumb(pht('Channel List'), $this->getApplicationURI());
$box = id(new PHUIObjectBoxView())
->setHeaderText('Channel List')
->setObjectList($list);
return $this->newPage()
->setTitle(pht('Channel List'))
->setCrumbs($crumbs)
->appendChild($box);
}
}

View file

@ -1,320 +0,0 @@
<?php
final class PhabricatorChatLogChannelLogController
extends PhabricatorChatLogController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('channelID');
$uri = new PhutilURI($request->getPath());
$pager = new AphrontCursorPagerView();
$pager->setURI($uri);
$pager->setPageSize(250);
$query = id(new PhabricatorChatLogQuery())
->setViewer($viewer)
->withChannelIDs(array($id));
$channel = id(new PhabricatorChatLogChannelQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$channel) {
return new Aphront404Response();
}
list($after, $before, $map) = $this->getPagingParameters($request, $query);
$pager->setAfterID($after);
$pager->setBeforeID($before);
$logs = $query->executeWithCursorPager($pager);
// Show chat logs oldest-first.
$logs = array_reverse($logs);
// Divide all the logs into blocks, where a block is the same author saying
// several things in a row. A block ends when another user speaks, or when
// two minutes pass without the author speaking.
$blocks = array();
$block = null;
$last_author = null;
$last_epoch = null;
foreach ($logs as $log) {
$this_author = $log->getAuthor();
$this_epoch = $log->getEpoch();
// Decide whether we should start a new block or not.
$new_block = ($this_author !== $last_author) ||
($this_epoch - (60 * 2) > $last_epoch);
if ($new_block) {
if ($block) {
$blocks[] = $block;
}
$block = array(
'id' => $log->getID(),
'epoch' => $this_epoch,
'author' => $this_author,
'logs' => array($log),
);
} else {
$block['logs'][] = $log;
}
$last_author = $this_author;
$last_epoch = $this_epoch;
}
if ($block) {
$blocks[] = $block;
}
// Figure out CSS classes for the blocks. We alternate colors between
// lines, and highlight the entire block which contains the target ID or
// date, if applicable.
foreach ($blocks as $key => $block) {
$classes = array();
if ($key % 2) {
$classes[] = 'alternate';
}
$ids = mpull($block['logs'], 'getID', 'getID');
if (array_intersect_key($ids, $map)) {
$classes[] = 'highlight';
}
$blocks[$key]['class'] = $classes ? implode(' ', $classes) : null;
}
require_celerity_resource('phabricator-chatlog-css');
$out = array();
foreach ($blocks as $block) {
$author = $block['author'];
$author = id(new PhutilUTF8StringTruncator())
->setMaximumGlyphs(18)
->truncateString($author);
$author = phutil_tag('td', array('class' => 'author'), $author);
$href = $uri->alter('at', $block['id']);
$timestamp = $block['epoch'];
$timestamp = phabricator_datetime($timestamp, $viewer);
$timestamp = phutil_tag(
'a',
array(
'href' => $href,
'class' => 'timestamp',
),
$timestamp);
$message = mpull($block['logs'], 'getMessage');
$message = implode("\n", $message);
$message = phutil_tag(
'td',
array(
'class' => 'message',
),
array(
$timestamp,
$message,
));
$out[] = phutil_tag(
'tr',
array(
'class' => $block['class'],
),
array(
$author,
$message,
));
}
$links = array();
$first_uri = $pager->getFirstPageURI();
if ($first_uri) {
$links[] = phutil_tag(
'a',
array(
'href' => $first_uri,
),
"\xC2\xAB ".pht('Newest'));
}
$prev_uri = $pager->getPrevPageURI();
if ($prev_uri) {
$links[] = phutil_tag(
'a',
array(
'href' => $prev_uri,
),
"\xE2\x80\xB9 ".pht('Newer'));
}
$next_uri = $pager->getNextPageURI();
if ($next_uri) {
$links[] = phutil_tag(
'a',
array(
'href' => $next_uri,
),
pht('Older')." \xE2\x80\xBA");
}
$pager_bottom = phutil_tag(
'div',
array('class' => 'phabricator-chat-log-pager-bottom'),
$links);
$crumbs = $this
->buildApplicationCrumbs()
->addTextCrumb($channel->getChannelName(), $uri);
$form = id(new AphrontFormView())
->setUser($viewer)
->setMethod('GET')
->setAction($uri)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Date'))
->setName('date')
->setValue($request->getStr('date')))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Jump')));
$table = phutil_tag(
'table',
array(
'class' => 'phabricator-chat-log',
),
$out);
$log = phutil_tag(
'div',
array(
'class' => 'phabricator-chat-log-panel',
),
$table);
$jump_link = id(new PHUIButtonView())
->setTag('a')
->setHref('#latest')
->setText(pht('Jump to Bottom'))
->setIcon('fa-arrow-circle-down');
$jump_target = phutil_tag(
'div',
array(
'id' => 'latest',
));
$content = phutil_tag(
'div',
array(
'class' => 'phabricator-chat-log-wrap',
),
array(
$log,
$jump_target,
$pager_bottom,
));
$header = id(new PHUIHeaderView())
->setHeader($channel->getChannelName())
->setSubHeader($channel->getServiceName())
->addActionLink($jump_link);
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->setCollapsed(true)
->appendChild($content);
$box->setShowHide(
pht('Search Dates'),
pht('Hide Dates'),
$form,
'#');
return $this->newPage()
->setTitle(pht('Channel Log'))
->setCrumbs($crumbs)
->appendChild($box);
}
/**
* From request parameters, figure out where we should jump to in the log.
* We jump to either a date or log ID, but load a few lines of context before
* it so the user can see the nearby conversation.
*/
private function getPagingParameters(
AphrontRequest $request,
PhabricatorChatLogQuery $query) {
$viewer = $request->getViewer();
$at_id = $request->getInt('at');
$at_date = $request->getStr('date');
$context_log = null;
$map = array();
$query = clone $query;
$query->setLimit(8);
if ($at_id) {
// Jump to the log in question, and load a few lines of context before
// it.
$context_logs = $query
->setAfterID($at_id)
->execute();
$context_log = last($context_logs);
$map = array(
$at_id => true,
);
} else if ($at_date) {
$timestamp = PhabricatorTime::parseLocalTime($at_date, $viewer);
if ($timestamp) {
$context_logs = $query
->withMaximumEpoch($timestamp)
->execute();
$context_log = last($context_logs);
$target_log = head($context_logs);
if ($target_log) {
$map = array(
$target_log->getID() => true,
);
}
}
}
if ($context_log) {
$after = null;
$before = $context_log->getID() - 1;
} else {
$after = $request->getInt('after');
$before = $request->getInt('before');
}
return array($after, $before, $map);
}
}

View file

@ -1,3 +0,0 @@
<?php
abstract class PhabricatorChatLogController extends PhabricatorController {}

View file

@ -1,63 +0,0 @@
<?php
final class PhabricatorChatLogChannelQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $channels;
private $channelIDs;
public function withChannelNames(array $channels) {
$this->channels = $channels;
return $this;
}
public function withIDs(array $channel_ids) {
$this->channelIDs = $channel_ids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorChatLogChannel();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T c %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$logs = $table->loadAllFromArray($data);
return $logs;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->channelIDs) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->channelIDs);
}
if ($this->channels) {
$where[] = qsprintf(
$conn,
'channelName IN (%Ls)',
$this->channels);
}
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
return 'PhabricatorChatLogApplication';
}
}

View file

@ -1,84 +0,0 @@
<?php
final class PhabricatorChatLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $channelIDs;
private $maximumEpoch;
public function withChannelIDs(array $channel_ids) {
$this->channelIDs = $channel_ids;
return $this;
}
public function withMaximumEpoch($epoch) {
$this->maximumEpoch = $epoch;
return $this;
}
protected function loadPage() {
$table = new PhabricatorChatLogEvent();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T e %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$logs = $table->loadAllFromArray($data);
return $logs;
}
protected function willFilterPage(array $events) {
$channel_ids = mpull($events, 'getChannelID', 'getChannelID');
$channels = id(new PhabricatorChatLogChannelQuery())
->setViewer($this->getViewer())
->withIDs($channel_ids)
->execute();
$channels = mpull($channels, null, 'getID');
foreach ($events as $key => $event) {
$channel = idx($channels, $event->getChannelID());
if (!$channel) {
unset($events[$key]);
continue;
}
$event->attachChannel($channel);
}
return $events;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->maximumEpoch !== null) {
$where[] = qsprintf(
$conn,
'epoch <= %d',
$this->maximumEpoch);
}
if ($this->channelIDs !== null) {
$where[] = qsprintf(
$conn,
'channelID IN (%Ld)',
$this->channelIDs);
}
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
return 'PhabricatorChatLogApplication';
}
}

View file

@ -1,51 +0,0 @@
<?php
final class PhabricatorChatLogChannel
extends PhabricatorChatLogDAO
implements PhabricatorPolicyInterface {
protected $serviceName;
protected $serviceType;
protected $channelName;
protected $viewPolicy;
protected $editPolicy;
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'serviceName' => 'text64',
'serviceType' => 'text32',
'channelName' => 'text64',
),
self::CONFIG_KEY_SCHEMA => array(
'key_channel' => array(
'columns' => array('channelName', 'serviceType', 'serviceName'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->viewPolicy;
break;
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->editPolicy;
break;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
}

View file

@ -1,9 +0,0 @@
<?php
abstract class PhabricatorChatLogDAO extends PhabricatorLiskDAO {
public function getApplicationName() {
return 'chatlog';
}
}

View file

@ -1,59 +0,0 @@
<?php
final class PhabricatorChatLogEvent
extends PhabricatorChatLogDAO
implements PhabricatorPolicyInterface {
protected $channelID;
protected $epoch;
protected $author;
protected $type;
protected $message;
protected $loggedByPHID;
private $channel = self::ATTACHABLE;
protected function getConfiguration() {
return array(
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_COLUMN_SCHEMA => array(
'author' => 'text64',
'type' => 'text4',
'message' => 'text',
),
self::CONFIG_KEY_SCHEMA => array(
'channel' => array(
'columns' => array('epoch'),
),
),
) + parent::getConfiguration();
}
public function attachChannel(PhabricatorChatLogChannel $channel) {
$this->channel = $channel;
return $this;
}
public function getChannel() {
return $this->assertAttached($this->channel);
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
return $this->getChannel()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getChannel()->hasAutomaticCapability($capability, $viewer);
}
}

View file

@ -57,10 +57,6 @@
"name": "Celerity", "name": "Celerity",
"include": "(^src/applications/celerity/)" "include": "(^src/applications/celerity/)"
}, },
"chatlog": {
"name": "Chatlog",
"include": "(^src/applications/chatlog/)"
},
"conduit": { "conduit": {
"name": "Conduit", "name": "Conduit",
"include": "(^src/applications/conduit/)" "include": "(^src/applications/conduit/)"

View file

@ -50,7 +50,6 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'after' => array( /* First Patch */ ), 'after' => array( /* First Patch */ ),
), ),
'db.calendar' => array(), 'db.calendar' => array(),
'db.chatlog' => array(),
'db.conduit' => array(), 'db.conduit' => array(),
'db.countdown' => array(), 'db.countdown' => array(),
'db.daemon' => array(), 'db.daemon' => array(),

View file

@ -1,81 +0,0 @@
/**
* @provides phabricator-chatlog-css
*/
.device-phone .phabricator-chat-log-wrap {
padding: 0;
}
.phabricator-chat-log-pager-bottom {
padding: 8px 4px 16px;
font-weight: bold;
float: right;
}
.phabricator-chat-log-pager-bottom a {
padding: 2px 3px;
}
.phabricator-chat-log-panel {
clear: both;
}
.phabricator-chat-log {
width: 100%;
}
.phabricator-chat-log td {
padding: 8px;
line-height: 18px;
}
.phabricator-chat-log tr {
background: #fff;
}
.phabricator-chat-log tr td.author {
background: {$greybackground};
}
.phabricator-chat-log tr.alternate {
border-top: 1px solid {$thinblueborder};
border-bottom: 1px solid {$thinblueborder};
}
.phabricator-chat-log tr.alternate td.author {
background: {$lightgreybackground};
}
.phabricator-chat-log tr.highlight td {
background: {$lightyellow};
}
.phabricator-chat-log td.timestamp {
white-space: nowrap;
text-align: right;
width: 12em;
}
.phabricator-chat-log td.message .timestamp {
color: {$bluetext};
font-size: {$smallestfontsize};
float: right;
margin-left: 5px;
}
.phabricator-chat-log td.author {
white-space: nowrap;
text-align: right;
font-weight: bold;
width: 140px;
color: {$darkbluetext};
}
.device-phone .phabricator-chat-log td.author {
width: 80px;
}
.phabricator-chat-log td.message {
white-space: pre-wrap;
word-break: break-word;
}