diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index cd67501ae6..211b4fa5e3 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3508,6 +3508,7 @@ phutil_register_library_map(array( 'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php', 'PhabricatorFileTransformListController' => 'applications/files/controller/PhabricatorFileTransformListController.php', 'PhabricatorFileTransformTestCase' => 'applications/files/transform/__tests__/PhabricatorFileTransformTestCase.php', + 'PhabricatorFileUICurtainListController' => 'applications/files/controller/PhabricatorFileUICurtainListController.php', 'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php', 'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php', 'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php', @@ -3521,6 +3522,7 @@ phutil_register_library_map(array( 'PhabricatorFilesComposeAvatarBuiltinFile' => 'applications/files/builtin/PhabricatorFilesComposeAvatarBuiltinFile.php', 'PhabricatorFilesComposeIconBuiltinFile' => 'applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php', 'PhabricatorFilesConfigOptions' => 'applications/files/config/PhabricatorFilesConfigOptions.php', + 'PhabricatorFilesCurtainExtension' => 'applications/files/engineextension/PhabricatorFilesCurtainExtension.php', 'PhabricatorFilesManagementCatWorkflow' => 'applications/files/management/PhabricatorFilesManagementCatWorkflow.php', 'PhabricatorFilesManagementCompactWorkflow' => 'applications/files/management/PhabricatorFilesManagementCompactWorkflow.php', 'PhabricatorFilesManagementCycleWorkflow' => 'applications/files/management/PhabricatorFilesManagementCycleWorkflow.php', @@ -9970,6 +9972,7 @@ phutil_register_library_map(array( 'PhabricatorFileTransformController' => 'PhabricatorFileController', 'PhabricatorFileTransformListController' => 'PhabricatorFileController', 'PhabricatorFileTransformTestCase' => 'PhabricatorTestCase', + 'PhabricatorFileUICurtainListController' => 'PhabricatorFileController', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileUploadDialogController' => 'PhabricatorFileController', 'PhabricatorFileUploadException' => 'Exception', @@ -9983,6 +9986,7 @@ phutil_register_library_map(array( 'PhabricatorFilesComposeAvatarBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesComposeIconBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions', + 'PhabricatorFilesCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorFilesManagementCatWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementCompactWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementCycleWorkflow' => 'PhabricatorFilesManagementWorkflow', diff --git a/src/applications/files/application/PhabricatorFilesApplication.php b/src/applications/files/application/PhabricatorFilesApplication.php index 2e4c48f0d6..14b29e57f6 100644 --- a/src/applications/files/application/PhabricatorFilesApplication.php +++ b/src/applications/files/application/PhabricatorFilesApplication.php @@ -95,6 +95,8 @@ final class PhabricatorFilesApplication extends PhabricatorApplication { ), 'document/(?P[^/]+)/(?P[^/]+)/' => 'PhabricatorFileDocumentController', + 'ui/curtainlist/(?P[^/]+)/' + => 'PhabricatorFileUICurtainListController', ) + $this->getResourceSubroutes(), ); } diff --git a/src/applications/files/controller/PhabricatorFileUICurtainListController.php b/src/applications/files/controller/PhabricatorFileUICurtainListController.php new file mode 100644 index 0000000000..25d6fd65ed --- /dev/null +++ b/src/applications/files/controller/PhabricatorFileUICurtainListController.php @@ -0,0 +1,61 @@ +getViewer(); + + $object_phid = $request->getURIData('phid'); + + $object = id(new PhabricatorObjectQuery()) + ->setViewer($viewer) + ->withPHIDs(array($object_phid)) + ->executeOne(); + if (!$object) { + return new Aphront404Response(); + } + + $attachments = id(new PhabricatorFileAttachmentQuery()) + ->setViewer($viewer) + ->withObjectPHIDs(array($object->getPHID())) + ->needFiles(true) + ->execute(); + + $handles = $viewer->loadHandles(array($object_phid)); + $object_handle = $handles[$object_phid]; + + $file_phids = mpull($attachments, 'getFilePHID'); + $file_handles = $viewer->loadHandles($file_phids); + + $list = id(new PHUIObjectItemListView()) + ->setUser($viewer); + foreach ($attachments as $attachment) { + $file_phid = $attachment->getFilePHID(); + $handle = $file_handles[$file_phid]; + + $item = id(new PHUIObjectItemView()) + ->setHeader($handle->getFullName()) + ->setHref($handle->getURI()) + ->setDisabled($handle->isDisabled()); + + if ($handle->getImageURI()) { + $item->setImageURI($handle->getImageURI()); + } + + $list->addItem($item); + } + + return $this->newDialog() + ->setViewer($viewer) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->setTitle(pht('Attached 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 new file mode 100644 index 0000000000..aefa5a93a2 --- /dev/null +++ b/src/applications/files/engineextension/PhabricatorFilesCurtainExtension.php @@ -0,0 +1,89 @@ +getViewer(); + + $attachment_table = new PhabricatorFileAttachment(); + $attachment_conn = $attachment_table->establishConnection('r'); + + $exact_limit = 100; + $visible_limit = 8; + + $attachments = id(new PhabricatorFileAttachmentQuery()) + ->setViewer($viewer) + ->withObjectPHIDs(array($object->getPHID())) + ->setLimit($exact_limit + 1) + ->needFiles(true) + ->execute(); + + $visible_attachments = array_slice($attachments, 0, $visible_limit, true); + $visible_phids = mpull($visible_attachments, 'getFilePHID'); + + $handles = $viewer->loadHandles($visible_phids); + + PhabricatorPolicyFilterSet::loadHandleViewCapabilities( + $viewer, + $handles, + array($object)); + + $ref_list = id(new PHUICurtainObjectRefListView()) + ->setViewer($viewer) + ->setEmptyMessage(pht('None')); + + foreach ($visible_attachments as $attachment) { + $file_phid = $attachment->getFilePHID(); + $handle = $handles[$file_phid]; + + $ref = $ref_list->newObjectRefView() + ->setHandle($handle); + + if ($handle->hasCapabilities()) { + if (!$handle->hasViewCapability($object)) { + $ref->setExiled(true); + } + } + + $epoch = $attachment->getDateCreated(); + $ref->setEpoch($epoch); + } + + $show_all = (count($visible_attachments) < count($attachments)); + if ($show_all) { + $view_all_uri = urisprintf( + '/file/ui/curtainlist/%s/', + $object->getPHID()); + + $loaded_count = count($attachments); + if ($loaded_count > $exact_limit) { + $link_text = pht('View All Files'); + } else { + $link_text = pht('View All %d Files', new PhutilNumber($loaded_count)); + } + + $ref_list->newTailLink() + ->setURI($view_all_uri) + ->setText($link_text) + ->setWorkflow(true); + } + + return $this->newPanel() + ->setHeaderText(pht('Attached Files')) + ->setOrder(15000) + ->appendChild($ref_list); + } + + +}