mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +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:
parent
cf8d5d60a5
commit
4d4712b58d
25 changed files with 5 additions and 1080 deletions
|
@ -42,7 +42,6 @@ return array(
|
|||
'rsrc/css/application/base/notification-menu.css' => '4df1ee30',
|
||||
'rsrc/css/application/base/phui-theme.css' => '35883b37',
|
||||
'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/config/config-options.css' => '16c920ae',
|
||||
'rsrc/css/application/config/config-template.css' => 'e689dbbd',
|
||||
|
@ -770,7 +769,6 @@ return array(
|
|||
'people-profile-css' => '2ea2daa1',
|
||||
'phabricator-action-list-view-css' => '1b0085b2',
|
||||
'phabricator-busy' => '5202e831',
|
||||
'phabricator-chatlog-css' => 'abdc76ee',
|
||||
'phabricator-content-source-view-css' => 'cdf0d579',
|
||||
'phabricator-core-css' => 'b3a5928e',
|
||||
'phabricator-countdown-css' => 'bff8012f',
|
||||
|
|
|
@ -4,7 +4,6 @@ $applications = array(
|
|||
'Audit',
|
||||
'Auth',
|
||||
'Calendar',
|
||||
'ChatLog',
|
||||
'Conduit',
|
||||
'Config',
|
||||
'Conpherence',
|
||||
|
|
|
@ -1,10 +1 @@
|
|||
CREATE TABLE {$NAMESPACE}_chatlog.chatlog_event (
|
||||
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)
|
||||
);
|
||||
/* This file is intentionally left empty, see T15126 */
|
||||
|
|
|
@ -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 TABLE `{$NAMESPACE}_conduit`.`conduit_certificatetoken`
|
||||
|
|
|
@ -1,11 +1 @@
|
|||
CREATE TABLE {$NAMESPACE}_chatlog.chatlog_channel (
|
||||
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;
|
||||
/* This file is intentionally left empty, see T15126 */
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
ALTER TABLE `{$NAMESPACE}_chatlog`.`chatlog_event`
|
||||
ADD `channelID` INT UNSIGNED NOT NULL;
|
||||
/* This file is intentionally left empty, see T15126 */
|
||||
|
|
|
@ -1,64 +1,3 @@
|
|||
<?php
|
||||
|
||||
echo pht('Updating channel IDs of previous chatlog events...')."\n";
|
||||
$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";
|
||||
/* This file is intentionally left empty, see T15126 */
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
ALTER TABLE `{$NAMESPACE}_chatlog`.`chatlog_event`
|
||||
DROP channel;
|
||||
/* This file is intentionally left empty, see T15126 */
|
||||
|
|
|
@ -1477,45 +1477,6 @@ CREATE TABLE `edgedata` (
|
|||
PRIMARY KEY (`id`)
|
||||
) 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} */;
|
||||
|
||||
USE `{$NAMESPACE}_conduit`;
|
||||
|
|
|
@ -339,9 +339,6 @@ phutil_register_library_map(array(
|
|||
'CelerityResourcesOnDisk' => 'applications/celerity/resources/CelerityResourcesOnDisk.php',
|
||||
'CeleritySpriteGenerator' => 'applications/celerity/CeleritySpriteGenerator.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',
|
||||
'ConduitAPIMethod' => 'applications/conduit/method/ConduitAPIMethod.php',
|
||||
'ConduitAPIMethodTestCase' => 'applications/conduit/method/__tests__/ConduitAPIMethodTestCase.php',
|
||||
|
@ -2808,15 +2805,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorChartInterval' => 'applications/fact/chart/PhabricatorChartInterval.php',
|
||||
'PhabricatorChartRenderingEngine' => 'applications/fact/engine/PhabricatorChartRenderingEngine.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',
|
||||
'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php',
|
||||
'PhabricatorClassConfigType' => 'applications/config/type/PhabricatorClassConfigType.php',
|
||||
|
@ -6339,9 +6327,6 @@ phutil_register_library_map(array(
|
|||
'CelerityResourcesOnDisk' => 'CelerityPhysicalResources',
|
||||
'CeleritySpriteGenerator' => 'Phobject',
|
||||
'CelerityStaticResourceResponse' => 'Phobject',
|
||||
'ChatLogConduitAPIMethod' => 'ConduitAPIMethod',
|
||||
'ChatLogQueryConduitAPIMethod' => 'ChatLogConduitAPIMethod',
|
||||
'ChatLogRecordConduitAPIMethod' => 'ChatLogConduitAPIMethod',
|
||||
'ConduitAPIDocumentationPage' => 'Phobject',
|
||||
'ConduitAPIMethod' => array(
|
||||
'Phobject',
|
||||
|
@ -9191,21 +9176,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorChartInterval' => 'Phobject',
|
||||
'PhabricatorChartRenderingEngine' => 'Phobject',
|
||||
'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',
|
||||
'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||
'PhabricatorClassConfigType' => 'PhabricatorTextConfigType',
|
||||
|
|
|
@ -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',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
abstract class ChatLogConduitAPIMethod extends ConduitAPIMethod {
|
||||
|
||||
final public function getApplication() {
|
||||
return PhabricatorApplication::getByClass('PhabricatorChatLogApplication');
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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'));
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorChatLogController extends PhabricatorController {}
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorChatLogDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'chatlog';
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -57,10 +57,6 @@
|
|||
"name": "Celerity",
|
||||
"include": "(^src/applications/celerity/)"
|
||||
},
|
||||
"chatlog": {
|
||||
"name": "Chatlog",
|
||||
"include": "(^src/applications/chatlog/)"
|
||||
},
|
||||
"conduit": {
|
||||
"name": "Conduit",
|
||||
"include": "(^src/applications/conduit/)"
|
||||
|
|
|
@ -50,7 +50,6 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'after' => array( /* First Patch */ ),
|
||||
),
|
||||
'db.calendar' => array(),
|
||||
'db.chatlog' => array(),
|
||||
'db.conduit' => array(),
|
||||
'db.countdown' => array(),
|
||||
'db.daemon' => array(),
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue