Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14834491
D21837.id52048.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
26 KB
Referenced Files
None
Subscribers
None
D21837.id52048.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -9,7 +9,7 @@
'names' => array(
'conpherence.pkg.css' => '0e3cf785',
'conpherence.pkg.js' => '020aebcf',
- 'core.pkg.css' => '00a2e7f4',
+ 'core.pkg.css' => 'b816811e',
'core.pkg.js' => 'd2de90d9',
'dark-console.pkg.js' => '187792c2',
'differential.pkg.css' => 'ffb69e3d',
@@ -147,7 +147,7 @@
'rsrc/css/phui/phui-comment-form.css' => '68a2d99a',
'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0',
'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf',
- 'rsrc/css/phui/phui-curtain-object-ref-view.css' => '5f752bdb',
+ 'rsrc/css/phui/phui-curtain-object-ref-view.css' => '51d93266',
'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6',
'rsrc/css/phui/phui-document-pro.css' => 'b9613a10',
'rsrc/css/phui/phui-document-summary.css' => 'b068eed1',
@@ -838,7 +838,7 @@
'phui-comment-form-css' => '68a2d99a',
'phui-comment-panel-css' => 'ec4e31c0',
'phui-crumbs-view-css' => '614f43cf',
- 'phui-curtain-object-ref-view-css' => '5f752bdb',
+ 'phui-curtain-object-ref-view-css' => '51d93266',
'phui-curtain-view-css' => '68c5efb6',
'phui-document-summary-view-css' => 'b068eed1',
'phui-document-view-css' => '52b748a5',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3508,6 +3508,7 @@
'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php',
'PhabricatorFileTransformListController' => 'applications/files/controller/PhabricatorFileTransformListController.php',
'PhabricatorFileTransformTestCase' => 'applications/files/transform/__tests__/PhabricatorFileTransformTestCase.php',
+ 'PhabricatorFileUICurtainAttachController' => 'applications/files/controller/PhabricatorFileUICurtainAttachController.php',
'PhabricatorFileUICurtainListController' => 'applications/files/controller/PhabricatorFileUICurtainListController.php',
'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php',
'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php',
@@ -9972,6 +9973,7 @@
'PhabricatorFileTransformController' => 'PhabricatorFileController',
'PhabricatorFileTransformListController' => 'PhabricatorFileController',
'PhabricatorFileTransformTestCase' => 'PhabricatorTestCase',
+ 'PhabricatorFileUICurtainAttachController' => 'PhabricatorFileController',
'PhabricatorFileUICurtainListController' => 'PhabricatorFileController',
'PhabricatorFileUploadController' => 'PhabricatorFileController',
'PhabricatorFileUploadDialogController' => 'PhabricatorFileController',
diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php
--- a/src/applications/base/controller/PhabricatorController.php
+++ b/src/applications/base/controller/PhabricatorController.php
@@ -420,6 +420,10 @@
->setSubmitURI($submit_uri);
}
+ public function newRedirect() {
+ return id(new AphrontRedirectResponse());
+ }
+
public function newPage() {
$page = id(new PhabricatorStandardPageView())
->setRequest($this->getRequest())
diff --git a/src/applications/files/application/PhabricatorFilesApplication.php b/src/applications/files/application/PhabricatorFilesApplication.php
--- a/src/applications/files/application/PhabricatorFilesApplication.php
+++ b/src/applications/files/application/PhabricatorFilesApplication.php
@@ -95,8 +95,14 @@
),
'document/(?P<engineKey>[^/]+)/(?P<phid>[^/]+)/'
=> 'PhabricatorFileDocumentController',
- 'ui/curtainlist/(?P<phid>[^/]+)/'
- => 'PhabricatorFileUICurtainListController',
+ 'ui/' => array(
+ 'curtain/' => array(
+ 'list/(?P<phid>[^/]+)/'
+ => 'PhabricatorFileUICurtainListController',
+ 'attach/(?P<objectPHID>[^/]+)/(?P<filePHID>[^/]+)/'
+ => 'PhabricatorFileUICurtainAttachController',
+ ),
+ ),
) + $this->getResourceSubroutes(),
);
}
diff --git a/src/applications/files/controller/PhabricatorFileUICurtainAttachController.php b/src/applications/files/controller/PhabricatorFileUICurtainAttachController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/controller/PhabricatorFileUICurtainAttachController.php
@@ -0,0 +1,136 @@
+<?php
+
+final class PhabricatorFileUICurtainAttachController
+ extends PhabricatorFileController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ $object_phid = $request->getURIData('objectPHID');
+ $file_phid = $request->getURIData('filePHID');
+
+ $object = id(new PhabricatorObjectQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($object_phid))
+ ->executeOne();
+ if (!$object) {
+ return new Aphront404Response();
+ }
+
+ $attachment = id(new PhabricatorFileAttachmentQuery())
+ ->setViewer($viewer)
+ ->withObjectPHIDs(array($object->getPHID()))
+ ->withFilePHIDs(array($file_phid))
+ ->needFiles(true)
+ ->withVisibleFiles(true)
+ ->executeOne();
+ if (!$attachment) {
+ return new Aphront404Response();
+ }
+
+ $file = $attachment->getFile();
+ $file_phid = $file->getPHID();
+
+ $handles = $viewer->loadHandles(
+ array(
+ $object_phid,
+ $file_phid,
+ ));
+
+ $object_handle = $handles[$object_phid];
+ $file_handle = $handles[$file_phid];
+ $cancel_uri = $object_handle->getURI();
+
+ $dialog = $this->newDialog()
+ ->setViewer($viewer)
+ ->setTitle(pht('Attach File'))
+ ->addCancelButton($object_handle->getURI(), pht('Close'));
+
+ $file_link = phutil_tag('strong', array(), $file_handle->renderLink());
+ $object_link = phutil_tag('strong', array(), $object_handle->renderLink());
+
+ if ($attachment->isPolicyAttachment()) {
+ $body = pht(
+ 'The file %s is already attached to the object %s.',
+ $file_link,
+ $object_link);
+
+ return $dialog->appendParagraph($body);
+ }
+
+ if (!$request->isDialogFormPost()) {
+ $dialog->appendRemarkup(
+ pht(
+ '(WARNING) This file is referenced by this object, but '.
+ 'not formally attached to it. Users who can see the object may '.
+ 'not be able to see the file.'));
+
+ $dialog->appendParagraph(
+ pht(
+ 'Do you want to attach the file %s to the object %s?',
+ $file_link,
+ $object_link));
+
+ $dialog->addSubmitButton(pht('Attach File'));
+
+ return $dialog;
+ }
+
+ if (!$request->getBool('confirm')) {
+ $dialog->setTitle(pht('Confirm File Attachment'));
+
+ $dialog->addHiddenInput('confirm', 1);
+
+ $dialog->appendRemarkup(
+ pht(
+ '(IMPORTANT) If you attach this file to this object, any user who '.
+ 'has permission to view the object will be able to view and '.
+ 'download the file!'));
+
+ $dialog->appendParagraph(
+ pht(
+ 'Really attach the file %s to the object %s, allowing any user '.
+ 'who can view the object to view and download the file?',
+ $file_link,
+ $object_link));
+
+ $dialog->addSubmitButton(pht('Grant Permission'));
+
+ return $dialog;
+ }
+
+ if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
+ $dialog->appendParagraph(
+ pht(
+ 'This object (of class "%s") does not implement the required '.
+ 'interface ("%s"), so files can not be manually attached to it.',
+ get_class($object),
+ 'PhabricatorApplicationTransactionInterface'));
+
+ return $dialog;
+ }
+
+ $editor = $object->getApplicationTransactionEditor()
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true)
+ ->setContinueOnMissingFields(true);
+
+ $template = $object->getApplicationTransactionTemplate();
+
+ $xactions = array();
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType(PhabricatorTransactions::TYPE_FILE)
+ ->setNewValue(
+ array(
+ $file_phid => PhabricatorFileAttachment::MODE_ATTACH,
+ ));
+
+ $editor->applyTransactions($object, $xactions);
+
+ return $this->newRedirect()
+ ->setURI($cancel_uri);
+ }
+
+}
diff --git a/src/applications/files/controller/PhabricatorFileUICurtainListController.php b/src/applications/files/controller/PhabricatorFileUICurtainListController.php
--- a/src/applications/files/controller/PhabricatorFileUICurtainListController.php
+++ b/src/applications/files/controller/PhabricatorFileUICurtainListController.php
@@ -53,7 +53,7 @@
return $this->newDialog()
->setViewer($viewer)
->setWidth(AphrontDialogView::WIDTH_FORM)
- ->setTitle(pht('Attached Files'))
+ ->setTitle(pht('Referenced Files'))
->setObjectList($list)
->addCancelButton($object_handle->getURI(), pht('Close'));
}
diff --git a/src/applications/files/engineextension/PhabricatorFilesCurtainExtension.php b/src/applications/files/engineextension/PhabricatorFilesCurtainExtension.php
--- a/src/applications/files/engineextension/PhabricatorFilesCurtainExtension.php
+++ b/src/applications/files/engineextension/PhabricatorFilesCurtainExtension.php
@@ -34,15 +34,16 @@
$handles = $viewer->loadHandles($visible_phids);
- PhabricatorPolicyFilterSet::loadHandleViewCapabilities(
- $viewer,
- $handles,
- array($object));
-
$ref_list = id(new PHUICurtainObjectRefListView())
->setViewer($viewer)
->setEmptyMessage(pht('None'));
+ $view_capability = PhabricatorPolicyCapability::CAN_VIEW;
+ $object_policies = PhabricatorPolicyQuery::loadPolicies(
+ $viewer,
+ $object);
+ $object_policy = idx($object_policies, $view_capability);
+
foreach ($visible_attachments as $attachment) {
$file_phid = $attachment->getFilePHID();
$handle = $handles[$file_phid];
@@ -50,9 +51,38 @@
$ref = $ref_list->newObjectRefView()
->setHandle($handle);
- if ($handle->hasCapabilities()) {
- if (!$handle->hasViewCapability($object)) {
- $ref->setExiled(true);
+ $file = $attachment->getFile();
+ if (!$file) {
+ // ...
+ } else {
+ if (!$attachment->isPolicyAttachment()) {
+ $file_policies = PhabricatorPolicyQuery::loadPolicies(
+ $viewer,
+ $file);
+ $file_policy = idx($file_policies, $view_capability);
+
+ if ($object_policy->isStrongerThanOrEqualTo($file_policy)) {
+ // The file is not attached to the object, but the file policy
+ // allows anyone who can see the object to see the file too, so
+ // there is no material problem with the file not being attached.
+ } else {
+ $attach_uri = urisprintf(
+ '/file/ui/curtain/attach/%s/%s/',
+ $object->getPHID(),
+ $file->getPHID());
+
+ $attached_link = javelin_tag(
+ 'a',
+ array(
+ 'href' => $attach_uri,
+ 'sigil' => 'workflow',
+ ),
+ pht('File Not Attached'));
+
+ $ref->setExiled(
+ true,
+ $attached_link);
+ }
}
}
@@ -63,7 +93,7 @@
$show_all = (count($visible_attachments) < count($attachments));
if ($show_all) {
$view_all_uri = urisprintf(
- '/file/ui/curtainlist/%s/',
+ '/file/ui/curtain/list/%s/',
$object->getPHID());
$loaded_count = count($attachments);
@@ -80,7 +110,7 @@
}
return $this->newPanel()
- ->setHeaderText(pht('Attached Files'))
+ ->setHeaderText(pht('Referenced Files'))
->setOrder(15000)
->appendChild($ref_list);
}
diff --git a/src/applications/files/phid/PhabricatorFileFilePHIDType.php b/src/applications/files/phid/PhabricatorFileFilePHIDType.php
--- a/src/applications/files/phid/PhabricatorFileFilePHIDType.php
+++ b/src/applications/files/phid/PhabricatorFileFilePHIDType.php
@@ -39,6 +39,9 @@
$handle->setName("F{$id}");
$handle->setFullName("F{$id}: {$name}");
$handle->setURI($uri);
+
+ $icon = FileTypeIcon::getFileIcon($name);
+ $handle->setIcon($icon);
}
}
diff --git a/src/applications/files/query/PhabricatorFileAttachmentQuery.php b/src/applications/files/query/PhabricatorFileAttachmentQuery.php
--- a/src/applications/files/query/PhabricatorFileAttachmentQuery.php
+++ b/src/applications/files/query/PhabricatorFileAttachmentQuery.php
@@ -4,13 +4,25 @@
extends PhabricatorCursorPagedPolicyAwareQuery {
private $objectPHIDs;
+ private $filePHIDs;
private $needFiles;
+ private $visibleFiles;
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
+ public function withFilePHIDs(array $file_phids) {
+ $this->filePHIDs = $file_phids;
+ return $this;
+ }
+
+ public function withVisibleFiles($visible_files) {
+ $this->visibleFiles = $visible_files;
+ return $this;
+ }
+
public function needFiles($need) {
$this->needFiles = $need;
return $this;
@@ -34,6 +46,13 @@
$this->objectPHIDs);
}
+ if ($this->filePHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'attachments.filePHID IN (%Ls)',
+ $this->filePHIDs);
+ }
+
return $where;
}
@@ -92,6 +111,12 @@
$file_phid = $attachment->getFilePHID();
$file = idx($files, $file_phid);
+ if ($this->visibleFiles && !$file) {
+ $this->didRejectResult($attachment);
+ unset($attachments[$key]);
+ continue;
+ }
+
$attachment->attachFile($file);
}
}
diff --git a/src/applications/files/storage/PhabricatorFileAttachment.php b/src/applications/files/storage/PhabricatorFileAttachment.php
--- a/src/applications/files/storage/PhabricatorFileAttachment.php
+++ b/src/applications/files/storage/PhabricatorFileAttachment.php
@@ -46,6 +46,15 @@
);
}
+ public function isPolicyAttachment() {
+ switch ($this->getAttachmentMode()) {
+ case self::MODE_ATTACH:
+ return true;
+ default:
+ return false;
+ }
+ }
+
public function attachObject($object) {
$this->object = $object;
return $this;
diff --git a/src/applications/policy/storage/PhabricatorPolicy.php b/src/applications/policy/storage/PhabricatorPolicy.php
--- a/src/applications/policy/storage/PhabricatorPolicy.php
+++ b/src/applications/policy/storage/PhabricatorPolicy.php
@@ -417,12 +417,23 @@
PhabricatorPolicies::POLICY_NOONE => 1,
);
- $this_strength = idx($strengths, $this->getPHID(), 0);
- $other_strength = idx($strengths, $other->getPHID(), 0);
+ $this_strength = idx($strengths, $this_policy, 0);
+ $other_strength = idx($strengths, $other_policy, 0);
return ($this_strength > $other_strength);
}
+ public function isStrongerThanOrEqualTo(PhabricatorPolicy $other) {
+ $this_policy = $this->getPHID();
+ $other_policy = $other->getPHID();
+
+ if ($this_policy === $other_policy) {
+ return true;
+ }
+
+ return $this->isStrongerThan($other);
+ }
+
public function isValidPolicyForEdit() {
return $this->getType() !== PhabricatorPolicyType::TYPE_MASKED;
}
diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
--- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
+++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
@@ -2321,6 +2321,7 @@
$xaction = $object->getApplicationTransactionTemplate()
->setTransactionType(PhabricatorTransactions::TYPE_FILE)
+ ->setMetadataValue('attach.implicit', true)
->setNewValue($new_map);
return $xaction;
diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
--- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
+++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
@@ -341,6 +341,9 @@
$phids[] = $old;
$phids[] = $new;
break;
+ case PhabricatorTransactions::TYPE_FILE:
+ $phids[] = array_keys($old + $new);
+ break;
case PhabricatorTransactions::TYPE_EDGE:
$record = PhabricatorEdgeChangeRecord::newFromTransaction($this);
$phids[] = $record->getChangedPHIDs();
@@ -592,7 +595,9 @@
// Always hide file attach/detach transactions.
if ($xaction_type === PhabricatorTransactions::TYPE_FILE) {
- return true;
+ if ($this->getMetadataValue('attach.implicit')) {
+ return true;
+ }
}
// Hide creation transactions if the old value is empty. These are
@@ -1041,6 +1046,124 @@
'%s updated subscribers...',
$this->renderHandleLink($author_phid));
}
+ break;
+ case PhabricatorTransactions::TYPE_FILE:
+ $add = array_diff_key($new, $old);
+ $add = array_keys($add);
+
+ $rem = array_diff_key($old, $new);
+ $rem = array_keys($rem);
+
+ $mod = array();
+ foreach ($old + $new as $key => $ignored) {
+ if (!isset($old[$key])) {
+ continue;
+ }
+
+ if (!isset($new[$key])) {
+ continue;
+ }
+
+ if ($old[$key] === $new[$key]) {
+ continue;
+ }
+
+ $mod[] = $key;
+ }
+
+ // Specialize the specific case of only modifying files and upgrading
+ // references to attachments. This is accessible via the UI and can
+ // be shown more clearly than the generic default transaction shows
+ // it.
+
+ $mode_reference = PhabricatorFileAttachment::MODE_REFERENCE;
+ $mode_attach = PhabricatorFileAttachment::MODE_ATTACH;
+
+ $is_refattach = false;
+ if ($mod && !$add && !$rem) {
+ $all_refattach = true;
+ foreach ($mod as $phid) {
+ if (idx($old, $phid) !== $mode_reference) {
+ $all_refattach = false;
+ break;
+ }
+ if (idx($new, $phid) !== $mode_attach) {
+ $all_refattach = false;
+ break;
+ }
+ }
+ $is_refattach = $all_refattach;
+ }
+
+ if ($is_refattach) {
+ return pht(
+ '%s attached %s referenced file(s): %s.',
+ $this->renderHandleLink($author_phid),
+ phutil_count($mod),
+ $this->renderHandleList($mod));
+ } else if ($add && $rem && $mod) {
+ return pht(
+ '%s updated %s attached file(s), added %s: %s; removed %s: %s; '.
+ 'modified %s: %s.',
+ $this->renderHandleLink($author_phid),
+ new PhutilNumber(count($add) + count($rem)),
+ phutil_count($add),
+ $this->renderHandleList($add),
+ phutil_count($rem),
+ $this->renderHandleList($rem),
+ phutil_count($mod),
+ $this->renderHandleList($mod));
+ } else if ($add && $rem) {
+ return pht(
+ '%s updated %s attached file(s), added %s: %s; removed %s: %s.',
+ $this->renderHandleLink($author_phid),
+ new PhutilNumber(count($add) + count($rem)),
+ phutil_count($add),
+ $this->renderHandleList($add),
+ phutil_count($rem),
+ $this->renderHandleList($rem));
+ } else if ($add && $mod) {
+ return pht(
+ '%s updated %s attached file(s), added %s: %s; modified %s: %s.',
+ $this->renderHandleLink($author_phid),
+ new PhutilNumber(count($add) + count($mod)),
+ phutil_count($add),
+ $this->renderHandleList($add),
+ phutil_count($mod),
+ $this->renderHandleList($mod));
+ } else if ($rem && $mod) {
+ return pht(
+ '%s updated %s attached file(s), removed %s: %s; modified %s: %s.',
+ $this->renderHandleLink($author_phid),
+ new PhutilNumber(count($rem) + count($mod)),
+ phutil_count($rem),
+ $this->renderHandleList($rem),
+ phutil_count($mod),
+ $this->renderHandleList($mod));
+ } else if ($add) {
+ return pht(
+ '%s attached %s file(s): %s.',
+ $this->renderHandleLink($author_phid),
+ phutil_count($add),
+ $this->renderHandleList($add));
+ } else if ($rem) {
+ return pht(
+ '%s removed %s attached file(s): %s.',
+ $this->renderHandleLink($author_phid),
+ phutil_count($rem),
+ $this->renderHandleList($rem));
+ } else if ($mod) {
+ return pht(
+ '%s modified %s attached file(s): %s.',
+ $this->renderHandleLink($author_phid),
+ phutil_count($mod),
+ $this->renderHandleList($mod));
+ } else {
+ return pht(
+ '%s attached files...',
+ $this->renderHandleLink($author_phid));
+ }
+
break;
case PhabricatorTransactions::TYPE_EDGE:
$record = PhabricatorEdgeChangeRecord::newFromTransaction($this);
@@ -1479,6 +1602,8 @@
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
+ case PhabricatorTransactions::TYPE_FILE:
+ return true;
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
$field = $this->getTransactionCustomField();
if ($field) {
@@ -1494,6 +1619,11 @@
}
public function renderChangeDetailsForMail(PhabricatorUser $viewer) {
+ switch ($this->getTransactionType()) {
+ case PhabricatorTransactions::TYPE_FILE:
+ return false;
+ }
+
$view = $this->renderChangeDetails($viewer);
if ($view instanceof PhabricatorApplicationTransactionTextDiffDetailView) {
return $view->renderForMail();
@@ -1503,6 +1633,8 @@
public function renderChangeDetails(PhabricatorUser $viewer) {
switch ($this->getTransactionType()) {
+ case PhabricatorTransactions::TYPE_FILE:
+ return $this->newFileTransactionChangeDetails($viewer);
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
$field = $this->getTransactionCustomField();
if ($field) {
@@ -1769,6 +1901,66 @@
->addInt(-$this->getActionStrength());
}
+ private function newFileTransactionChangeDetails(PhabricatorUser $viewer) {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $phids = array_keys($old + $new);
+ $handles = $viewer->loadHandles($phids);
+
+ $names = array(
+ PhabricatorFileAttachment::MODE_REFERENCE => pht('Referenced'),
+ PhabricatorFileAttachment::MODE_ATTACH => pht('Attached'),
+ );
+
+ $rows = array();
+ foreach ($old + $new as $phid => $ignored) {
+ $handle = $handles[$phid];
+
+ $old_mode = idx($old, $phid);
+ $new_mode = idx($new, $phid);
+
+ if ($old_mode === null) {
+ $old_name = pht('None');
+ } else if (isset($names[$old_mode])) {
+ $old_name = $names[$old_mode];
+ } else {
+ $old_name = pht('Unknown ("%s")', $old_mode);
+ }
+
+ if ($new_mode === null) {
+ $new_name = pht('Detached');
+ } else if (isset($names[$new_mode])) {
+ $new_name = $names[$new_mode];
+ } else {
+ $new_name = pht('Unknown ("%s")', $new_mode);
+ }
+
+ $rows[] = array(
+ $handle->renderLink(),
+ $old_name,
+ $new_name,
+ );
+ }
+
+ $table = id(new AphrontTableView($rows))
+ ->setHeaders(
+ array(
+ pht('File'),
+ pht('Old Mode'),
+ pht('New Mode'),
+ ))
+ ->setColumnClasses(
+ array(
+ 'pri',
+ ));
+
+ return id(new PHUIBoxView())
+ ->addMargin(PHUI::MARGIN_SMALL)
+ ->appendChild($table);
+ }
+
+
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
@@ -1836,5 +2028,4 @@
$this->saveTransaction();
}
-
}
diff --git a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
--- a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
+++ b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
@@ -1789,6 +1789,20 @@
'Executed %s tasks.',
),
+ '%s modified %s attached file(s): %s.' => array(
+ array(
+ '%s modified an attached file: %3$s.',
+ '%s modified attached files: %3$s.',
+ ),
+ ),
+
+ '%s attached %s referenced file(s): %s.' => array(
+ array(
+ '%s attached a referenced file: %3$s.',
+ '%s attached referenced files: %3$s.',
+ ),
+ ),
+
);
}
diff --git a/src/view/phui/PHUICurtainObjectRefView.php b/src/view/phui/PHUICurtainObjectRefView.php
--- a/src/view/phui/PHUICurtainObjectRefView.php
+++ b/src/view/phui/PHUICurtainObjectRefView.php
@@ -7,6 +7,7 @@
private $epoch;
private $highlighted;
private $exiled;
+ private $exileNote = false;
public function setHandle(PhabricatorObjectHandle $handle) {
$this->handle = $handle;
@@ -23,8 +24,9 @@
return $this;
}
- public function setExiled($is_exiled) {
+ public function setExiled($is_exiled, $note = false) {
$this->exiled = $is_exiled;
+ $this->exileNote = $note;
return $this;
}
@@ -72,10 +74,16 @@
}
if ($this->exiled) {
+ if ($this->exileNote !== false) {
+ $exile_note = $this->exileNote;
+ } else {
+ $exile_note = pht('No View Permission');
+ }
+
$exiled_view = array(
id(new PHUIIconView())->setIcon('fa-eye-slash red'),
' ',
- pht('No View Permission'),
+ $exile_note,
);
$exiled_cells = array();
diff --git a/webroot/rsrc/css/phui/phui-curtain-object-ref-view.css b/webroot/rsrc/css/phui/phui-curtain-object-ref-view.css
--- a/webroot/rsrc/css/phui/phui-curtain-object-ref-view.css
+++ b/webroot/rsrc/css/phui/phui-curtain-object-ref-view.css
@@ -92,6 +92,7 @@
opacity: 0.75;
}
-.phui-curtain-object-ref-view-exiled-cell {
+.phui-curtain-object-ref-view-exiled-cell,
+.phui-curtain-object-ref-view-exiled-cell a {
color: {$red};
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 31, 3:36 PM (4 h, 41 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7078983
Default Alt Text
D21837.id52048.diff (26 KB)
Attached To
Mode
D21837: Provide a simple "Attach File" explicit workflow for files referenced but not attached
Attached
Detach File
Event Timeline
Log In to Comment