mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-10 06:41:04 +01:00
(stable) Promote 2018 Week 37
This commit is contained in:
commit
f65b846ecf
72 changed files with 1513 additions and 459 deletions
|
@ -9,7 +9,7 @@ return array(
|
|||
'names' => array(
|
||||
'conpherence.pkg.css' => 'e68cf1fa',
|
||||
'conpherence.pkg.js' => '15191c65',
|
||||
'core.pkg.css' => 'badf3f16',
|
||||
'core.pkg.css' => '2574c199',
|
||||
'core.pkg.js' => 'b5a949ca',
|
||||
'differential.pkg.css' => '06dc617c',
|
||||
'differential.pkg.js' => 'c1cfa143',
|
||||
|
@ -122,7 +122,7 @@ return array(
|
|||
'rsrc/css/layout/phabricator-source-code-view.css' => '2ab25dfa',
|
||||
'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494',
|
||||
'rsrc/css/phui/button/phui-button-simple.css' => '8e1baf68',
|
||||
'rsrc/css/phui/button/phui-button.css' => '1863cc6e',
|
||||
'rsrc/css/phui/button/phui-button.css' => '6ccb303c',
|
||||
'rsrc/css/phui/calendar/phui-calendar-day.css' => '572b1893',
|
||||
'rsrc/css/phui/calendar/phui-calendar-list.css' => '576be600',
|
||||
'rsrc/css/phui/calendar/phui-calendar-month.css' => '21154caf',
|
||||
|
@ -146,12 +146,12 @@ return array(
|
|||
'rsrc/css/phui/phui-comment-panel.css' => 'f50152ad',
|
||||
'rsrc/css/phui/phui-crumbs-view.css' => '10728aaa',
|
||||
'rsrc/css/phui/phui-curtain-view.css' => '2bdaf026',
|
||||
'rsrc/css/phui/phui-document-pro.css' => '1a08ef4b',
|
||||
'rsrc/css/phui/phui-document-pro.css' => 'd033e8d5',
|
||||
'rsrc/css/phui/phui-document-summary.css' => '9ca48bdf',
|
||||
'rsrc/css/phui/phui-document.css' => 'c4ac41f9',
|
||||
'rsrc/css/phui/phui-feed-story.css' => '44a9c8e9',
|
||||
'rsrc/css/phui/phui-fontkit.css' => '1320ed01',
|
||||
'rsrc/css/phui/phui-form-view.css' => 'f808e5be',
|
||||
'rsrc/css/phui/phui-form-view.css' => '2f43fae7',
|
||||
'rsrc/css/phui/phui-form.css' => '7aaa04e3',
|
||||
'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f',
|
||||
'rsrc/css/phui/phui-header-view.css' => '1ba8b707',
|
||||
|
@ -423,7 +423,7 @@ return array(
|
|||
'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e2e0a072',
|
||||
'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08',
|
||||
'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f',
|
||||
'rsrc/js/application/transactions/behavior-comment-actions.js' => '54110499',
|
||||
'rsrc/js/application/transactions/behavior-comment-actions.js' => '038bf27f',
|
||||
'rsrc/js/application/transactions/behavior-reorder-configs.js' => 'd7a74243',
|
||||
'rsrc/js/application/transactions/behavior-reorder-fields.js' => 'b59e1e96',
|
||||
'rsrc/js/application/transactions/behavior-show-older-transactions.js' => '8f29b364',
|
||||
|
@ -575,7 +575,7 @@ return array(
|
|||
'javelin-behavior-bulk-job-reload' => 'edf8a145',
|
||||
'javelin-behavior-calendar-month-view' => 'fe33e256',
|
||||
'javelin-behavior-choose-control' => '327a00d1',
|
||||
'javelin-behavior-comment-actions' => '54110499',
|
||||
'javelin-behavior-comment-actions' => '038bf27f',
|
||||
'javelin-behavior-config-reorder-fields' => 'b6993408',
|
||||
'javelin-behavior-conpherence-menu' => '4047cd35',
|
||||
'javelin-behavior-conpherence-participant-pane' => 'd057e45a',
|
||||
|
@ -800,7 +800,7 @@ return array(
|
|||
'phui-box-css' => '4bd6cdb9',
|
||||
'phui-bulk-editor-css' => '9a81e5d5',
|
||||
'phui-button-bar-css' => 'f1ff5494',
|
||||
'phui-button-css' => '1863cc6e',
|
||||
'phui-button-css' => '6ccb303c',
|
||||
'phui-button-simple-css' => '8e1baf68',
|
||||
'phui-calendar-css' => 'f1ddf11c',
|
||||
'phui-calendar-day-css' => '572b1893',
|
||||
|
@ -814,12 +814,12 @@ return array(
|
|||
'phui-curtain-view-css' => '2bdaf026',
|
||||
'phui-document-summary-view-css' => '9ca48bdf',
|
||||
'phui-document-view-css' => 'c4ac41f9',
|
||||
'phui-document-view-pro-css' => '1a08ef4b',
|
||||
'phui-document-view-pro-css' => 'd033e8d5',
|
||||
'phui-feed-story-css' => '44a9c8e9',
|
||||
'phui-font-icon-base-css' => '870a7360',
|
||||
'phui-fontkit-css' => '1320ed01',
|
||||
'phui-form-css' => '7aaa04e3',
|
||||
'phui-form-view-css' => 'f808e5be',
|
||||
'phui-form-view-css' => '2f43fae7',
|
||||
'phui-head-thing-view-css' => 'fd311e5f',
|
||||
'phui-header-view-css' => '1ba8b707',
|
||||
'phui-hovercard' => '1bd28176',
|
||||
|
@ -905,6 +905,15 @@ return array(
|
|||
'javelin-behavior',
|
||||
'javelin-uri',
|
||||
),
|
||||
'038bf27f' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
'javelin-workflow',
|
||||
'javelin-dom',
|
||||
'phuix-form-control-view',
|
||||
'phuix-icon-view',
|
||||
'javelin-behavior-phabricator-gesture',
|
||||
),
|
||||
'040fce04' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-request',
|
||||
|
@ -1251,15 +1260,6 @@ return array(
|
|||
'javelin-vector',
|
||||
'javelin-typeahead-static-source',
|
||||
),
|
||||
54110499 => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
'javelin-workflow',
|
||||
'javelin-dom',
|
||||
'phuix-form-control-view',
|
||||
'phuix-icon-view',
|
||||
'javelin-behavior-phabricator-gesture',
|
||||
),
|
||||
'549459b8' => array(
|
||||
'javelin-behavior',
|
||||
),
|
||||
|
|
54
resources/sql/autopatches/20180910.audit.01.searches.php
Normal file
54
resources/sql/autopatches/20180910.audit.01.searches.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
$table = new PhabricatorSavedQuery();
|
||||
$conn = $table->establishConnection('w');
|
||||
|
||||
$status_map = array(
|
||||
0 => 'none',
|
||||
1 => 'needs-audit',
|
||||
2 => 'concern-raised',
|
||||
3 => 'partially-audited',
|
||||
4 => 'audited',
|
||||
5 => 'needs-verification',
|
||||
);
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $query) {
|
||||
if ($query->getEngineClassName() !== 'PhabricatorCommitSearchEngine') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameters = $query->getParameters();
|
||||
$status = idx($parameters, 'statuses');
|
||||
|
||||
if (!$status) {
|
||||
// No saved "status" constraint.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_array($status)) {
|
||||
// Saved constraint isn't a list.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Migrate old integer values to new string values.
|
||||
$old_status = $status;
|
||||
foreach ($status as $key => $value) {
|
||||
if (is_numeric($value)) {
|
||||
$status[$key] = $status_map[$value];
|
||||
}
|
||||
}
|
||||
|
||||
if ($status === $old_status) {
|
||||
// Nothing changed.
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameters['statuses'] = $status;
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'UPDATE %T SET parameters = %s WHERE id = %d',
|
||||
$table->getTableName(),
|
||||
phutil_json_encode($parameters),
|
||||
$query->getID());
|
||||
}
|
2
resources/sql/autopatches/20180910.audit.02.string.sql
Normal file
2
resources/sql/autopatches/20180910.audit.02.string.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_repository.repository_commit
|
||||
CHANGE auditStatus auditStatus VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT};
|
28
resources/sql/autopatches/20180910.audit.03.status.php
Normal file
28
resources/sql/autopatches/20180910.audit.03.status.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
$table = new PhabricatorRepositoryCommit();
|
||||
$conn = $table->establishConnection('w');
|
||||
|
||||
$status_map = array(
|
||||
0 => 'none',
|
||||
1 => 'needs-audit',
|
||||
2 => 'concern-raised',
|
||||
3 => 'partially-audited',
|
||||
4 => 'audited',
|
||||
5 => 'needs-verification',
|
||||
);
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $commit) {
|
||||
$status = $commit->getAuditStatus();
|
||||
|
||||
if (!isset($status_map[$status])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'UPDATE %T SET auditStatus = %s WHERE id = %d',
|
||||
$table->getTableName(),
|
||||
$status_map[$status],
|
||||
$commit->getID());
|
||||
}
|
48
resources/sql/autopatches/20180910.audit.04.xactions.php
Normal file
48
resources/sql/autopatches/20180910.audit.04.xactions.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
$table = new PhabricatorAuditTransaction();
|
||||
$conn = $table->establishConnection('w');
|
||||
|
||||
$status_map = array(
|
||||
0 => 'none',
|
||||
1 => 'needs-audit',
|
||||
2 => 'concern-raised',
|
||||
3 => 'partially-audited',
|
||||
4 => 'audited',
|
||||
5 => 'needs-verification',
|
||||
);
|
||||
|
||||
$state_type = DiffusionCommitStateTransaction::TRANSACTIONTYPE;
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $xaction) {
|
||||
if ($xaction->getTransactionType() !== $state_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$old_value = $xaction->getOldValue();
|
||||
$new_value = $xaction->getNewValue();
|
||||
|
||||
$any_change = false;
|
||||
|
||||
if (isset($status_map[$old_value])) {
|
||||
$old_value = $status_map[$old_value];
|
||||
$any_change = true;
|
||||
}
|
||||
|
||||
if (isset($status_map[$new_value])) {
|
||||
$new_value = $status_map[$new_value];
|
||||
$any_change = true;
|
||||
}
|
||||
|
||||
if (!$any_change) {
|
||||
continue;
|
||||
}
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'UPDATE %T SET oldValue = %s, newValue = %s WHERE id = %d',
|
||||
$table->getTableName(),
|
||||
phutil_json_encode($old_value),
|
||||
phutil_json_encode($new_value),
|
||||
$xaction->getID());
|
||||
}
|
26
resources/sql/autopatches/20180914.audit.01.mailkey.php
Normal file
26
resources/sql/autopatches/20180914.audit.01.mailkey.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
$commit_table = new PhabricatorRepositoryCommit();
|
||||
$commit_conn = $commit_table->establishConnection('w');
|
||||
$commit_name = $commit_table->getTableName();
|
||||
|
||||
$properties_table = new PhabricatorMetaMTAMailProperties();
|
||||
$conn = $properties_table->establishConnection('w');
|
||||
|
||||
$iterator = new LiskRawMigrationIterator($commit_conn, $commit_name);
|
||||
foreach ($iterator as $commit) {
|
||||
queryfx(
|
||||
$conn,
|
||||
'INSERT IGNORE INTO %T
|
||||
(objectPHID, mailProperties, dateCreated, dateModified)
|
||||
VALUES
|
||||
(%s, %s, %d, %d)',
|
||||
$properties_table->getTableName(),
|
||||
$commit['phid'],
|
||||
phutil_json_encode(
|
||||
array(
|
||||
'mailKey' => $commit['mailKey'],
|
||||
)),
|
||||
PhabricatorTime::getNow(),
|
||||
PhabricatorTime::getNow());
|
||||
}
|
2
resources/sql/autopatches/20180914.audit.02.rmkey.sql
Normal file
2
resources/sql/autopatches/20180914.audit.02.rmkey.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_repository.repository_commit
|
||||
DROP mailKey;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
ADD operationPHID VARBINARY(64);
|
|
@ -704,6 +704,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionCommitAcceptTransaction' => 'applications/diffusion/xaction/DiffusionCommitAcceptTransaction.php',
|
||||
'DiffusionCommitActionTransaction' => 'applications/diffusion/xaction/DiffusionCommitActionTransaction.php',
|
||||
'DiffusionCommitAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionCommitAffectedFilesHeraldField.php',
|
||||
'DiffusionCommitAuditStatus' => 'applications/diffusion/DiffusionCommitAuditStatus.php',
|
||||
'DiffusionCommitAuditTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditTransaction.php',
|
||||
'DiffusionCommitAuditorsHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuditorsHeraldField.php',
|
||||
'DiffusionCommitAuditorsTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php',
|
||||
|
@ -1167,6 +1168,7 @@ phutil_register_library_map(array(
|
|||
'DrydockManagementUpdateResourceWorkflow' => 'applications/drydock/management/DrydockManagementUpdateResourceWorkflow.php',
|
||||
'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php',
|
||||
'DrydockObjectAuthorizationView' => 'applications/drydock/view/DrydockObjectAuthorizationView.php',
|
||||
'DrydockOperationWorkLogType' => 'applications/drydock/logtype/DrydockOperationWorkLogType.php',
|
||||
'DrydockQuery' => 'applications/drydock/query/DrydockQuery.php',
|
||||
'DrydockRepositoryOperation' => 'applications/drydock/storage/DrydockRepositoryOperation.php',
|
||||
'DrydockRepositoryOperationController' => 'applications/drydock/controller/DrydockRepositoryOperationController.php',
|
||||
|
@ -1204,6 +1206,7 @@ phutil_register_library_map(array(
|
|||
'DrydockSlotLockException' => 'applications/drydock/exception/DrydockSlotLockException.php',
|
||||
'DrydockSlotLockFailureLogType' => 'applications/drydock/logtype/DrydockSlotLockFailureLogType.php',
|
||||
'DrydockTestRepositoryOperation' => 'applications/drydock/operation/DrydockTestRepositoryOperation.php',
|
||||
'DrydockTextLogType' => 'applications/drydock/logtype/DrydockTextLogType.php',
|
||||
'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php',
|
||||
'DrydockWorker' => 'applications/drydock/worker/DrydockWorker.php',
|
||||
'DrydockWorkingCopyBlueprintImplementation' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php',
|
||||
|
@ -2147,7 +2150,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php',
|
||||
'PhabricatorAuditApplication' => 'applications/audit/application/PhabricatorAuditApplication.php',
|
||||
'PhabricatorAuditCommentEditor' => 'applications/audit/editor/PhabricatorAuditCommentEditor.php',
|
||||
'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/PhabricatorAuditCommitStatusConstants.php',
|
||||
'PhabricatorAuditController' => 'applications/audit/controller/PhabricatorAuditController.php',
|
||||
'PhabricatorAuditEditor' => 'applications/audit/editor/PhabricatorAuditEditor.php',
|
||||
'PhabricatorAuditInlineComment' => 'applications/audit/storage/PhabricatorAuditInlineComment.php',
|
||||
|
@ -5021,6 +5023,9 @@ phutil_register_library_map(array(
|
|||
'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php',
|
||||
'PhrictionDocumentDatasource' => 'applications/phriction/typeahead/PhrictionDocumentDatasource.php',
|
||||
'PhrictionDocumentDeleteTransaction' => 'applications/phriction/xaction/PhrictionDocumentDeleteTransaction.php',
|
||||
'PhrictionDocumentDraftTransaction' => 'applications/phriction/xaction/PhrictionDocumentDraftTransaction.php',
|
||||
'PhrictionDocumentEditEngine' => 'applications/phriction/editor/PhrictionDocumentEditEngine.php',
|
||||
'PhrictionDocumentEditTransaction' => 'applications/phriction/xaction/PhrictionDocumentEditTransaction.php',
|
||||
'PhrictionDocumentFerretEngine' => 'applications/phriction/search/PhrictionDocumentFerretEngine.php',
|
||||
'PhrictionDocumentFulltextEngine' => 'applications/phriction/search/PhrictionDocumentFulltextEngine.php',
|
||||
'PhrictionDocumentHeraldAdapter' => 'applications/phriction/herald/PhrictionDocumentHeraldAdapter.php',
|
||||
|
@ -5042,6 +5047,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionDocumentVersionTransaction' => 'applications/phriction/xaction/PhrictionDocumentVersionTransaction.php',
|
||||
'PhrictionEditConduitAPIMethod' => 'applications/phriction/conduit/PhrictionEditConduitAPIMethod.php',
|
||||
'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php',
|
||||
'PhrictionEditEngineController' => 'applications/phriction/controller/PhrictionEditEngineController.php',
|
||||
'PhrictionHistoryConduitAPIMethod' => 'applications/phriction/conduit/PhrictionHistoryConduitAPIMethod.php',
|
||||
'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php',
|
||||
'PhrictionInfoConduitAPIMethod' => 'applications/phriction/conduit/PhrictionInfoConduitAPIMethod.php',
|
||||
|
@ -6066,6 +6072,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionCommitAcceptTransaction' => 'DiffusionCommitAuditTransaction',
|
||||
'DiffusionCommitActionTransaction' => 'DiffusionCommitTransactionType',
|
||||
'DiffusionCommitAffectedFilesHeraldField' => 'DiffusionCommitHeraldField',
|
||||
'DiffusionCommitAuditStatus' => 'Phobject',
|
||||
'DiffusionCommitAuditTransaction' => 'DiffusionCommitActionTransaction',
|
||||
'DiffusionCommitAuditorsHeraldField' => 'DiffusionCommitHeraldField',
|
||||
'DiffusionCommitAuditorsTransaction' => 'DiffusionCommitTransactionType',
|
||||
|
@ -6570,6 +6577,7 @@ phutil_register_library_map(array(
|
|||
'DrydockManagementUpdateResourceWorkflow' => 'DrydockManagementWorkflow',
|
||||
'DrydockManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'DrydockObjectAuthorizationView' => 'AphrontView',
|
||||
'DrydockOperationWorkLogType' => 'DrydockLogType',
|
||||
'DrydockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'DrydockRepositoryOperation' => array(
|
||||
'DrydockDAO',
|
||||
|
@ -6613,6 +6621,7 @@ phutil_register_library_map(array(
|
|||
'DrydockSlotLockException' => 'Exception',
|
||||
'DrydockSlotLockFailureLogType' => 'DrydockLogType',
|
||||
'DrydockTestRepositoryOperation' => 'DrydockRepositoryOperationType',
|
||||
'DrydockTextLogType' => 'DrydockLogType',
|
||||
'DrydockWebrootInterface' => 'DrydockInterface',
|
||||
'DrydockWorker' => 'PhabricatorWorker',
|
||||
'DrydockWorkingCopyBlueprintImplementation' => 'DrydockBlueprintImplementation',
|
||||
|
@ -7715,7 +7724,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuditActionConstants' => 'Phobject',
|
||||
'PhabricatorAuditApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorAuditCommentEditor' => 'PhabricatorEditor',
|
||||
'PhabricatorAuditCommitStatusConstants' => 'Phobject',
|
||||
'PhabricatorAuditController' => 'PhabricatorController',
|
||||
'PhabricatorAuditEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhabricatorAuditInlineComment' => array(
|
||||
|
@ -11136,10 +11144,13 @@ phutil_register_library_map(array(
|
|||
),
|
||||
'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField',
|
||||
'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField',
|
||||
'PhrictionDocumentContentTransaction' => 'PhrictionDocumentVersionTransaction',
|
||||
'PhrictionDocumentContentTransaction' => 'PhrictionDocumentEditTransaction',
|
||||
'PhrictionDocumentController' => 'PhrictionController',
|
||||
'PhrictionDocumentDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhrictionDocumentDeleteTransaction' => 'PhrictionDocumentVersionTransaction',
|
||||
'PhrictionDocumentDraftTransaction' => 'PhrictionDocumentEditTransaction',
|
||||
'PhrictionDocumentEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhrictionDocumentEditTransaction' => 'PhrictionDocumentVersionTransaction',
|
||||
'PhrictionDocumentFerretEngine' => 'PhabricatorFerretEngine',
|
||||
'PhrictionDocumentFulltextEngine' => 'PhabricatorFulltextEngine',
|
||||
'PhrictionDocumentHeraldAdapter' => 'HeraldAdapter',
|
||||
|
@ -11161,6 +11172,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionDocumentVersionTransaction' => 'PhrictionDocumentTransactionType',
|
||||
'PhrictionEditConduitAPIMethod' => 'PhrictionConduitAPIMethod',
|
||||
'PhrictionEditController' => 'PhrictionController',
|
||||
'PhrictionEditEngineController' => 'PhrictionController',
|
||||
'PhrictionHistoryConduitAPIMethod' => 'PhrictionConduitAPIMethod',
|
||||
'PhrictionHistoryController' => 'PhrictionController',
|
||||
'PhrictionInfoConduitAPIMethod' => 'PhrictionConduitAPIMethod',
|
||||
|
|
|
@ -68,17 +68,17 @@ final class AuditQueryConduitAPIMethod extends AuditConduitAPIMethod {
|
|||
|
||||
$status_map = array(
|
||||
self::AUDIT_LEGACYSTATUS_OPEN => array(
|
||||
PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT,
|
||||
PhabricatorAuditCommitStatusConstants::CONCERN_RAISED,
|
||||
DiffusionCommitAuditStatus::NEEDS_AUDIT,
|
||||
DiffusionCommitAuditStatus::CONCERN_RAISED,
|
||||
),
|
||||
self::AUDIT_LEGACYSTATUS_CONCERN => array(
|
||||
PhabricatorAuditCommitStatusConstants::CONCERN_RAISED,
|
||||
DiffusionCommitAuditStatus::CONCERN_RAISED,
|
||||
),
|
||||
self::AUDIT_LEGACYSTATUS_ACCEPTED => array(
|
||||
PhabricatorAuditCommitStatusConstants::FULLY_AUDITED,
|
||||
DiffusionCommitAuditStatus::AUDITED,
|
||||
),
|
||||
self::AUDIT_LEGACYSTATUS_PARTIAL => array(
|
||||
PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED,
|
||||
DiffusionCommitAuditStatus::PARTIALLY_AUDITED,
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuditCommitStatusConstants extends Phobject {
|
||||
|
||||
private $key;
|
||||
private $spec = array();
|
||||
|
||||
const NONE = 0;
|
||||
const NEEDS_AUDIT = 1;
|
||||
const CONCERN_RAISED = 2;
|
||||
const PARTIALLY_AUDITED = 3;
|
||||
const FULLY_AUDITED = 4;
|
||||
const NEEDS_VERIFICATION = 5;
|
||||
|
||||
const MODERN_NONE = 'none';
|
||||
const MODERN_NEEDS_AUDIT = 'needs-audit';
|
||||
const MODERN_CONCERN_RAISED = 'concern-raised';
|
||||
const MODERN_PARTIALLY_AUDITED = 'partially-audited';
|
||||
const MODERN_AUDITED = 'audited';
|
||||
const MODERN_NEEDS_VERIFICATION = 'needs-verification';
|
||||
|
||||
public static function newForLegacyStatus($status) {
|
||||
$map = self::getMap();
|
||||
|
||||
foreach ($map as $key => $spec) {
|
||||
if (idx($spec, 'legacy') == $status) {
|
||||
return self::newForStatus($key);
|
||||
}
|
||||
}
|
||||
|
||||
return self::newForStatus($status);
|
||||
}
|
||||
|
||||
public static function newForStatus($status) {
|
||||
$result = new self();
|
||||
|
||||
$result->key = $status;
|
||||
|
||||
$map = self::getMap();
|
||||
if (isset($map[$status])) {
|
||||
$result->spec = $map[$status];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getKey() {
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return idx($this->spec, 'icon');
|
||||
}
|
||||
|
||||
public function getColor() {
|
||||
return idx($this->spec, 'color');
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return idx($this->spec, 'name', pht('Unknown ("%s")', $this->key));
|
||||
}
|
||||
|
||||
public static function getStatusNameMap() {
|
||||
$map = self::getMap();
|
||||
return ipull($map, 'name', 'legacy');
|
||||
}
|
||||
|
||||
public static function getStatusName($code) {
|
||||
return idx(self::getStatusNameMap(), $code, pht('Unknown'));
|
||||
}
|
||||
|
||||
public static function getOpenStatusConstants() {
|
||||
$constants = array();
|
||||
foreach (self::getMap() as $map) {
|
||||
if (!$map['closed']) {
|
||||
$constants[] = $map['legacy'];
|
||||
}
|
||||
}
|
||||
return $constants;
|
||||
}
|
||||
|
||||
public static function getStatusColor($code) {
|
||||
$map = self::getMap();
|
||||
$map = ipull($map, 'color', 'legacy');
|
||||
return idx($map, $code);
|
||||
}
|
||||
|
||||
public static function getStatusIcon($code) {
|
||||
$map = self::getMap();
|
||||
$map = ipull($map, 'icon', 'legacy');
|
||||
return idx($map, $code);
|
||||
}
|
||||
|
||||
private static function getMap() {
|
||||
return array(
|
||||
self::MODERN_NONE => array(
|
||||
'name' => pht('No Audits'),
|
||||
'legacy' => self::NONE,
|
||||
'icon' => 'fa-check',
|
||||
'color' => 'bluegrey',
|
||||
'closed' => true,
|
||||
),
|
||||
self::MODERN_NEEDS_AUDIT => array(
|
||||
'name' => pht('Audit Required'),
|
||||
'legacy' => self::NEEDS_AUDIT,
|
||||
'icon' => 'fa-exclamation-circle',
|
||||
'color' => 'orange',
|
||||
'closed' => false,
|
||||
),
|
||||
self::MODERN_CONCERN_RAISED => array(
|
||||
'name' => pht('Concern Raised'),
|
||||
'legacy' => self::CONCERN_RAISED,
|
||||
'icon' => 'fa-times-circle',
|
||||
'color' => 'red',
|
||||
'closed' => false,
|
||||
),
|
||||
self::MODERN_PARTIALLY_AUDITED => array(
|
||||
'name' => pht('Partially Audited'),
|
||||
'legacy' => self::PARTIALLY_AUDITED,
|
||||
'icon' => 'fa-check-circle-o',
|
||||
'color' => 'yellow',
|
||||
'closed' => false,
|
||||
),
|
||||
self::MODERN_AUDITED => array(
|
||||
'name' => pht('Audited'),
|
||||
'legacy' => self::FULLY_AUDITED,
|
||||
'icon' => 'fa-check-circle',
|
||||
'color' => 'green',
|
||||
'closed' => true,
|
||||
),
|
||||
self::MODERN_NEEDS_VERIFICATION => array(
|
||||
'name' => pht('Needs Verification'),
|
||||
'legacy' => self::NEEDS_VERIFICATION,
|
||||
'icon' => 'fa-refresh',
|
||||
'color' => 'indigo',
|
||||
'closed' => false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -206,12 +206,10 @@ final class PhabricatorAuditEditor
|
|||
$object->writeImportStatusFlag($import_status_flag);
|
||||
}
|
||||
|
||||
$partial_status = PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED;
|
||||
|
||||
// If the commit has changed state after this edit, add an informational
|
||||
// transaction about the state change.
|
||||
if ($old_status != $new_status) {
|
||||
if ($new_status == $partial_status) {
|
||||
if ($object->isAuditStatusPartiallyAudited()) {
|
||||
// This state isn't interesting enough to get a transaction. The
|
||||
// best way we could lead the user forward is something like "This
|
||||
// commit still requires additional audits." but that's redundant and
|
||||
|
|
|
@ -15,6 +15,7 @@ final class PhabricatorCommitSearchEngine
|
|||
return id(new DiffusionCommitQuery())
|
||||
->needAuditRequests(true)
|
||||
->needCommitData(true)
|
||||
->needIdentities(true)
|
||||
->needDrafts(true);
|
||||
}
|
||||
|
||||
|
@ -92,7 +93,9 @@ final class PhabricatorCommitSearchEngine
|
|||
->setLabel(pht('Audit Status'))
|
||||
->setKey('statuses')
|
||||
->setAliases(array('status'))
|
||||
->setOptions(PhabricatorAuditCommitStatusConstants::getStatusNameMap())
|
||||
->setOptions(DiffusionCommitAuditStatus::newOptions())
|
||||
->setDeprecatedOptions(
|
||||
DiffusionCommitAuditStatus::newDeprecatedOptions())
|
||||
->setDescription(pht('Find commits with given audit statuses.')),
|
||||
id(new PhabricatorSearchDatasourceField())
|
||||
->setLabel(pht('Repositories'))
|
||||
|
@ -160,7 +163,7 @@ final class PhabricatorCommitSearchEngine
|
|||
case 'active':
|
||||
$bucket_key = DiffusionCommitRequiredActionResultBucket::BUCKETKEY;
|
||||
|
||||
$open = PhabricatorAuditCommitStatusConstants::getOpenStatusConstants();
|
||||
$open = DiffusionCommitAuditStatus::getOpenStatusConstants();
|
||||
|
||||
$query
|
||||
->setParameter('responsiblePHIDs', array($viewer_phid))
|
||||
|
|
|
@ -490,8 +490,7 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
PhabricatorAuthSession $session,
|
||||
$force = false) {
|
||||
|
||||
$until = $session->getHighSecurityUntil();
|
||||
if ($until > time() || $force) {
|
||||
if ($session->isHighSecuritySession() || $force) {
|
||||
return new PhabricatorAuthHighSecurityToken();
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,22 @@ final class PhabricatorAuthSession extends PhabricatorAuthDAO
|
|||
}
|
||||
}
|
||||
|
||||
public function isHighSecuritySession() {
|
||||
$until = $this->getHighSecurityUntil();
|
||||
|
||||
if (!$until) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$now = PhabricatorTime::getNow();
|
||||
if ($until < $now) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ final class ConduitConstantDescription extends Phobject {
|
|||
|
||||
private $key;
|
||||
private $value;
|
||||
private $isDeprecated;
|
||||
|
||||
public function setKey($key) {
|
||||
$this->key = $key;
|
||||
|
@ -23,4 +24,13 @@ final class ConduitConstantDescription extends Phobject {
|
|||
return $this->value;
|
||||
}
|
||||
|
||||
public function setIsDeprecated($is_deprecated) {
|
||||
$this->isDeprecated = $is_deprecated;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsDeprecated() {
|
||||
return $this->isDeprecated;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
173
src/applications/diffusion/DiffusionCommitAuditStatus.php
Normal file
173
src/applications/diffusion/DiffusionCommitAuditStatus.php
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionCommitAuditStatus extends Phobject {
|
||||
|
||||
private $key;
|
||||
private $spec = array();
|
||||
|
||||
const NONE = 'none';
|
||||
const NEEDS_AUDIT = 'needs-audit';
|
||||
const CONCERN_RAISED = 'concern-raised';
|
||||
const PARTIALLY_AUDITED = 'partially-audited';
|
||||
const AUDITED = 'audited';
|
||||
const NEEDS_VERIFICATION = 'needs-verification';
|
||||
|
||||
public static function newModernKeys(array $values) {
|
||||
$map = self::getMap();
|
||||
|
||||
$modern = array();
|
||||
foreach ($map as $key => $spec) {
|
||||
if (isset($spec['legacy'])) {
|
||||
$modern[$spec['legacy']] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$values[$key] = idx($modern, $value, $value);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
public static function newForStatus($status) {
|
||||
$result = new self();
|
||||
|
||||
$result->key = $status;
|
||||
|
||||
$map = self::getMap();
|
||||
if (isset($map[$status])) {
|
||||
$result->spec = $map[$status];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getKey() {
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return idx($this->spec, 'icon');
|
||||
}
|
||||
|
||||
public function getColor() {
|
||||
return idx($this->spec, 'color');
|
||||
}
|
||||
|
||||
public function getAnsiColor() {
|
||||
return idx($this->spec, 'color.ansi');
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return idx($this->spec, 'name', pht('Unknown ("%s")', $this->key));
|
||||
}
|
||||
|
||||
public function isNoAudit() {
|
||||
return ($this->key == self::NONE);
|
||||
}
|
||||
|
||||
public function isNeedsAudit() {
|
||||
return ($this->key == self::NEEDS_AUDIT);
|
||||
}
|
||||
|
||||
public function isConcernRaised() {
|
||||
return ($this->key == self::CONCERN_RAISED);
|
||||
}
|
||||
|
||||
public function isNeedsVerification() {
|
||||
return ($this->key == self::NEEDS_VERIFICATION);
|
||||
}
|
||||
|
||||
public function isPartiallyAudited() {
|
||||
return ($this->key == self::PARTIALLY_AUDITED);
|
||||
}
|
||||
|
||||
public function isAudited() {
|
||||
return ($this->key == self::AUDITED);
|
||||
}
|
||||
|
||||
public function getIsClosed() {
|
||||
return idx($this->spec, 'closed');
|
||||
}
|
||||
|
||||
public static function getOpenStatusConstants() {
|
||||
$constants = array();
|
||||
foreach (self::getMap() as $key => $map) {
|
||||
if (!$map['closed']) {
|
||||
$constants[] = $key;
|
||||
}
|
||||
}
|
||||
return $constants;
|
||||
}
|
||||
|
||||
public static function newOptions() {
|
||||
$map = self::getMap();
|
||||
return ipull($map, 'name');
|
||||
}
|
||||
|
||||
public static function newDeprecatedOptions() {
|
||||
$map = self::getMap();
|
||||
|
||||
$results = array();
|
||||
foreach ($map as $key => $spec) {
|
||||
if (isset($spec['legacy'])) {
|
||||
$results[$spec['legacy']] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
private static function getMap() {
|
||||
return array(
|
||||
self::NONE => array(
|
||||
'name' => pht('No Audits'),
|
||||
'legacy' => 0,
|
||||
'icon' => 'fa-check',
|
||||
'color' => 'bluegrey',
|
||||
'closed' => true,
|
||||
'color.ansi' => null,
|
||||
),
|
||||
self::NEEDS_AUDIT => array(
|
||||
'name' => pht('Audit Required'),
|
||||
'legacy' => 1,
|
||||
'icon' => 'fa-exclamation-circle',
|
||||
'color' => 'orange',
|
||||
'closed' => false,
|
||||
'color.ansi' => 'magenta',
|
||||
),
|
||||
self::CONCERN_RAISED => array(
|
||||
'name' => pht('Concern Raised'),
|
||||
'legacy' => 2,
|
||||
'icon' => 'fa-times-circle',
|
||||
'color' => 'red',
|
||||
'closed' => false,
|
||||
'color.ansi' => 'red',
|
||||
),
|
||||
self::PARTIALLY_AUDITED => array(
|
||||
'name' => pht('Partially Audited'),
|
||||
'legacy' => 3,
|
||||
'icon' => 'fa-check-circle-o',
|
||||
'color' => 'yellow',
|
||||
'closed' => false,
|
||||
'color.ansi' => 'yellow',
|
||||
),
|
||||
self::AUDITED => array(
|
||||
'name' => pht('Audited'),
|
||||
'legacy' => 4,
|
||||
'icon' => 'fa-check-circle',
|
||||
'color' => 'green',
|
||||
'closed' => true,
|
||||
'color.ansi' => 'green',
|
||||
),
|
||||
self::NEEDS_VERIFICATION => array(
|
||||
'name' => pht('Needs Verification'),
|
||||
'legacy' => 5,
|
||||
'icon' => 'fa-refresh',
|
||||
'color' => 'indigo',
|
||||
'closed' => false,
|
||||
'color.ansi' => 'magenta',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -171,13 +171,12 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
->setHeaderIcon('fa-code-fork')
|
||||
->addTag($commit_tag);
|
||||
|
||||
if ($commit->getAuditStatus()) {
|
||||
$icon = PhabricatorAuditCommitStatusConstants::getStatusIcon(
|
||||
$commit->getAuditStatus());
|
||||
$color = PhabricatorAuditCommitStatusConstants::getStatusColor(
|
||||
$commit->getAuditStatus());
|
||||
$status = PhabricatorAuditCommitStatusConstants::getStatusName(
|
||||
$commit->getAuditStatus());
|
||||
if (!$commit->isAuditStatusNoAudit()) {
|
||||
$status = $commit->getAuditStatusObject();
|
||||
|
||||
$icon = $status->getIcon();
|
||||
$color = $status->getColor();
|
||||
$status = $status->getName();
|
||||
|
||||
$header->setStatus($icon, $color, $status);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,6 @@ final class DiffusionDoorkeeperCommitFeedStoryPublisher
|
|||
// After ApplicationTransactions, we could annotate feed stories more
|
||||
// explicitly.
|
||||
|
||||
$fully_audited = PhabricatorAuditCommitStatusConstants::FULLY_AUDITED;
|
||||
|
||||
$story = $this->getFeedStory();
|
||||
$xaction = $story->getPrimaryTransaction();
|
||||
switch ($xaction->getTransactionType()) {
|
||||
|
@ -41,7 +39,7 @@ final class DiffusionDoorkeeperCommitFeedStoryPublisher
|
|||
case PhabricatorAuditActionConstants::CLOSE:
|
||||
return true;
|
||||
case PhabricatorAuditActionConstants::ACCEPT:
|
||||
if ($object->getAuditStatus() == $fully_audited) {
|
||||
if ($object->isAuditStatusAudited()) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
@ -165,14 +163,7 @@ final class DiffusionDoorkeeperCommitFeedStoryPublisher
|
|||
}
|
||||
|
||||
public function isObjectClosed($object) {
|
||||
switch ($object->getAuditStatus()) {
|
||||
case PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT:
|
||||
case PhabricatorAuditCommitStatusConstants::CONCERN_RAISED:
|
||||
case PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return $object->getAuditStatusObject()->getIsClosed();
|
||||
}
|
||||
|
||||
public function getResponsibilityTitle($object) {
|
||||
|
|
|
@ -41,12 +41,12 @@ final class DiffusionHovercardEngineExtension
|
|||
$hovercard->addField(pht('Date'),
|
||||
phabricator_date($commit->getEpoch(), $viewer));
|
||||
|
||||
if ($commit->getAuditStatus() !=
|
||||
PhabricatorAuditCommitStatusConstants::NONE) {
|
||||
if (!$commit->isAuditStatusNoAudit()) {
|
||||
$status = $commit->getAuditStatusObject();
|
||||
|
||||
$hovercard->addField(pht('Audit Status'),
|
||||
PhabricatorAuditCommitStatusConstants::getStatusName(
|
||||
$commit->getAuditStatus()));
|
||||
$hovercard->addField(
|
||||
pht('Audit Status'),
|
||||
$status->getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -714,10 +714,13 @@ final class DiffusionCommitQuery
|
|||
}
|
||||
|
||||
if ($this->statuses !== null) {
|
||||
$statuses = DiffusionCommitAuditStatus::newModernKeys(
|
||||
$this->statuses);
|
||||
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'commit.auditStatus IN (%Ld)',
|
||||
$this->statuses);
|
||||
'commit.auditStatus IN (%Ls)',
|
||||
$statuses);
|
||||
}
|
||||
|
||||
if ($this->packagePHIDs !== null) {
|
||||
|
|
|
@ -69,14 +69,12 @@ final class DiffusionCommitRequiredActionResultBucket
|
|||
$results = array();
|
||||
$objects = $this->objects;
|
||||
|
||||
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
|
||||
|
||||
foreach ($objects as $key => $object) {
|
||||
if (empty($phids[$object->getAuthorPHID()])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($object->getAuditStatus() != $status_concern) {
|
||||
if (!$object->isAuditStatusConcernRaised()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -91,7 +89,6 @@ final class DiffusionCommitRequiredActionResultBucket
|
|||
$results = array();
|
||||
$objects = $this->objects;
|
||||
|
||||
$status_verify = PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION;
|
||||
$has_concern = array(
|
||||
PhabricatorAuditStatusConstants::CONCERNED,
|
||||
);
|
||||
|
@ -102,7 +99,7 @@ final class DiffusionCommitRequiredActionResultBucket
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($object->getAuditStatus() != $status_verify) {
|
||||
if (!$object->isAuditStatusNeedsVerification()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -147,10 +144,8 @@ final class DiffusionCommitRequiredActionResultBucket
|
|||
$results = array();
|
||||
$objects = $this->objects;
|
||||
|
||||
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
|
||||
|
||||
foreach ($objects as $key => $object) {
|
||||
if ($object->getAuditStatus() != $status_concern) {
|
||||
if (!$object->isAuditStatusConcernRaised()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -169,15 +164,13 @@ final class DiffusionCommitRequiredActionResultBucket
|
|||
$results = array();
|
||||
$objects = $this->objects;
|
||||
|
||||
$status_waiting = array(
|
||||
PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT,
|
||||
PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION,
|
||||
PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED,
|
||||
);
|
||||
$status_waiting = array_fuse($status_waiting);
|
||||
|
||||
foreach ($objects as $key => $object) {
|
||||
if (empty($status_waiting[$object->getAuditStatus()])) {
|
||||
$any_waiting =
|
||||
$object->isAuditStatusNeedsAudit() ||
|
||||
$object->isAuditStatusNeedsVerification() ||
|
||||
$object->isAuditStatusPartiallyAudited();
|
||||
|
||||
if (!$any_waiting) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,8 +33,7 @@ final class DiffusionCommitConcernTransaction
|
|||
public function applyInternalEffects($object, $value) {
|
||||
// NOTE: We force the commit directly into "Concern Raised" so that we
|
||||
// override a possible "Needs Verification" state.
|
||||
$object->setAuditStatus(
|
||||
PhabricatorAuditCommitStatusConstants::CONCERN_RAISED);
|
||||
$object->setAuditStatus(DiffusionCommitAuditStatus::CONCERN_RAISED);
|
||||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
|
@ -54,10 +53,8 @@ final class DiffusionCommitConcernTransaction
|
|||
|
||||
// Even if you've already raised a concern, you can raise again as long
|
||||
// as the author requested you verify.
|
||||
$state_verify = PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION;
|
||||
|
||||
if ($this->isViewerFullyRejected($object, $viewer)) {
|
||||
if ($object->getAuditStatus() != $state_verify) {
|
||||
if (!$object->isAuditStatusNeedsVerification()) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'You can not raise a concern with this commit because you have '.
|
||||
|
|
|
@ -11,29 +11,32 @@ final class DiffusionCommitStateTransaction
|
|||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
private function getAuditStatusObject() {
|
||||
$new = $this->getNewValue();
|
||||
return PhabricatorAuditCommitStatusConstants::getStatusIcon($new);
|
||||
return DiffusionCommitAuditStatus::newForStatus($new);
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return $this->getAuditStatusObject()->getIcon();
|
||||
}
|
||||
|
||||
public function getColor() {
|
||||
$new = $this->getNewValue();
|
||||
return PhabricatorAuditCommitStatusConstants::getStatusColor($new);
|
||||
return $this->getAuditStatusObject()->getColor();
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$new = $this->getNewValue();
|
||||
$status = $this->getAuditStatusObject();
|
||||
|
||||
switch ($new) {
|
||||
case PhabricatorAuditCommitStatusConstants::NONE:
|
||||
switch ($status->getKey()) {
|
||||
case DiffusionCommitAuditStatus::NONE:
|
||||
return pht('This commit no longer requires audit.');
|
||||
case PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT:
|
||||
case DiffusionCommitAuditStatus::NEEDS_AUDIT:
|
||||
return pht('This commit now requires audit.');
|
||||
case PhabricatorAuditCommitStatusConstants::CONCERN_RAISED:
|
||||
case DiffusionCommitAuditStatus::CONCERN_RAISED:
|
||||
return pht('This commit now has outstanding concerns.');
|
||||
case PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION:
|
||||
case DiffusionCommitAuditStatus::NEEDS_VERIFICATION:
|
||||
return pht('This commit now requires verification by auditors.');
|
||||
case PhabricatorAuditCommitStatusConstants::FULLY_AUDITED:
|
||||
case DiffusionCommitAuditStatus::AUDITED:
|
||||
return pht('All concerns with this commit have now been addressed.');
|
||||
}
|
||||
|
||||
|
@ -41,26 +44,26 @@ final class DiffusionCommitStateTransaction
|
|||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
$new = $this->getNewValue();
|
||||
$status = $this->getAuditStatusObject();
|
||||
|
||||
switch ($new) {
|
||||
case PhabricatorAuditCommitStatusConstants::NONE:
|
||||
switch ($status->getKey()) {
|
||||
case DiffusionCommitAuditStatus::NONE:
|
||||
return pht(
|
||||
'%s no longer requires audit.',
|
||||
$this->renderObject());
|
||||
case PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT:
|
||||
case DiffusionCommitAuditStatus::NEEDS_AUDIT:
|
||||
return pht(
|
||||
'%s now requires audit.',
|
||||
$this->renderObject());
|
||||
case PhabricatorAuditCommitStatusConstants::CONCERN_RAISED:
|
||||
case DiffusionCommitAuditStatus::CONCERN_RAISED:
|
||||
return pht(
|
||||
'%s now has outstanding concerns.',
|
||||
$this->renderObject());
|
||||
case PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION:
|
||||
case DiffusionCommitAuditStatus::NEEDS_VERIFICATION:
|
||||
return pht(
|
||||
'%s now requires verification by auditors.',
|
||||
$this->renderObject());
|
||||
case PhabricatorAuditCommitStatusConstants::FULLY_AUDITED:
|
||||
case DiffusionCommitAuditStatus::AUDITED:
|
||||
return pht(
|
||||
'All concerns with %s have now been addressed.',
|
||||
$this->renderObject());
|
||||
|
|
|
@ -36,8 +36,7 @@ final class DiffusionCommitVerifyTransaction
|
|||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setAuditStatus(
|
||||
PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION);
|
||||
$object->setAuditStatus(DiffusionCommitAuditStatus::NEEDS_VERIFICATION);
|
||||
}
|
||||
|
||||
protected function validateAction($object, PhabricatorUser $viewer) {
|
||||
|
@ -48,8 +47,7 @@ final class DiffusionCommitVerifyTransaction
|
|||
'are not the author.'));
|
||||
}
|
||||
|
||||
$status = $object->getAuditStatus();
|
||||
if ($status != PhabricatorAuditCommitStatusConstants::CONCERN_RAISED) {
|
||||
if (!$object->isAuditStatusConcernRaised()) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'You can not request verification of this commit because no '.
|
||||
|
|
|
@ -93,6 +93,8 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication {
|
|||
'' => 'DrydockRepositoryOperationViewController',
|
||||
'status/' => 'DrydockRepositoryOperationStatusController',
|
||||
'dismiss/' => 'DrydockRepositoryOperationDismissController',
|
||||
'logs/(?:query/(?P<queryKey>[^/]+)/)?' =>
|
||||
'DrydockLogListController',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -58,8 +58,11 @@ final class DrydockBlueprintViewController extends DrydockBlueprintController {
|
|||
$log_query = id(new DrydockLogQuery())
|
||||
->withBlueprintPHIDs(array($blueprint->getPHID()));
|
||||
|
||||
$log_table = $this->buildLogTable($log_query)
|
||||
->setHideBlueprints(true);
|
||||
|
||||
$logs = $this->buildLogBox(
|
||||
$log_query,
|
||||
$log_table,
|
||||
$this->getApplicationURI("blueprint/{$id}/logs/query/all/"));
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
|
|
|
@ -79,7 +79,7 @@ abstract class DrydockController extends PhabricatorController {
|
|||
->addRawContent($table);
|
||||
}
|
||||
|
||||
protected function buildLogBox(DrydockLogQuery $query, $all_uri) {
|
||||
protected function buildLogTable(DrydockLogQuery $query) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$logs = $query
|
||||
|
@ -89,9 +89,12 @@ abstract class DrydockController extends PhabricatorController {
|
|||
|
||||
$log_table = id(new DrydockLogListView())
|
||||
->setUser($viewer)
|
||||
->setLogs($logs)
|
||||
->render();
|
||||
->setLogs($logs);
|
||||
|
||||
return $log_table;
|
||||
}
|
||||
|
||||
protected function buildLogBox(DrydockLogListView $log_table, $all_uri) {
|
||||
$log_header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Logs'))
|
||||
->addActionLink(
|
||||
|
|
|
@ -43,8 +43,11 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
|
|||
$log_query = id(new DrydockLogQuery())
|
||||
->withLeasePHIDs(array($lease->getPHID()));
|
||||
|
||||
$log_table = $this->buildLogTable($log_query)
|
||||
->setHideLeases(true);
|
||||
|
||||
$logs = $this->buildLogBox(
|
||||
$log_query,
|
||||
$log_table,
|
||||
$this->getApplicationURI("lease/{$id}/logs/query/all/"));
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
|
|
|
@ -6,6 +6,7 @@ abstract class DrydockLogController
|
|||
private $blueprint;
|
||||
private $resource;
|
||||
private $lease;
|
||||
private $operation;
|
||||
|
||||
public function setBlueprint(DrydockBlueprint $blueprint) {
|
||||
$this->blueprint = $blueprint;
|
||||
|
@ -34,6 +35,15 @@ abstract class DrydockLogController
|
|||
return $this->lease;
|
||||
}
|
||||
|
||||
public function setOperation(DrydockRepositoryOperation $operation) {
|
||||
$this->operation = $operation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOperation() {
|
||||
return $this->operation;
|
||||
}
|
||||
|
||||
public function buildSideNavView() {
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
@ -56,6 +66,11 @@ abstract class DrydockLogController
|
|||
$engine->setLease($lease);
|
||||
}
|
||||
|
||||
$operation = $this->getOperation();
|
||||
if ($operation) {
|
||||
$engine->setOperation($operation);
|
||||
}
|
||||
|
||||
$engine->addNavigationItems($nav->getMenu());
|
||||
|
||||
$nav->selectFilter(null);
|
||||
|
@ -66,9 +81,12 @@ abstract class DrydockLogController
|
|||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$blueprint = $this->getBlueprint();
|
||||
$resource = $this->getResource();
|
||||
$lease = $this->getLease();
|
||||
$operation = $this->getOperation();
|
||||
if ($blueprint) {
|
||||
$id = $blueprint->getID();
|
||||
|
||||
|
@ -111,6 +129,20 @@ abstract class DrydockLogController
|
|||
$crumbs->addTextCrumb(
|
||||
pht('Logs'),
|
||||
$this->getApplicationURI("lease/{$id}/logs/"));
|
||||
} else if ($operation) {
|
||||
$id = $operation->getID();
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Operations'),
|
||||
$this->getApplicationURI('operation/'));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Repository Operation %d', $id),
|
||||
$this->getApplicationURI("operation/{$id}/"));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Logs'),
|
||||
$this->getApplicationURI("operation/{$id}/logs/"));
|
||||
}
|
||||
|
||||
return $crumbs;
|
||||
|
|
|
@ -46,6 +46,17 @@ final class DrydockLogListController extends DrydockLogController {
|
|||
$engine->setLease($lease);
|
||||
$this->setLease($lease);
|
||||
break;
|
||||
case 'operation':
|
||||
$operation = id(new DrydockRepositoryOperationQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->executeOne();
|
||||
if (!$operation) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$engine->setOperation($operation);
|
||||
$this->setOperation($operation);
|
||||
break;
|
||||
default:
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
|
|
@ -47,13 +47,25 @@ final class DrydockRepositoryOperationViewController
|
|||
->setUser($viewer)
|
||||
->setOperation($operation);
|
||||
|
||||
$log_query = id(new DrydockLogQuery())
|
||||
->withOperationPHIDs(array($operation->getPHID()));
|
||||
|
||||
$log_table = $this->buildLogTable($log_query)
|
||||
->setHideOperations(true);
|
||||
|
||||
$logs = $this->buildLogBox(
|
||||
$log_table,
|
||||
$this->getApplicationURI("operation/{$id}/logs/query/all/"));
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setCurtain($curtain)
|
||||
->addPropertySection(pht('Properties'), $properties)
|
||||
->setMainColumn(array(
|
||||
$status_view,
|
||||
));
|
||||
->setMainColumn(
|
||||
array(
|
||||
$status_view,
|
||||
$logs,
|
||||
));
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
|
|
|
@ -48,8 +48,11 @@ final class DrydockResourceViewController extends DrydockResourceController {
|
|||
$log_query = id(new DrydockLogQuery())
|
||||
->withResourcePHIDs(array($resource->getPHID()));
|
||||
|
||||
$log_box = $this->buildLogBox(
|
||||
$log_query,
|
||||
$log_table = $this->buildLogTable($log_query)
|
||||
->setHideResources(true);
|
||||
|
||||
$logs = $this->buildLogBox(
|
||||
$log_table,
|
||||
$this->getApplicationURI("resource/{$id}/logs/query/all/"));
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
|
@ -86,11 +89,12 @@ final class DrydockResourceViewController extends DrydockResourceController {
|
|||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setCurtain($curtain)
|
||||
->setMainColumn(array(
|
||||
$object_box,
|
||||
$lease_box,
|
||||
$log_box,
|
||||
));
|
||||
->setMainColumn(
|
||||
array(
|
||||
$object_box,
|
||||
$lease_box,
|
||||
$logs,
|
||||
));
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
final class DrydockOperationWorkLogType extends DrydockLogType {
|
||||
|
||||
const LOGCONST = 'core.operation.work';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Started Work');
|
||||
}
|
||||
|
||||
public function getLogTypeIcon(array $data) {
|
||||
return 'fa-check green';
|
||||
}
|
||||
|
||||
public function renderLog(array $data) {
|
||||
return pht('Started this operation in a working copy.');
|
||||
}
|
||||
|
||||
}
|
27
src/applications/drydock/logtype/DrydockTextLogType.php
Normal file
27
src/applications/drydock/logtype/DrydockTextLogType.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Simple convenience log type for logging arbitrary text.
|
||||
*
|
||||
* Drydock logs can be given formal types, which allows them to be translated
|
||||
* and filtered. If you don't particularly care about fancy logging features,
|
||||
* you can use this log type to just dump some text into the log. Maybe you
|
||||
* could upgrade to more formal logging later.
|
||||
*/
|
||||
final class DrydockTextLogType extends DrydockLogType {
|
||||
|
||||
const LOGCONST = 'core.text';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Text');
|
||||
}
|
||||
|
||||
public function getLogTypeIcon(array $data) {
|
||||
return 'fa-file-text-o grey';
|
||||
}
|
||||
|
||||
public function renderLog(array $data) {
|
||||
return idx($data, 'text');
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ final class DrydockRepositoryOperationPHIDType extends PhabricatorPHIDType {
|
|||
const TYPECONST = 'DRYO';
|
||||
|
||||
public function getTypeName() {
|
||||
return pht('Drydock Repository Operation');
|
||||
return pht('Repository Operation');
|
||||
}
|
||||
|
||||
public function newObject() {
|
||||
|
@ -33,7 +33,7 @@ final class DrydockRepositoryOperationPHIDType extends PhabricatorPHIDType {
|
|||
$operation = $objects[$phid];
|
||||
$id = $operation->getID();
|
||||
|
||||
$handle->setName(pht('Drydock Repository Operation %d', $id));
|
||||
$handle->setName(pht('Repository Operation %d', $id));
|
||||
$handle->setURI("/drydock/operation/{$id}/");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ final class DrydockLogQuery extends DrydockQuery {
|
|||
private $blueprintPHIDs;
|
||||
private $resourcePHIDs;
|
||||
private $leasePHIDs;
|
||||
private $operationPHIDs;
|
||||
|
||||
public function withBlueprintPHIDs(array $phids) {
|
||||
$this->blueprintPHIDs = $phids;
|
||||
|
@ -21,6 +22,11 @@ final class DrydockLogQuery extends DrydockQuery {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withOperationPHIDs(array $phids) {
|
||||
$this->operationPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new DrydockLog();
|
||||
}
|
||||
|
@ -93,6 +99,27 @@ final class DrydockLogQuery extends DrydockQuery {
|
|||
$log->attachLease($lease);
|
||||
}
|
||||
|
||||
$operation_phids = array_filter(mpull($logs, 'getOperationPHID'));
|
||||
if ($operation_phids) {
|
||||
$operations = id(new DrydockRepositoryOperationQuery())
|
||||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($operation_phids)
|
||||
->execute();
|
||||
$operations = mpull($operations, null, 'getPHID');
|
||||
} else {
|
||||
$operations = array();
|
||||
}
|
||||
|
||||
foreach ($logs as $key => $log) {
|
||||
$operation = null;
|
||||
$operation_phid = $log->getOperationPHID();
|
||||
if ($operation_phid) {
|
||||
$operation = idx($operations, $operation_phid);
|
||||
}
|
||||
$log->attachOperation($operation);
|
||||
}
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
|
@ -120,6 +147,13 @@ final class DrydockLogQuery extends DrydockQuery {
|
|||
$this->leasePHIDs);
|
||||
}
|
||||
|
||||
if ($this->operationPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'operationPHID IN (%Ls)',
|
||||
$this->operationPHIDs);
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
|
|||
private $blueprint;
|
||||
private $resource;
|
||||
private $lease;
|
||||
private $operation;
|
||||
|
||||
public function setBlueprint(DrydockBlueprint $blueprint) {
|
||||
$this->blueprint = $blueprint;
|
||||
|
@ -33,6 +34,15 @@ final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
|
|||
return $this->lease;
|
||||
}
|
||||
|
||||
public function setOperation(DrydockRepositoryOperation $operation) {
|
||||
$this->operation = $operation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOperation() {
|
||||
return $this->operation;
|
||||
}
|
||||
|
||||
public function canUseInPanelContext() {
|
||||
// Prevent use on Dashboard panels since all log queries currently need a
|
||||
// parent object and these don't seem particularly useful in any case.
|
||||
|
@ -65,6 +75,11 @@ final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
|
|||
$query->withLeasePHIDs(array($lease->getPHID()));
|
||||
}
|
||||
|
||||
$operation = $this->getOperation();
|
||||
if ($operation) {
|
||||
$query->withOperationPHIDs(array($operation->getPHID()));
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
@ -97,9 +112,15 @@ final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
|
|||
return "/drydock/lease/{$id}/logs/{$path}";
|
||||
}
|
||||
|
||||
$operation = $this->getOperation();
|
||||
if ($operation) {
|
||||
$id = $operation->getID();
|
||||
return "/drydock/operation/{$id}/logs/{$path}";
|
||||
}
|
||||
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Search engine has no blueprint, resource, or lease.'));
|
||||
'Search engine has no blueprint, resource, lease, or operation.'));
|
||||
}
|
||||
|
||||
protected function getBuiltinQueryNames() {
|
||||
|
|
|
@ -6,6 +6,7 @@ final class DrydockLog extends DrydockDAO
|
|||
protected $blueprintPHID;
|
||||
protected $resourcePHID;
|
||||
protected $leasePHID;
|
||||
protected $operationPHID;
|
||||
protected $epoch;
|
||||
protected $type;
|
||||
protected $data = array();
|
||||
|
@ -13,6 +14,7 @@ final class DrydockLog extends DrydockDAO
|
|||
private $blueprint = self::ATTACHABLE;
|
||||
private $resource = self::ATTACHABLE;
|
||||
private $lease = self::ATTACHABLE;
|
||||
private $operation = self::ATTACHABLE;
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
|
@ -24,6 +26,7 @@ final class DrydockLog extends DrydockDAO
|
|||
'blueprintPHID' => 'phid?',
|
||||
'resourcePHID' => 'phid?',
|
||||
'leasePHID' => 'phid?',
|
||||
'operationPHID' => 'phid?',
|
||||
'type' => 'text64',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
|
@ -36,6 +39,9 @@ final class DrydockLog extends DrydockDAO
|
|||
'key_lease' => array(
|
||||
'columns' => array('leasePHID', 'type'),
|
||||
),
|
||||
'key_operation' => array(
|
||||
'columns' => array('operationPHID', 'type'),
|
||||
),
|
||||
'epoch' => array(
|
||||
'columns' => array('epoch'),
|
||||
),
|
||||
|
@ -70,6 +76,16 @@ final class DrydockLog extends DrydockDAO
|
|||
return $this->assertAttached($this->lease);
|
||||
}
|
||||
|
||||
public function attachOperation(
|
||||
DrydockRepositoryOperation $operation = null) {
|
||||
$this->operation = $operation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOperation() {
|
||||
return $this->assertAttached($this->operation);
|
||||
}
|
||||
|
||||
public function isComplete() {
|
||||
if ($this->getBlueprintPHID() && !$this->getBlueprint()) {
|
||||
return false;
|
||||
|
@ -83,6 +99,10 @@ final class DrydockLog extends DrydockDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
if ($this->getOperationPHID() && !$this->getOperation()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -108,8 +128,8 @@ final class DrydockLog extends DrydockDAO
|
|||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'To view log details, you must be able to view the associated '.
|
||||
'blueprint, resource and lease.');
|
||||
'To view log details, you must be able to view all associated '.
|
||||
'blueprints, resources, leases, and repository operations.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ final class DrydockRepositoryOperation extends DrydockDAO
|
|||
private $repository = self::ATTACHABLE;
|
||||
private $object = self::ATTACHABLE;
|
||||
private $implementation = self::ATTACHABLE;
|
||||
private $workingCopyLease = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewOperation(
|
||||
DrydockRepositoryOperationType $op) {
|
||||
|
@ -90,6 +91,19 @@ final class DrydockRepositoryOperation extends DrydockDAO
|
|||
return $this->implementation;
|
||||
}
|
||||
|
||||
public function getWorkingCopyLease() {
|
||||
return $this->assertAttached($this->workingCopyLease);
|
||||
}
|
||||
|
||||
public function attachWorkingCopyLease(DrydockLease $lease) {
|
||||
$this->workingCopyLease = $lease;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasWorkingCopyLease() {
|
||||
return ($this->workingCopyLease !== self::ATTACHABLE);
|
||||
}
|
||||
|
||||
public function getProperty($key, $default = null) {
|
||||
return idx($this->properties, $key, $default);
|
||||
}
|
||||
|
@ -189,6 +203,37 @@ final class DrydockRepositoryOperation extends DrydockDAO
|
|||
return $this->getProperty('exec.workingcopy.error');
|
||||
}
|
||||
|
||||
public function logText($text) {
|
||||
return $this->logEvent(
|
||||
DrydockTextLogType::LOGCONST,
|
||||
array(
|
||||
'text' => $text,
|
||||
));
|
||||
}
|
||||
|
||||
public function logEvent($type, array $data = array()) {
|
||||
$log = id(new DrydockLog())
|
||||
->setEpoch(PhabricatorTime::getNow())
|
||||
->setType($type)
|
||||
->setData($data);
|
||||
|
||||
$log->setOperationPHID($this->getPHID());
|
||||
|
||||
if ($this->hasWorkingCopyLease()) {
|
||||
$lease = $this->getWorkingCopyLease();
|
||||
$log->setLeasePHID($lease->getPHID());
|
||||
|
||||
$resource_phid = $lease->getResourcePHID();
|
||||
if ($resource_phid) {
|
||||
$resource = $lease->getResource();
|
||||
|
||||
$log->setResourcePHID($resource->getPHID());
|
||||
$log->setBlueprintPHID($resource->getBlueprintPHID());
|
||||
}
|
||||
}
|
||||
|
||||
return $log->save();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
|
|
@ -3,6 +3,46 @@
|
|||
final class DrydockLogListView extends AphrontView {
|
||||
|
||||
private $logs;
|
||||
private $hideBlueprints;
|
||||
private $hideResources;
|
||||
private $hideLeases;
|
||||
private $hideOperations;
|
||||
|
||||
public function setHideBlueprints($hide_blueprints) {
|
||||
$this->hideBlueprints = $hide_blueprints;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHideBlueprints() {
|
||||
return $this->hideBlueprints;
|
||||
}
|
||||
|
||||
public function setHideResources($hide_resources) {
|
||||
$this->hideResources = $hide_resources;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHideResources() {
|
||||
return $this->hideResources;
|
||||
}
|
||||
|
||||
public function setHideLeases($hide_leases) {
|
||||
$this->hideLeases = $hide_leases;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHideLeases() {
|
||||
return $this->hideLeases;
|
||||
}
|
||||
|
||||
public function setHideOperations($hide_operations) {
|
||||
$this->hideOperations = $hide_operations;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHideOperations() {
|
||||
return $this->hideOperations;
|
||||
}
|
||||
|
||||
public function setLogs(array $logs) {
|
||||
assert_instances_of($logs, 'DrydockLog');
|
||||
|
@ -41,6 +81,13 @@ final class DrydockLogListView extends AphrontView {
|
|||
$lease = null;
|
||||
}
|
||||
|
||||
$operation_phid = $log->getOperationPHID();
|
||||
if ($operation_phid) {
|
||||
$operation = $viewer->renderHandle($operation_phid);
|
||||
} else {
|
||||
$operation = null;
|
||||
}
|
||||
|
||||
if ($log->isComplete()) {
|
||||
$type_key = $log->getType();
|
||||
if (isset($types[$type_key])) {
|
||||
|
@ -72,6 +119,7 @@ final class DrydockLogListView extends AphrontView {
|
|||
$blueprint,
|
||||
$resource,
|
||||
$lease,
|
||||
$operation,
|
||||
id(new PHUIIconView())->setIcon($icon),
|
||||
$type,
|
||||
$data,
|
||||
|
@ -86,16 +134,25 @@ final class DrydockLogListView extends AphrontView {
|
|||
pht('Blueprint'),
|
||||
pht('Resource'),
|
||||
pht('Lease'),
|
||||
pht('Operation'),
|
||||
null,
|
||||
pht('Type'),
|
||||
pht('Data'),
|
||||
pht('Date'),
|
||||
))
|
||||
->setColumnVisibility(
|
||||
array(
|
||||
!$this->getHideBlueprints(),
|
||||
!$this->getHideResources(),
|
||||
!$this->getHideLeases(),
|
||||
!$this->getHideOperations(),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'icon',
|
||||
'',
|
||||
'wide',
|
||||
|
|
|
@ -59,6 +59,10 @@ final class DrydockRepositoryOperationUpdateWorker
|
|||
// No matter what happens here, destroy the lease away once we're done.
|
||||
$lease->setReleaseOnDestruction(true);
|
||||
|
||||
$operation->attachWorkingCopyLease($lease);
|
||||
|
||||
$operation->logEvent(DrydockOperationWorkLogType::LOGCONST);
|
||||
|
||||
$operation->applyOperation($interface);
|
||||
|
||||
} catch (PhabricatorWorkerYieldException $ex) {
|
||||
|
|
|
@ -71,7 +71,7 @@ final class PhabricatorOwnersDetailController
|
|||
'package' => $package->getPHID(),
|
||||
));
|
||||
|
||||
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
|
||||
$status_concern = DiffusionCommitAuditStatus::CONCERN_RAISED;
|
||||
|
||||
$attention_commits = id(new DiffusionCommitQuery())
|
||||
->setViewer($request->getUser())
|
||||
|
|
|
@ -306,6 +306,14 @@ final class PhabricatorUser
|
|||
return ($this->session !== self::ATTACHABLE);
|
||||
}
|
||||
|
||||
public function hasHighSecuritySession() {
|
||||
if (!$this->hasSession()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getSession()->isHighSecuritySession();
|
||||
}
|
||||
|
||||
private function generateConduitCertificate() {
|
||||
return Filesystem::readRandomCharacters(255);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@ final class PhabricatorPhrictionApplication extends PhabricatorApplication {
|
|||
|
||||
'preview/(?P<slug>.*/)' => 'PhrictionMarkupPreviewController',
|
||||
'diff/(?P<id>[1-9]\d*)/' => 'PhrictionDiffController',
|
||||
|
||||
$this->getEditRoutePattern('document/edit/')
|
||||
=> 'PhrictionEditEngineController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ final class PhrictionDiffController extends PhrictionController {
|
|||
$navigation_table = null;
|
||||
if ($l + 1 == $r) {
|
||||
$nav_l = ($l > 1);
|
||||
$nav_r = ($r != $current->getVersion());
|
||||
$nav_r = ($r != $document->getMaxVersion());
|
||||
|
||||
$uri = $request->getRequestURI();
|
||||
|
||||
|
@ -191,30 +191,28 @@ final class PhrictionDiffController extends PhrictionController {
|
|||
PhrictionChangeType::CHANGE_MOVE_AWAY => true, // Plain silly
|
||||
PhrictionChangeType::CHANGE_STUB => true, // Utterly silly
|
||||
);
|
||||
|
||||
if (isset($hidden_statuses[$content->getChangeType()])) {
|
||||
// Don't show an edit/revert button for changes which deleted, moved or
|
||||
// stubbed the content since it's silly.
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($content->getID() == $current->getID()) {
|
||||
return phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/phriction/edit/'.$document_id.'/',
|
||||
'class' => 'button button-grey',
|
||||
),
|
||||
pht('Edit Current Version'));
|
||||
if ($version == $current->getVersion()) {
|
||||
$label = pht('Edit Current Version %s...', new PhutilNumber($version));
|
||||
} else if ($version < $current->getVersion()) {
|
||||
$label = pht('Edit Older Version %s...', new PhutilNumber($version));
|
||||
} else {
|
||||
$label = pht('Edit Draft Version %s...', new PhutilNumber($version));
|
||||
}
|
||||
|
||||
|
||||
return phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/phriction/edit/'.$document_id.'/?revert='.$version,
|
||||
'class' => 'button button-grey',
|
||||
),
|
||||
pht('Revert to Version %s...', $version));
|
||||
$label);
|
||||
}
|
||||
|
||||
private function renderComparisonTable(array $content) {
|
||||
|
|
|
@ -186,6 +186,35 @@ final class PhrictionDocumentController
|
|||
);
|
||||
} else {
|
||||
$content = $document->getContent();
|
||||
|
||||
if ($content->getVersion() < $document->getMaxVersion()) {
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$document,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
if ($can_edit) {
|
||||
$document_uri = new PhutilURI($document->getURI());
|
||||
$draft_uri = $document_uri->alter('v', $document->getMaxVersion());
|
||||
|
||||
$draft_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $draft_uri,
|
||||
),
|
||||
pht('View Draft Version'));
|
||||
|
||||
$draft_link = phutil_tag('strong', array(), $draft_link);
|
||||
|
||||
$version_note = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
|
||||
->appendChild(
|
||||
array(
|
||||
pht('This document has unpublished draft changes.'),
|
||||
' ',
|
||||
$draft_link,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$page_title = $content->getTitle();
|
||||
|
@ -348,6 +377,17 @@ final class PhrictionDocumentController
|
|||
$page_content->setCurtain($curtain);
|
||||
}
|
||||
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$document,
|
||||
new PhrictionTransactionQuery());
|
||||
|
||||
$edit_engine = id(new PhrictionDocumentEditEngine())
|
||||
->setViewer($viewer)
|
||||
->setTargetObject($document);
|
||||
|
||||
$comment_view = $edit_engine
|
||||
->buildEditEngineCommentView($document);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($page_title)
|
||||
->setCrumbs($crumbs)
|
||||
|
@ -356,7 +396,16 @@ final class PhrictionDocumentController
|
|||
array(
|
||||
$page_content,
|
||||
$prop_list,
|
||||
$children,
|
||||
phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phui-document-view-pro-box',
|
||||
),
|
||||
array(
|
||||
$children,
|
||||
$timeline,
|
||||
$comment_view,
|
||||
)),
|
||||
));
|
||||
|
||||
}
|
||||
|
@ -427,22 +476,31 @@ final class PhrictionDocumentController
|
|||
if ($is_draft) {
|
||||
$publish_name = pht('Publish Draft');
|
||||
} else {
|
||||
$publish_name = pht('Publish Revert');
|
||||
$publish_name = pht('Publish Older Version');
|
||||
}
|
||||
|
||||
// If you're looking at the current version; and it's an unpublished
|
||||
// draft; and you can publish it, add a UI hint that this might be an
|
||||
// interesting action to take.
|
||||
$hint_publish = false;
|
||||
if ($is_draft) {
|
||||
if ($can_publish) {
|
||||
if ($document->getMaxVersion() == $content->getVersion()) {
|
||||
$hint_publish = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$publish_uri = "/phriction/publish/{$id}/{$content_id}/";
|
||||
|
||||
if (PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
|
||||
$publish_name = pht('Publish (Prototype!)');
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName($publish_name)
|
||||
->setIcon('fa-upload')
|
||||
->setDisabled(!$can_publish)
|
||||
->setWorkflow(true)
|
||||
->setHref($publish_uri));
|
||||
}
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName($publish_name)
|
||||
->setIcon('fa-upload')
|
||||
->setSelected($hint_publish)
|
||||
->setDisabled(!$can_publish)
|
||||
->setWorkflow(true)
|
||||
->setHref($publish_uri));
|
||||
|
||||
if ($document->getStatus() == PhrictionDocumentStatus::STATUS_EXISTS) {
|
||||
$curtain->addAction(
|
||||
|
@ -600,7 +658,7 @@ final class PhrictionDocumentController
|
|||
),
|
||||
$list)));
|
||||
|
||||
return phutil_tag_div('phui-document-view-pro-box', $box);
|
||||
return $box;
|
||||
}
|
||||
|
||||
private function renderChildDocumentLink(array $info) {
|
||||
|
|
|
@ -72,43 +72,6 @@ final class PhrictionEditController
|
|||
}
|
||||
}
|
||||
|
||||
if ($request->getBool('nodraft')) {
|
||||
$draft = null;
|
||||
$draft_key = null;
|
||||
} else {
|
||||
if ($document->getPHID()) {
|
||||
$draft_key = $document->getPHID().':'.$content->getVersion();
|
||||
} else {
|
||||
$draft_key = 'phriction:'.$content->getSlug();
|
||||
}
|
||||
$draft = id(new PhabricatorDraft())->loadOneWhere(
|
||||
'authorPHID = %s AND draftKey = %s',
|
||||
$viewer->getPHID(),
|
||||
$draft_key);
|
||||
}
|
||||
|
||||
if ($draft &&
|
||||
strlen($draft->getDraft()) &&
|
||||
($draft->getDraft() != $content->getContent())) {
|
||||
$content_text = $draft->getDraft();
|
||||
|
||||
$discard = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $request->getRequestURI()->alter('nodraft', true),
|
||||
),
|
||||
pht('discard this draft'));
|
||||
|
||||
$draft_note = new PHUIInfoView();
|
||||
$draft_note->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
|
||||
$draft_note->setTitle(pht('Recovered Draft'));
|
||||
$draft_note->appendChild(
|
||||
pht('Showing a saved draft of your edits, you can %s.', $discard));
|
||||
} else {
|
||||
$content_text = $content->getContent();
|
||||
$draft_note = null;
|
||||
}
|
||||
|
||||
require_celerity_resource('phriction-document-css');
|
||||
|
||||
$e_title = true;
|
||||
|
@ -131,7 +94,15 @@ final class PhrictionEditController
|
|||
|
||||
$v_space = $document->getSpacePHID();
|
||||
|
||||
$content_text = $content->getContent();
|
||||
$is_draft_mode = ($document->getContent()->getVersion() != $max_version);
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
if ($is_new) {
|
||||
$save_as_draft = false;
|
||||
} else {
|
||||
$save_as_draft = ($is_draft_mode || $request->getExists('draft'));
|
||||
}
|
||||
|
||||
$title = $request->getStr('title');
|
||||
$content_text = $request->getStr('content');
|
||||
|
@ -143,13 +114,19 @@ final class PhrictionEditController
|
|||
$v_projects = $request->getArr('projects');
|
||||
$v_space = $request->getStr('spacePHID');
|
||||
|
||||
if ($save_as_draft) {
|
||||
$edit_type = PhrictionDocumentDraftTransaction::TRANSACTIONTYPE;
|
||||
} else {
|
||||
$edit_type = PhrictionDocumentContentTransaction::TRANSACTIONTYPE;
|
||||
}
|
||||
|
||||
$xactions = array();
|
||||
|
||||
$xactions[] = id(new PhrictionTransaction())
|
||||
->setTransactionType(PhrictionDocumentTitleTransaction::TRANSACTIONTYPE)
|
||||
->setNewValue($title);
|
||||
$xactions[] = id(new PhrictionTransaction())
|
||||
->setTransactionType(
|
||||
PhrictionDocumentContentTransaction::TRANSACTIONTYPE)
|
||||
->setTransactionType($edit_type)
|
||||
->setNewValue($content_text);
|
||||
$xactions[] = id(new PhrictionTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
|
||||
|
@ -181,11 +158,15 @@ final class PhrictionEditController
|
|||
try {
|
||||
$editor->applyTransactions($document, $xactions);
|
||||
|
||||
if ($draft) {
|
||||
$draft->delete();
|
||||
$uri = PhrictionDocument::getSlugURI($document->getSlug());
|
||||
$uri = new PhutilURI($uri);
|
||||
|
||||
// If the user clicked "Save as Draft", take them to the draft, not
|
||||
// to the current published page.
|
||||
if ($save_as_draft) {
|
||||
$uri = $uri->alter('v', $document->getMaxVersion());
|
||||
}
|
||||
|
||||
$uri = PhrictionDocument::getSlugURI($document->getSlug());
|
||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||
$validation_exception = $ex;
|
||||
|
@ -215,7 +196,7 @@ final class PhrictionEditController
|
|||
if ($overwrite) {
|
||||
$submit_button = pht('Overwrite Changes');
|
||||
} else {
|
||||
$submit_button = pht('Save Changes');
|
||||
$submit_button = pht('Save and Publish');
|
||||
}
|
||||
} else {
|
||||
$submit_button = pht('Create Document');
|
||||
|
@ -235,11 +216,9 @@ final class PhrictionEditController
|
|||
$view_capability = PhabricatorPolicyCapability::CAN_VIEW;
|
||||
$edit_capability = PhabricatorPolicyCapability::CAN_EDIT;
|
||||
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->addHiddenInput('slug', $document->getSlug())
|
||||
->addHiddenInput('nodraft', $request->getBool('nodraft'))
|
||||
->addHiddenInput('contentVersion', $max_version)
|
||||
->addHiddenInput('overwrite', $overwrite)
|
||||
->appendChild(
|
||||
|
@ -293,11 +272,31 @@ final class PhrictionEditController
|
|||
->setLabel(pht('Edit Notes'))
|
||||
->setValue($notes)
|
||||
->setError(null)
|
||||
->setName('description'))
|
||||
->appendChild(
|
||||
->setName('description'));
|
||||
|
||||
if ($is_draft_mode) {
|
||||
$form->appendControl(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->addCancelButton($cancel_uri)
|
||||
->setValue($submit_button));
|
||||
->setValue(pht('Save Draft')));
|
||||
} else {
|
||||
$submit = id(new AphrontFormSubmitControl());
|
||||
|
||||
if (!$is_new) {
|
||||
$draft_button = id(new PHUIButtonView())
|
||||
->setTag('input')
|
||||
->setName('draft')
|
||||
->setText(pht('Save as Draft'))
|
||||
->setColor(PHUIButtonView::GREEN);
|
||||
$submit->addButton($draft_button);
|
||||
}
|
||||
|
||||
$submit
|
||||
->addCancelButton($cancel_uri)
|
||||
->setValue($submit_button);
|
||||
|
||||
$form->appendControl($submit);
|
||||
}
|
||||
|
||||
$form_box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText($page_title)
|
||||
|
@ -325,7 +324,6 @@ final class PhrictionEditController
|
|||
$view = id(new PHUITwoColumnView())
|
||||
->setFooter(
|
||||
array(
|
||||
$draft_note,
|
||||
$form_box,
|
||||
$preview,
|
||||
));
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
final class PhrictionEditEngineController
|
||||
extends PhrictionController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
// NOTE: For now, this controller is only used to handle comments.
|
||||
|
||||
return id(new PhrictionDocumentEditEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -63,7 +63,7 @@ final class PhrictionPublishController
|
|||
}
|
||||
|
||||
if ($content->getVersion() < $document->getContent()->getVersion()) {
|
||||
$title = pht('Revert Document?');
|
||||
$title = pht('Publish Older Version?');
|
||||
$body = pht(
|
||||
'Revert the published version of this document to an older '.
|
||||
'version?');
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
final class PhrictionDocumentEditEngine
|
||||
extends PhabricatorEditEngine {
|
||||
|
||||
const ENGINECONST = 'phriction.document';
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Phriction Document');
|
||||
}
|
||||
|
||||
public function getSummaryHeader() {
|
||||
return pht('Edit Phriction Document Configurations');
|
||||
}
|
||||
|
||||
public function getSummaryText() {
|
||||
return pht('This engine is used to edit Phriction documents.');
|
||||
}
|
||||
|
||||
public function getEngineApplicationClass() {
|
||||
return 'PhabricatorPhrictionApplication';
|
||||
}
|
||||
|
||||
protected function newEditableObject() {
|
||||
$viewer = $this->getViewer();
|
||||
return PhrictionDocument::initializeNewDocument(
|
||||
$viewer,
|
||||
'/');
|
||||
}
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return id(new PhrictionDocumentQuery())
|
||||
->needContent(true);
|
||||
}
|
||||
|
||||
protected function getObjectCreateTitleText($object) {
|
||||
return pht('Create Document');
|
||||
}
|
||||
|
||||
protected function getObjectCreateButtonText($object) {
|
||||
return pht('Create Document');
|
||||
}
|
||||
|
||||
protected function getObjectEditTitleText($object) {
|
||||
return pht('Edit Document: %s', $object->getContent()->getTitle());
|
||||
}
|
||||
|
||||
protected function getObjectEditShortText($object) {
|
||||
return pht('Edit Document');
|
||||
}
|
||||
|
||||
protected function getObjectCreateShortText() {
|
||||
return pht('Create Document');
|
||||
}
|
||||
|
||||
protected function getObjectName() {
|
||||
return pht('Document');
|
||||
}
|
||||
|
||||
protected function getEditorURI() {
|
||||
return '/phriction/document/edit/';
|
||||
}
|
||||
|
||||
protected function getObjectCreateCancelURI($object) {
|
||||
return '/phriction/document/';
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
return $object->getURI();
|
||||
}
|
||||
|
||||
protected function getCreateNewObjectPolicy() {
|
||||
// NOTE: For now, this engine is only to support commenting.
|
||||
return PhabricatorPolicies::POLICY_NOONE;
|
||||
}
|
||||
|
||||
protected function buildCustomEditFields($object) {
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
|
@ -74,6 +74,21 @@ final class PhrictionTransactionEditor
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setShouldPublishContent(
|
||||
PhrictionDocument $object,
|
||||
$publish) {
|
||||
|
||||
if ($publish) {
|
||||
$content_phid = $this->getNewContent()->getPHID();
|
||||
} else {
|
||||
$content_phid = $this->getOldContent()->getPHID();
|
||||
}
|
||||
|
||||
$object->setContentPHID($content_phid);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorPhrictionApplication';
|
||||
}
|
||||
|
|
|
@ -1,87 +1,25 @@
|
|||
<?php
|
||||
|
||||
final class PhrictionDocumentContentTransaction
|
||||
extends PhrictionDocumentVersionTransaction {
|
||||
extends PhrictionDocumentEditTransaction {
|
||||
|
||||
const TRANSACTIONTYPE = 'content';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
if ($this->getEditor()->getIsNewObject()) {
|
||||
return null;
|
||||
}
|
||||
return $object->getContent()->getContent();
|
||||
}
|
||||
|
||||
public function generateNewValue($object, $value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
parent::applyInternalEffects($object, $value);
|
||||
|
||||
$object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
|
||||
|
||||
$content = $this->getNewDocumentContent($object);
|
||||
$content->setContent($value);
|
||||
}
|
||||
|
||||
public function shouldHide() {
|
||||
if ($this->getOldValue() === null) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getActionStrength() {
|
||||
return 1.3;
|
||||
}
|
||||
|
||||
public function getActionName() {
|
||||
return pht('Edited');
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s edited the content of this document.',
|
||||
$this->renderAuthor());
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
return pht(
|
||||
'%s edited the content of %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderObject());
|
||||
}
|
||||
|
||||
public function hasChangeDetailView() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getMailDiffSectionHeader() {
|
||||
return pht('CHANGES TO DOCUMENT CONTENT');
|
||||
}
|
||||
|
||||
public function newChangeDetailView() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
|
||||
->setViewer($viewer)
|
||||
->setOldText($this->getOldValue())
|
||||
->setNewText($this->getNewValue());
|
||||
}
|
||||
|
||||
public function newRemarkupChanges() {
|
||||
$changes = array();
|
||||
|
||||
$changes[] = $this->newRemarkupChange()
|
||||
->setOldValue($this->getOldValue())
|
||||
->setNewValue($this->getNewValue());
|
||||
|
||||
return $changes;
|
||||
$this->getEditor()->setShouldPublishContent($object, true);
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
// NOTE: This is slightly different from the draft validation. Here,
|
||||
// we're validating that: you can't edit away a document; and you can't
|
||||
// create an empty document.
|
||||
|
||||
$content = $object->getContent()->getContent();
|
||||
if ($this->isEmptyTextTransaction($content, $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
final class PhrictionDocumentDraftTransaction
|
||||
extends PhrictionDocumentEditTransaction {
|
||||
|
||||
const TRANSACTIONTYPE = 'draft';
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
parent::applyInternalEffects($object, $value);
|
||||
|
||||
$this->getEditor()->setShouldPublishContent($object, false);
|
||||
}
|
||||
|
||||
public function shouldHideForFeed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
// NOTE: We're only validating that you can't edit a document down to
|
||||
// nothing in a draft transaction. Alone, this doesn't prevent you from
|
||||
// creating a document with no content. The content transaction has
|
||||
// validation for that.
|
||||
|
||||
if (!$xactions) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
$content = $object->getContent()->getContent();
|
||||
if ($this->isEmptyTextTransaction($content, $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('Documents must have content.'));
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
abstract class PhrictionDocumentEditTransaction
|
||||
extends PhrictionDocumentVersionTransaction {
|
||||
|
||||
public function generateOldValue($object) {
|
||||
if ($this->getEditor()->getIsNewObject()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// NOTE: We want to get the newest version of the content here, regardless
|
||||
// of whether it's published or not.
|
||||
|
||||
$actor = $this->getActor();
|
||||
|
||||
return id(new PhrictionContentQuery())
|
||||
->setViewer($actor)
|
||||
->withDocumentPHIDs(array($object->getPHID()))
|
||||
->setOrder('newest')
|
||||
->setLimit(1)
|
||||
->executeOne()
|
||||
->getContent();
|
||||
}
|
||||
|
||||
public function generateNewValue($object, $value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$content = $this->getNewDocumentContent($object);
|
||||
$content->setContent($value);
|
||||
}
|
||||
|
||||
public function getActionStrength() {
|
||||
return 1.3;
|
||||
}
|
||||
|
||||
public function getActionName() {
|
||||
return pht('Edited');
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s edited the content of this document.',
|
||||
$this->renderAuthor());
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
return pht(
|
||||
'%s edited the content of %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderObject());
|
||||
}
|
||||
|
||||
public function getMailDiffSectionHeader() {
|
||||
return pht('CHANGES TO DOCUMENT CONTENT');
|
||||
}
|
||||
|
||||
public function hasChangeDetailView() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function newChangeDetailView() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
|
||||
->setViewer($viewer)
|
||||
->setOldText($this->getOldValue())
|
||||
->setNewText($this->getNewValue());
|
||||
}
|
||||
|
||||
public function newRemarkupChanges() {
|
||||
$changes = array();
|
||||
|
||||
$changes[] = $this->newRemarkupChange()
|
||||
->setOldValue($this->getOldValue())
|
||||
->setNewValue($this->getNewValue());
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
}
|
|
@ -25,9 +25,8 @@ final class PhabricatorRepositoryCommit
|
|||
protected $committerIdentityPHID;
|
||||
protected $commitIdentifier;
|
||||
protected $epoch;
|
||||
protected $mailKey;
|
||||
protected $authorPHID;
|
||||
protected $auditStatus = PhabricatorAuditCommitStatusConstants::NONE;
|
||||
protected $auditStatus = DiffusionCommitAuditStatus::NONE;
|
||||
protected $summary = '';
|
||||
protected $importStatus = 0;
|
||||
|
||||
|
@ -116,11 +115,10 @@ final class PhabricatorRepositoryCommit
|
|||
self::CONFIG_TIMESTAMPS => false,
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'commitIdentifier' => 'text40',
|
||||
'mailKey' => 'bytes20',
|
||||
'authorPHID' => 'phid?',
|
||||
'authorIdentityPHID' => 'phid?',
|
||||
'committerIdentityPHID' => 'phid?',
|
||||
'auditStatus' => 'uint32',
|
||||
'auditStatus' => 'text32',
|
||||
'summary' => 'text255',
|
||||
'importStatus' => 'uint32',
|
||||
),
|
||||
|
@ -321,13 +319,6 @@ final class PhabricatorRepositoryCommit
|
|||
return mpull($audits, 'getAuditorPHID');
|
||||
}
|
||||
|
||||
public function save() {
|
||||
if (!$this->mailKey) {
|
||||
$this->mailKey = Filesystem::readRandomCharacters(20);
|
||||
}
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
$data = $this->loadCommitData();
|
||||
$audits = id(new PhabricatorRepositoryAuditRequest())
|
||||
|
@ -381,27 +372,24 @@ final class PhabricatorRepositoryCommit
|
|||
}
|
||||
}
|
||||
|
||||
$current_status = $this->getAuditStatus();
|
||||
$status_verify = PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION;
|
||||
|
||||
if ($any_concern) {
|
||||
if ($current_status == $status_verify) {
|
||||
if ($this->isAuditStatusNeedsVerification()) {
|
||||
// If the change is in "Needs Verification", we keep it there as
|
||||
// long as any auditors still have concerns.
|
||||
$status = $status_verify;
|
||||
$status = DiffusionCommitAuditStatus::NEEDS_VERIFICATION;
|
||||
} else {
|
||||
$status = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
|
||||
$status = DiffusionCommitAuditStatus::CONCERN_RAISED;
|
||||
}
|
||||
} else if ($any_accept) {
|
||||
if ($any_need) {
|
||||
$status = PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED;
|
||||
$status = DiffusionCommitAuditStatus::PARTIALLY_AUDITED;
|
||||
} else {
|
||||
$status = PhabricatorAuditCommitStatusConstants::FULLY_AUDITED;
|
||||
$status = DiffusionCommitAuditStatus::AUDITED;
|
||||
}
|
||||
} else if ($any_need) {
|
||||
$status = PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT;
|
||||
$status = DiffusionCommitAuditStatus::NEEDS_AUDIT;
|
||||
} else {
|
||||
$status = PhabricatorAuditCommitStatusConstants::NONE;
|
||||
$status = DiffusionCommitAuditStatus::NONE;
|
||||
}
|
||||
|
||||
return $this->setAuditStatus($status);
|
||||
|
@ -532,7 +520,31 @@ final class PhabricatorRepositoryCommit
|
|||
|
||||
public function getAuditStatusObject() {
|
||||
$status = $this->getAuditStatus();
|
||||
return PhabricatorAuditCommitStatusConstants::newForLegacyStatus($status);
|
||||
return DiffusionCommitAuditStatus::newForStatus($status);
|
||||
}
|
||||
|
||||
public function isAuditStatusNoAudit() {
|
||||
return $this->getAuditStatusObject()->isNoAudit();
|
||||
}
|
||||
|
||||
public function isAuditStatusNeedsAudit() {
|
||||
return $this->getAuditStatusObject()->isNeedsAudit();
|
||||
}
|
||||
|
||||
public function isAuditStatusConcernRaised() {
|
||||
return $this->getAuditStatusObject()->isConcernRaised();
|
||||
}
|
||||
|
||||
public function isAuditStatusNeedsVerification() {
|
||||
return $this->getAuditStatusObject()->isNeedsVerification();
|
||||
}
|
||||
|
||||
public function isAuditStatusPartiallyAudited() {
|
||||
return $this->getAuditStatusObject()->isPartiallyAudited();
|
||||
}
|
||||
|
||||
public function isAuditStatusAudited() {
|
||||
return $this->getAuditStatusObject()->isAudited();
|
||||
}
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
@ -584,7 +596,6 @@ final class PhabricatorRepositoryCommit
|
|||
'phid' => $this->getPHID(),
|
||||
'commitIdentifier' => $this->getCommitIdentifier(),
|
||||
'epoch' => $this->getEpoch(),
|
||||
'mailKey' => $this->getMailKey(),
|
||||
'authorPHID' => $this->getAuthorPHID(),
|
||||
'auditStatus' => $this->getAuditStatus(),
|
||||
'summary' => $this->getSummary(),
|
||||
|
@ -830,16 +841,110 @@ final class PhabricatorRepositoryCommit
|
|||
->setKey('identifier')
|
||||
->setType('string')
|
||||
->setDescription(pht('The commit identifier.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('repositoryPHID')
|
||||
->setType('phid')
|
||||
->setDescription(pht('The repository this commit belongs to.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('author')
|
||||
->setType('map<string, wild>')
|
||||
->setDescription(pht('Information about the commit author.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('committer')
|
||||
->setType('map<string, wild>')
|
||||
->setDescription(pht('Information about the committer.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('isImported')
|
||||
->setType('bool')
|
||||
->setDescription(pht('True if the commit is fully imported.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('isUnreachable')
|
||||
->setType('bool')
|
||||
->setDescription(
|
||||
pht(
|
||||
'True if the commit is not the ancestor of any tag, branch, or '.
|
||||
'ref.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('auditStatus')
|
||||
->setType('map<string, wild>')
|
||||
->setDescription(pht('Information about the current audit status.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('message')
|
||||
->setType('string')
|
||||
->setDescription(pht('The commit message.')),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFieldValuesForConduit() {
|
||||
$data = $this->getCommitData();
|
||||
|
||||
// NOTE: This data should be similar to the information returned about
|
||||
// commmits by "differential.diff.search" with the "commits" attachment.
|
||||
$author_identity = $this->getAuthorIdentity();
|
||||
if ($author_identity) {
|
||||
$author_name = $author_identity->getIdentityDisplayName();
|
||||
$author_email = $author_identity->getIdentityEmailAddress();
|
||||
$author_raw = $author_identity->getIdentityName();
|
||||
$author_identity_phid = $author_identity->getPHID();
|
||||
$author_user_phid = $author_identity->getCurrentEffectiveUserPHID();
|
||||
} else {
|
||||
$author_name = null;
|
||||
$author_email = null;
|
||||
$author_raw = null;
|
||||
$author_identity_phid = null;
|
||||
$author_user_phid = null;
|
||||
}
|
||||
|
||||
$committer_identity = $this->getCommitterIdentity();
|
||||
if ($committer_identity) {
|
||||
$committer_name = $committer_identity->getIdentityDisplayName();
|
||||
$committer_email = $committer_identity->getIdentityEmailAddress();
|
||||
$committer_raw = $committer_identity->getIdentityName();
|
||||
$committer_identity_phid = $committer_identity->getPHID();
|
||||
$committer_user_phid = $committer_identity->getCurrentEffectiveUserPHID();
|
||||
} else {
|
||||
$committer_name = null;
|
||||
$committer_email = null;
|
||||
$committer_raw = null;
|
||||
$committer_identity_phid = null;
|
||||
$committer_user_phid = null;
|
||||
}
|
||||
|
||||
$author_epoch = $data->getCommitDetail('authorEpoch');
|
||||
if ($author_epoch) {
|
||||
$author_epoch = (int)$author_epoch;
|
||||
} else {
|
||||
$author_epoch = null;
|
||||
}
|
||||
|
||||
$audit_status = $this->getAuditStatusObject();
|
||||
|
||||
return array(
|
||||
'identifier' => $this->getCommitIdentifier(),
|
||||
'repositoryPHID' => $this->getRepository()->getPHID(),
|
||||
'author' => array(
|
||||
'name' => $author_name,
|
||||
'email' => $author_email,
|
||||
'raw' => $author_raw,
|
||||
'epoch' => $author_epoch,
|
||||
'identityPHID' => $author_identity_phid,
|
||||
'userPHID' => $author_user_phid,
|
||||
),
|
||||
'committer' => array(
|
||||
'name' => $committer_name,
|
||||
'email' => $committer_email,
|
||||
'raw' => $committer_raw,
|
||||
'epoch' => (int)$this->getEpoch(),
|
||||
'identityPHID' => $committer_identity_phid,
|
||||
'userPHID' => $committer_user_phid,
|
||||
),
|
||||
'isUnreachable' => (bool)$this->isUnreachable(),
|
||||
'isImported' => (bool)$this->isImported(),
|
||||
'auditStatus' => array(
|
||||
'value' => $audit_status->getKey(),
|
||||
'name' => $audit_status->getName(),
|
||||
'closed' => (bool)$audit_status->getIsClosed(),
|
||||
'color.ansi' => $audit_status->getAnsiColor(),
|
||||
),
|
||||
'message' => $data->getCommitMessage(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -230,9 +230,20 @@ EOTEXT
|
|||
|
||||
$constants_rows = array();
|
||||
foreach ($constants as $constant) {
|
||||
if ($constant->getIsDeprecated()) {
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon('fa-exclamation-triangle', 'red');
|
||||
} else {
|
||||
$icon = null;
|
||||
}
|
||||
|
||||
$constants_rows[] = array(
|
||||
$constant->getKey(),
|
||||
$constant->getValue(),
|
||||
array(
|
||||
$icon,
|
||||
' ',
|
||||
$constant->getValue(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -244,7 +255,7 @@ EOTEXT
|
|||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'pre',
|
||||
'mono',
|
||||
'wide',
|
||||
));
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ final class PhabricatorSearchCheckboxesField
|
|||
extends PhabricatorSearchField {
|
||||
|
||||
private $options;
|
||||
private $deprecatedOptions = array();
|
||||
|
||||
public function setOptions(array $options) {
|
||||
$this->options = $options;
|
||||
|
@ -14,6 +15,15 @@ final class PhabricatorSearchCheckboxesField
|
|||
return $this->options;
|
||||
}
|
||||
|
||||
public function setDeprecatedOptions(array $deprecated_options) {
|
||||
$this->deprecatedOptions = $deprecated_options;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDeprecatedOptions() {
|
||||
return $this->deprecatedOptions;
|
||||
}
|
||||
|
||||
protected function getDefaultValue() {
|
||||
return array();
|
||||
}
|
||||
|
@ -23,11 +33,12 @@ final class PhabricatorSearchCheckboxesField
|
|||
return array();
|
||||
}
|
||||
|
||||
return $value;
|
||||
return $this->getCanonicalValue($value);
|
||||
}
|
||||
|
||||
protected function getValueFromRequest(AphrontRequest $request, $key) {
|
||||
return $this->getListFromRequest($request, $key);
|
||||
$value = $this->getListFromRequest($request, $key);
|
||||
return $this->getCanonicalValue($value);
|
||||
}
|
||||
|
||||
protected function newControl() {
|
||||
|
@ -58,7 +69,29 @@ final class PhabricatorSearchCheckboxesField
|
|||
->setValue($option);
|
||||
}
|
||||
|
||||
foreach ($this->getDeprecatedOptions() as $key => $value) {
|
||||
$list[] = id(new ConduitConstantDescription())
|
||||
->setKey($key)
|
||||
->setIsDeprecated(true)
|
||||
->setValue(pht('Deprecated alias for "%s".', $value));
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
private function getCanonicalValue(array $values) {
|
||||
// Always map the current normal options to themselves.
|
||||
$normal_options = array_fuse(array_keys($this->getOptions()));
|
||||
|
||||
// Map deprecated values to their new values.
|
||||
$deprecated_options = $this->getDeprecatedOptions();
|
||||
|
||||
$map = $normal_options + $deprecated_options;
|
||||
foreach ($values as $key => $value) {
|
||||
$values[$key] = idx($map, $value, $value);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -850,6 +850,10 @@ abstract class PhabricatorApplicationTransactionEditor
|
|||
$xaction->setIsSilentTransaction(true);
|
||||
}
|
||||
|
||||
if ($actor->hasHighSecuritySession()) {
|
||||
$xaction->setIsMFATransaction(true);
|
||||
}
|
||||
|
||||
return $xaction;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,15 @@ final class PhabricatorApplicationTransactionResponse
|
|||
$xactions[$key] = hsprintf('%s', $xaction);
|
||||
}
|
||||
|
||||
$aural = phutil_tag(
|
||||
'h3',
|
||||
array(
|
||||
'class' => 'aural-only',
|
||||
),
|
||||
pht('Comment Preview'));
|
||||
|
||||
$content = array(
|
||||
'header' => hsprintf('%s', $aural),
|
||||
'xactions' => $xactions,
|
||||
'spacer' => PHUITimelineView::renderSpacer(),
|
||||
'previewContent' => hsprintf('%s', $this->getPreviewContent()),
|
||||
|
|
|
@ -165,6 +165,14 @@ abstract class PhabricatorApplicationTransaction
|
|||
return (bool)$this->getMetadataValue('core.silent', false);
|
||||
}
|
||||
|
||||
public function setIsMFATransaction($mfa) {
|
||||
return $this->setMetadataValue('core.mfa', $mfa);
|
||||
}
|
||||
|
||||
public function getIsMFATransaction() {
|
||||
return (bool)$this->getMetadataValue('core.mfa', false);
|
||||
}
|
||||
|
||||
public function attachComment(
|
||||
PhabricatorApplicationTransactionComment $comment) {
|
||||
$this->comment = $comment;
|
||||
|
@ -1461,6 +1469,12 @@ abstract class PhabricatorApplicationTransaction
|
|||
if ($is_silent != $xaction->getIsSilentTransaction()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't group MFA and non-MFA transactions together.
|
||||
$is_mfa = $this->getIsMFATransaction();
|
||||
if ($is_mfa != $xaction->getIsMFATransaction()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -243,8 +243,16 @@ class PhabricatorApplicationTransactionCommentView extends AphrontView {
|
|||
|
||||
$comment_box = id(new PHUIObjectBoxView())
|
||||
->setFlush(true)
|
||||
->setNoBorder(true)
|
||||
->addClass('phui-comment-form-view')
|
||||
->addSigil('phui-comment-form')
|
||||
->appendChild(
|
||||
phutil_tag(
|
||||
'h3',
|
||||
array(
|
||||
'class' => 'aural-only',
|
||||
),
|
||||
pht('Add Comment')))
|
||||
->appendChild($image)
|
||||
->appendChild($badge_view)
|
||||
->appendChild($wedge)
|
||||
|
|
|
@ -424,7 +424,8 @@ class PhabricatorApplicationTransactionView extends AphrontView {
|
|||
->setIcon($xaction->getIcon())
|
||||
->setColor($xaction->getColor())
|
||||
->setHideCommentOptions($this->getHideCommentOptions())
|
||||
->setIsSilent($xaction->getIsSilentTransaction());
|
||||
->setIsSilent($xaction->getIsSilentTransaction())
|
||||
->setIsMFA($xaction->getIsMFATransaction());
|
||||
|
||||
list($token, $token_removed) = $xaction->getToken();
|
||||
if ($token) {
|
||||
|
|
|
@ -6,5 +6,78 @@ Construct a detailed written history of your civilization.
|
|||
Overview
|
||||
========
|
||||
|
||||
Phriction is a simple wiki. You can edit pages, and the text you write will stay
|
||||
Phriction is a wiki. You can edit pages, and the text you write will stay
|
||||
there. Other people can see it later.
|
||||
|
||||
Phriction documents are arranged in a hierarchy, like a filesystem. This can
|
||||
make it easier to keep things organized and to apply policy controls to
|
||||
groups of documents.
|
||||
|
||||
|
||||
Policies
|
||||
========
|
||||
|
||||
Documents and policies in Phriction are hierarchical, similar to a filesystem.
|
||||
For example, a document called "Zebra Information" may be located
|
||||
at `/zoo/animals/zebra/`.
|
||||
|
||||
To view a document in Phrction, you must first be able to view all of its
|
||||
ancestors. So a user can only see {nav Zoo > Animals > Zebra Information} if
|
||||
they can see the pages {nav Zoo} and {nav Zoo > Animals}.
|
||||
|
||||
This allows sections of the wiki to be restricted by applying a restrictive
|
||||
policy to the parent (or grandparent) document. For example, if you apply a
|
||||
restrictive view policy to the {nav Zoo} page, it will implicitly apply to
|
||||
all sub-pages, including {nav Zoo > Animals > Zebra Information}.
|
||||
|
||||
|
||||
Versions and Drafts
|
||||
===================
|
||||
|
||||
Document content is tracked with linear version numbers: version 1, version 2,
|
||||
version 3, and so on. Each time a page is edited, a new version of the page is
|
||||
created.
|
||||
|
||||
You can {nav View History} to review older versions of a page and see how it
|
||||
has changed over time (and who has changed it).
|
||||
|
||||
When you visit a particular document, you are normally shown the most recent
|
||||
version of that document. For example, if there are 17 versions, you'll see
|
||||
version 17.
|
||||
|
||||
Likewise, when you edit a document using {nav Edit Document > Save and Publish},
|
||||
your changes are published immediately. If there were previously 17 versions,
|
||||
your new changes will become version 18 and visitors to the document will begin
|
||||
seeing version 18.
|
||||
|
||||
If you want to edit a document without publishing the changes right away, you
|
||||
can use {nav Edit Document > Save as Draft} instead. This will still create a
|
||||
new version 18, but it won't change which version users see when they visit the
|
||||
document: they'll still see version 17 (the last published version).
|
||||
|
||||
You (and other users) can continue editing the draft by using
|
||||
{nav Edit Document}. (Once a document has an unpublished draft, editing will
|
||||
stay in draft mode.)
|
||||
|
||||
Once you're satisfied with your changes, use {nav Publish Draft} to make your
|
||||
changes the current visible version of the document that users see by default
|
||||
when they visit it.
|
||||
|
||||
If you made a mistake and published something you didn't intend to, you can
|
||||
navigate back to an older version of the document and use
|
||||
{nav Publish Older Version} to change the current visible version of the
|
||||
document to some older version.
|
||||
|
||||
Note that draft versions are still normal versions of the document: they are
|
||||
not private, they can not be deleted, other users can see them if they can see
|
||||
the document, and they will eventually become a standard part of the document
|
||||
history. The only private parts of drafts are: editing a draft does not
|
||||
generate a feed story; and users won't see draft content by default when
|
||||
viewing a document.
|
||||
|
||||
Drafts may be a good fit if you are:
|
||||
|
||||
- working on changes over time; or
|
||||
- starting with a rough change and refining it in several iterations; or
|
||||
- collaborating with others on a change; or
|
||||
- sharing changes before they're published to get feedback.
|
||||
|
|
|
@ -233,14 +233,15 @@ final class PHUIButtonView extends AphrontTagView {
|
|||
$classes = array();
|
||||
}
|
||||
|
||||
// See PHI823. If we aren't rendering a "<button>" tag, give the tag we
|
||||
// are rendering a "button" role as a hint to screen readers.
|
||||
// See PHI823. If we aren't rendering a "<button>" or "<input>" tag,
|
||||
// give the tag we are rendering a "button" role as a hint to screen
|
||||
// readers.
|
||||
$role = null;
|
||||
if ($this->tag !== 'button') {
|
||||
if ($this->tag !== 'button' && $this->tag !== 'input') {
|
||||
$role = 'button';
|
||||
}
|
||||
|
||||
return array(
|
||||
$attrs = array(
|
||||
'class' => $classes,
|
||||
'href' => $this->href,
|
||||
'name' => $this->name,
|
||||
|
@ -249,9 +250,19 @@ final class PHUIButtonView extends AphrontTagView {
|
|||
'meta' => $meta,
|
||||
'role' => $role,
|
||||
);
|
||||
|
||||
if ($this->tag == 'input') {
|
||||
$attrs['type'] = 'submit';
|
||||
$attrs['value'] = $this->text;
|
||||
}
|
||||
|
||||
return $attrs;
|
||||
}
|
||||
|
||||
protected function getTagContent() {
|
||||
if ($this->tag === 'input') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$icon = $this->icon;
|
||||
$text = null;
|
||||
|
|
|
@ -25,6 +25,7 @@ final class PHUIObjectBoxView extends AphrontTagView {
|
|||
private $showHideHref;
|
||||
private $showHideContent;
|
||||
private $showHideOpen;
|
||||
private $noBorder;
|
||||
|
||||
private $propertyLists = array();
|
||||
|
||||
|
@ -147,6 +148,11 @@ final class PHUIObjectBoxView extends AphrontTagView {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setNoBorder($no_border) {
|
||||
$this->noBorder = $no_border;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setValidationException(
|
||||
PhabricatorApplicationTransactionValidationException $ex = null) {
|
||||
$this->validationException = $ex;
|
||||
|
@ -156,7 +162,9 @@ final class PHUIObjectBoxView extends AphrontTagView {
|
|||
protected function getTagAttributes() {
|
||||
$classes = array();
|
||||
$classes[] = 'phui-box';
|
||||
$classes[] = 'phui-box-border';
|
||||
if (!$this->noBorder) {
|
||||
$classes[] = 'phui-box-border';
|
||||
}
|
||||
$classes[] = 'phui-object-box';
|
||||
$classes[] = 'mlt mll mlr';
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ final class PHUITimelineEventView extends AphrontView {
|
|||
private $badges = array();
|
||||
private $pinboardItems = array();
|
||||
private $isSilent;
|
||||
private $isMFA;
|
||||
|
||||
public function setAuthorPHID($author_phid) {
|
||||
$this->authorPHID = $author_phid;
|
||||
|
@ -187,6 +188,15 @@ final class PHUITimelineEventView extends AphrontView {
|
|||
return $this->isSilent;
|
||||
}
|
||||
|
||||
public function setIsMFA($is_mfa) {
|
||||
$this->isMFA = $is_mfa;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsMFA() {
|
||||
return $this->isMFA;
|
||||
}
|
||||
|
||||
public function setReallyMajorEvent($me) {
|
||||
$this->reallyMajorEvent = $me;
|
||||
return $this;
|
||||
|
@ -590,6 +600,14 @@ final class PHUITimelineEventView extends AphrontView {
|
|||
->setIcon('fa-bell-slash', 'red')
|
||||
->setTooltip(pht('Silent Edit'));
|
||||
}
|
||||
|
||||
// If this edit was applied while the actor was in high-security mode,
|
||||
// provide a hint that it was extra authentic.
|
||||
if ($this->getIsMFA()) {
|
||||
$extra[] = id(new PHUIIconView())
|
||||
->setIcon('fa-vcard', 'green')
|
||||
->setTooltip(pht('MFA Authenticated'));
|
||||
}
|
||||
}
|
||||
|
||||
$extra = javelin_tag(
|
||||
|
|
|
@ -83,7 +83,15 @@ final class PHUITimelineView extends AphrontView {
|
|||
'class' => 'phui-timeline-view',
|
||||
'id' => $this->id,
|
||||
),
|
||||
$events);
|
||||
array(
|
||||
phutil_tag(
|
||||
'h3',
|
||||
array(
|
||||
'class' => 'aural-only',
|
||||
),
|
||||
pht('Event Timeline')),
|
||||
$events,
|
||||
));
|
||||
}
|
||||
|
||||
public function buildEvents() {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
|
||||
button,
|
||||
a.button {
|
||||
a.button,
|
||||
input[type="submit"] {
|
||||
font: {$basefont};
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-user-select: none;
|
||||
|
@ -72,7 +73,8 @@ a.icon:visited {
|
|||
|
||||
button.button-green,
|
||||
a.button-green.button,
|
||||
a.button-green.button:visited {
|
||||
a.button-green.button:visited,
|
||||
input[type="submit"].button-green {
|
||||
background-color: {$green.button.color};
|
||||
border-color: {$green.button.color};
|
||||
background-image: {$green.button.gradient};
|
||||
|
@ -80,16 +82,17 @@ a.button-green.button:visited {
|
|||
|
||||
button.button-red,
|
||||
a.button-red.button,
|
||||
a.button-red.button:visited {
|
||||
a.button-red.button:visited,
|
||||
input[type="submit"].button-red {
|
||||
background-color: {$red.button.color};
|
||||
border-color: {$red.button.color};
|
||||
background-image: {$red.button.gradient};
|
||||
}
|
||||
|
||||
button.button-grey,
|
||||
input[type="submit"].button-grey,
|
||||
a.button-grey,
|
||||
a.button-grey:visited {
|
||||
a.button-grey:visited,
|
||||
input[type="submit"].button-grey {
|
||||
background-color: {$grey.button.color};
|
||||
background-image: {$grey.button.gradient};
|
||||
border: 1px solid rgba({$alphablue}, 0.3);
|
||||
|
|
|
@ -241,10 +241,13 @@ body.printable {
|
|||
}
|
||||
}
|
||||
|
||||
.phui-document-view-pro-box {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.phui-document-view-pro-box .phui-timeline-view {
|
||||
padding: 16px 0 0 0;
|
||||
background: none;
|
||||
border-top: 1px solid rgba({$alphablue}, 0.20);
|
||||
}
|
||||
|
||||
.phui-document-view-pro-box .phui-timeline-wedge {
|
||||
|
|
|
@ -133,19 +133,12 @@
|
|||
}
|
||||
|
||||
.aphront-form-control-submit button,
|
||||
.aphront-form-control-submit a.button {
|
||||
.aphront-form-control-submit a.button,
|
||||
.aphront-form-control-submit input[type="submit"] {
|
||||
float: right;
|
||||
margin: 4px 0 0 8px;
|
||||
}
|
||||
|
||||
.phui-form-control-multi-submit input,
|
||||
.phui-form-control-multi-submit button,
|
||||
.phui-form-control-multi-submit a {
|
||||
float: right;
|
||||
margin: 4px 0 0 8px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.aphront-form-control-textarea textarea.aphront-textarea-very-short {
|
||||
height: 44px;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ JX.behavior('comment-actions', function(config) {
|
|||
JX.DOM.setContent(
|
||||
preview_root,
|
||||
[
|
||||
JX.$H(response.header),
|
||||
JX.$H(response.xactions.join('')),
|
||||
JX.$H(response.previewContent)
|
||||
]);
|
||||
|
|
Loading…
Reference in a new issue