@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow users to search for signatures across documents

Summary:
Ref T3116. You can already search for sigatures on a specific document, but allow them to be searched across documents too.

In particular, this lets users answer questions like "Which of these 5 documents has alincoln signed?" / "Has alincoln signed all the stuff I care about?" / "who has signed either L5 or equivalent document L22?", etc.

Test Plan: {F171658}

Reviewers: chad

Reviewed By: chad

Subscribers: epriestley

Maniphest Tasks: T3116

Differential Revision: https://secure.phabricator.com/D9770

+99 -33
+2 -2
src/applications/legalpad/application/PhabricatorApplicationLegalpad.php
··· 49 49 'done/' => 'LegalpadDocumentDoneController', 50 50 'verify/(?P<code>[^/]+)/' => 51 51 'LegalpadDocumentSignatureVerificationController', 52 - 'signatures/(?P<id>\d+)/(?:query/(?P<queryKey>[^/]+)/)?' 53 - => 'LegalpadDocumentSignatureListController', 52 + 'signatures/(?:(?P<id>\d+)/)?(?:query/(?P<queryKey>[^/]+)/)?' => 53 + 'LegalpadDocumentSignatureListController', 54 54 'document/' => array( 55 55 'preview/' => 'PhabricatorMarkupPreviewController'), 56 56 ));
+3
src/applications/legalpad/controller/LegalpadController.php
··· 19 19 ->setViewer($user) 20 20 ->addNavigationItems($nav->getMenu()); 21 21 22 + $nav->addLabel(pht('Signatures')); 23 + $nav->addFilter('signatures/', pht('Find Signatures')); 24 + 22 25 return $nav; 23 26 } 24 27
+37 -22
src/applications/legalpad/controller/LegalpadDocumentSignatureListController.php
··· 7 7 private $document; 8 8 9 9 public function willProcessRequest(array $data) { 10 - $this->documentID = $data['id']; 10 + $this->documentID = idx($data, 'id'); 11 11 $this->queryKey = idx($data, 'queryKey'); 12 12 } 13 13 ··· 15 15 $request = $this->getRequest(); 16 16 $user = $request->getUser(); 17 17 18 - $document = id(new LegalpadDocumentQuery()) 19 - ->setViewer($user) 20 - ->withIDs(array($this->documentID)) 21 - ->requireCapabilities( 22 - array( 23 - PhabricatorPolicyCapability::CAN_VIEW, 24 - PhabricatorPolicyCapability::CAN_EDIT, 25 - )) 26 - ->executeOne(); 27 - if (!$document) { 28 - return new Aphront404Response(); 18 + if ($this->documentID) { 19 + $document = id(new LegalpadDocumentQuery()) 20 + ->setViewer($user) 21 + ->withIDs(array($this->documentID)) 22 + ->requireCapabilities( 23 + array( 24 + PhabricatorPolicyCapability::CAN_VIEW, 25 + PhabricatorPolicyCapability::CAN_EDIT, 26 + )) 27 + ->executeOne(); 28 + if (!$document) { 29 + return new Aphront404Response(); 30 + } 31 + 32 + $this->document = $document; 29 33 } 30 34 31 - $this->document = $document; 35 + $engine = id(new LegalpadDocumentSignatureSearchEngine()); 32 36 33 - $engine = id(new LegalpadDocumentSignatureSearchEngine()) 34 - ->setDocument($document); 37 + if ($this->document) { 38 + $engine->setDocument($this->document); 39 + } 35 40 36 41 $controller = id(new PhabricatorApplicationSearchController($request)) 37 42 ->setQueryKey($this->queryKey) ··· 47 52 $nav = new AphrontSideNavFilterView(); 48 53 $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 49 54 50 - id(new LegalpadDocumentSignatureSearchEngine()) 51 - ->setViewer($user) 52 - ->setDocument($this->document) 53 - ->addNavigationItems($nav->getMenu()); 55 + $engine = id(new LegalpadDocumentSignatureSearchEngine()) 56 + ->setViewer($user); 57 + 58 + if ($this->document) { 59 + $engine->setDocument($this->document); 60 + } 61 + 62 + $engine->addNavigationItems($nav->getMenu()); 54 63 55 64 return $nav; 56 65 } ··· 58 67 public function buildApplicationCrumbs() { 59 68 $crumbs = parent::buildApplicationCrumbs(); 60 69 61 - $crumbs->addTextCrumb( 62 - $this->document->getMonogram(), 63 - '/'.$this->document->getMonogram()); 70 + if ($this->document) { 71 + $crumbs->addTextCrumb( 72 + $this->document->getMonogram(), 73 + '/'.$this->document->getMonogram()); 74 + } else { 75 + $crumbs->addTextCrumb( 76 + pht('Signatures'), 77 + '/legalpad/signatures/'); 78 + } 64 79 65 80 return $crumbs; 66 81 }
+2 -2
src/applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php
··· 37 37 $document = $objects[$phid]; 38 38 $name = $document->getDocumentBody()->getTitle(); 39 39 $handle->setName($name); 40 - $handle->setFullName($name); 41 - $handle->setURI('/legalpad/view/'.$document->getID().'/'); 40 + $handle->setFullName($document->getMonogram().' '.$name); 41 + $handle->setURI('/'.$document->getMonogram()); 42 42 } 43 43 } 44 44
+55 -7
src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php
··· 25 25 'signerPHIDs', 26 26 $this->readUsersFromRequest($request, 'signers')); 27 27 28 + $saved->setParameter( 29 + 'documentPHIDs', 30 + $this->readPHIDsFromRequest( 31 + $request, 32 + 'documents', 33 + array( 34 + PhabricatorLegalpadPHIDTypeDocument::TYPECONST, 35 + ))); 36 + 28 37 return $saved; 29 38 } 30 39 ··· 38 47 39 48 if ($this->document) { 40 49 $query->withDocumentPHIDs(array($this->document->getPHID())); 50 + } else { 51 + $document_phids = $saved->getParameter('documentPHIDs', array()); 52 + if ($document_phids) { 53 + $query->withDocumentPHIDs($document_phids); 54 + } 41 55 } 42 56 43 57 return $query; ··· 47 61 AphrontFormView $form, 48 62 PhabricatorSavedQuery $saved_query) { 49 63 64 + $document_phids = $saved_query->getParameter('documentPHIDs', array()); 50 65 $signer_phids = $saved_query->getParameter('signerPHIDs', array()); 51 66 52 - $phids = array_merge($signer_phids); 67 + $phids = array_merge($document_phids, $signer_phids); 53 68 $handles = id(new PhabricatorHandleQuery()) 54 69 ->setViewer($this->requireViewer()) 55 70 ->withPHIDs($phids) 56 71 ->execute(); 72 + 73 + if (!$this->document) { 74 + $form 75 + ->appendChild( 76 + id(new AphrontFormTokenizerControl()) 77 + ->setDatasource('/typeahead/common/legalpaddocuments/') 78 + ->setName('documents') 79 + ->setLabel(pht('Documents')) 80 + ->setValue(array_select_keys($handles, $document_phids))); 81 + } 57 82 58 83 $form 59 84 ->appendChild( ··· 68 93 if ($this->document) { 69 94 return '/legalpad/signatures/'.$this->document->getID().'/'.$path; 70 95 } else { 71 - throw new Exception( 72 - pht( 73 - 'Searching for signatures outside of a document context is not '. 74 - 'currently supported.')); 96 + return '/legalpad/signatures/'.$path; 75 97 } 76 98 } 77 99 ··· 97 119 } 98 120 99 121 protected function getRequiredHandlePHIDsForResultList( 100 - array $documents, 122 + array $signatures, 101 123 PhabricatorSavedQuery $query) { 102 - return mpull($documents, 'getSignerPHID'); 124 + 125 + return array_merge( 126 + mpull($signatures, 'getSignerPHID'), 127 + mpull($signatures, 'getDocumentPHID')); 103 128 } 104 129 105 130 protected function renderResultList( ··· 150 175 151 176 $rows[] = array( 152 177 $sig_icon, 178 + $handles[$document->getPHID()]->renderLink(), 153 179 $handles[$signature->getSignerPHID()]->renderLink(), 154 180 $name, 155 181 phutil_tag( ··· 166 192 ->setHeaders( 167 193 array( 168 194 '', 195 + pht('Document'), 169 196 pht('Account'), 170 197 pht('Name'), 171 198 pht('Email'), 172 199 pht('Signed'), 173 200 )) 201 + ->setColumnVisibility( 202 + array( 203 + true, 204 + 205 + // Only show the "Document" column if we aren't scoped to a 206 + // particular document. 207 + !$this->document, 208 + )) 174 209 ->setColumnClasses( 175 210 array( 211 + '', 176 212 '', 177 213 '', 178 214 '', ··· 183 219 $box = id(new PHUIObjectBoxView()) 184 220 ->setHeaderText(pht('Signatures')) 185 221 ->appendChild($table); 222 + 223 + if (!$this->document) { 224 + $policy_notice = id(new AphrontErrorView()) 225 + ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) 226 + ->setErrors( 227 + array( 228 + pht( 229 + 'NOTE: You can only see your own signatures and signatures on '. 230 + 'documents you have permission to edit.'), 231 + )); 232 + $box->setErrorView($policy_notice); 233 + } 186 234 187 235 return $box; 188 236 }