From 705fd11ba1735b736a6ab10ff2abeca97f0b7a19 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Thu, 4 May 2017 11:53:52 -0700 Subject: [PATCH] Update Legalpad to use modular transactions Summary: Update Legalpad for modular transactions Test Plan: - New Document (no sign) - New Document (individual) - New Document (corp) - Require Signature - get prompted to sign before I can do anything. - Edit Documents - Sign Documents - Comment on Documents Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D17826 --- src/__phutil_library_map__.php | 14 +- .../LegalpadDocumentEditController.php | 15 +- .../editor/LegalpadDocumentEditor.php | 133 +++--------------- .../legalpad/storage/LegalpadTransaction.php | 77 +--------- .../LegalpadDocumentPreambleTransaction.php | 57 ++++++++ ...padDocumentRequireSignatureTransaction.php | 58 ++++++++ ...galpadDocumentSignatureTypeTransaction.php | 29 ++++ .../LegalpadDocumentTextTransaction.php | 60 ++++++++ .../LegalpadDocumentTitleTransaction.php | 58 ++++++++ .../LegalpadDocumentTransactionType.php | 4 + 10 files changed, 308 insertions(+), 197 deletions(-) create mode 100644 src/applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php create mode 100644 src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php create mode 100644 src/applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php create mode 100644 src/applications/legalpad/xaction/LegalpadDocumentTextTransaction.php create mode 100644 src/applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php create mode 100644 src/applications/legalpad/xaction/LegalpadDocumentTransactionType.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 35ea8488d0..bed1a60426 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1400,8 +1400,10 @@ phutil_register_library_map(array( 'LegalpadDocumentEditor' => 'applications/legalpad/editor/LegalpadDocumentEditor.php', 'LegalpadDocumentListController' => 'applications/legalpad/controller/LegalpadDocumentListController.php', 'LegalpadDocumentManageController' => 'applications/legalpad/controller/LegalpadDocumentManageController.php', + 'LegalpadDocumentPreambleTransaction' => 'applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php', 'LegalpadDocumentQuery' => 'applications/legalpad/query/LegalpadDocumentQuery.php', 'LegalpadDocumentRemarkupRule' => 'applications/legalpad/remarkup/LegalpadDocumentRemarkupRule.php', + 'LegalpadDocumentRequireSignatureTransaction' => 'applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php', 'LegalpadDocumentSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSearchEngine.php', 'LegalpadDocumentSignController' => 'applications/legalpad/controller/LegalpadDocumentSignController.php', 'LegalpadDocumentSignature' => 'applications/legalpad/storage/LegalpadDocumentSignature.php', @@ -1409,8 +1411,12 @@ phutil_register_library_map(array( 'LegalpadDocumentSignatureListController' => 'applications/legalpad/controller/LegalpadDocumentSignatureListController.php', 'LegalpadDocumentSignatureQuery' => 'applications/legalpad/query/LegalpadDocumentSignatureQuery.php', 'LegalpadDocumentSignatureSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php', + 'LegalpadDocumentSignatureTypeTransaction' => 'applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php', 'LegalpadDocumentSignatureVerificationController' => 'applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php', 'LegalpadDocumentSignatureViewController' => 'applications/legalpad/controller/LegalpadDocumentSignatureViewController.php', + 'LegalpadDocumentTextTransaction' => 'applications/legalpad/xaction/LegalpadDocumentTextTransaction.php', + 'LegalpadDocumentTitleTransaction' => 'applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php', + 'LegalpadDocumentTransactionType' => 'applications/legalpad/xaction/LegalpadDocumentTransactionType.php', 'LegalpadMailReceiver' => 'applications/legalpad/mail/LegalpadMailReceiver.php', 'LegalpadObjectNeedsSignatureEdgeType' => 'applications/legalpad/edge/LegalpadObjectNeedsSignatureEdgeType.php', 'LegalpadReplyHandler' => 'applications/legalpad/mail/LegalpadReplyHandler.php', @@ -6395,8 +6401,10 @@ phutil_register_library_map(array( 'LegalpadDocumentEditor' => 'PhabricatorApplicationTransactionEditor', 'LegalpadDocumentListController' => 'LegalpadController', 'LegalpadDocumentManageController' => 'LegalpadController', + 'LegalpadDocumentPreambleTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentRemarkupRule' => 'PhabricatorObjectRemarkupRule', + 'LegalpadDocumentRequireSignatureTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine', 'LegalpadDocumentSignController' => 'LegalpadController', 'LegalpadDocumentSignature' => array( @@ -6407,15 +6415,19 @@ phutil_register_library_map(array( 'LegalpadDocumentSignatureListController' => 'LegalpadController', 'LegalpadDocumentSignatureQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentSignatureSearchEngine' => 'PhabricatorApplicationSearchEngine', + 'LegalpadDocumentSignatureTypeTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentSignatureVerificationController' => 'LegalpadController', 'LegalpadDocumentSignatureViewController' => 'LegalpadController', + 'LegalpadDocumentTextTransaction' => 'LegalpadDocumentTransactionType', + 'LegalpadDocumentTitleTransaction' => 'LegalpadDocumentTransactionType', + 'LegalpadDocumentTransactionType' => 'PhabricatorModularTransactionType', 'LegalpadMailReceiver' => 'PhabricatorObjectMailReceiver', 'LegalpadObjectNeedsSignatureEdgeType' => 'PhabricatorEdgeType', 'LegalpadReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'LegalpadRequireSignatureHeraldAction' => 'HeraldAction', 'LegalpadSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'LegalpadSignatureNeededByObjectEdgeType' => 'PhabricatorEdgeType', - 'LegalpadTransaction' => 'PhabricatorApplicationTransaction', + 'LegalpadTransaction' => 'PhabricatorModularTransaction', 'LegalpadTransactionComment' => 'PhabricatorApplicationTransactionComment', 'LegalpadTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'LegalpadTransactionView' => 'PhabricatorApplicationTransactionView', diff --git a/src/applications/legalpad/controller/LegalpadDocumentEditController.php b/src/applications/legalpad/controller/LegalpadDocumentEditController.php index 8f84f60339..9b1d2ead22 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentEditController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentEditController.php @@ -57,7 +57,8 @@ final class LegalpadDocumentEditController extends LegalpadController { $errors[] = pht('The document title may not be blank.'); } else { $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_TITLE) + ->setTransactionType( + LegalpadDocumentTitleTransaction::TRANSACTIONTYPE) ->setNewValue($title); } @@ -67,7 +68,8 @@ final class LegalpadDocumentEditController extends LegalpadController { $errors[] = pht('The document may not be blank.'); } else { $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_TEXT) + ->setTransactionType( + LegalpadDocumentTextTransaction::TRANSACTIONTYPE) ->setNewValue($text); } @@ -83,13 +85,15 @@ final class LegalpadDocumentEditController extends LegalpadController { if ($is_create) { $v_signature_type = $request->getStr('signatureType'); $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_SIGNATURE_TYPE) + ->setTransactionType( + LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE) ->setNewValue($v_signature_type); } $v_preamble = $request->getStr('preamble'); $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_PREAMBLE) + ->setTransactionType( + LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE) ->setNewValue($v_preamble); $v_require_signature = $request->getBool('requireSignature', 0); @@ -106,7 +110,8 @@ final class LegalpadDocumentEditController extends LegalpadController { } if ($viewer->getIsAdmin()) { $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_REQUIRE_SIGNATURE) + ->setTransactionType( + LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE) ->setNewValue($v_require_signature); } diff --git a/src/applications/legalpad/editor/LegalpadDocumentEditor.php b/src/applications/legalpad/editor/LegalpadDocumentEditor.php index 5e319b5905..14430b2c33 100644 --- a/src/applications/legalpad/editor/LegalpadDocumentEditor.php +++ b/src/applications/legalpad/editor/LegalpadDocumentEditor.php @@ -3,8 +3,6 @@ final class LegalpadDocumentEditor extends PhabricatorApplicationTransactionEditor { - private $isContribution = false; - public function getEditorApplicationClass() { return 'PhabricatorLegalpadApplication'; } @@ -13,15 +11,6 @@ final class LegalpadDocumentEditor return pht('Legalpad Documents'); } - private function setIsContribution($is_contribution) { - $this->isContribution = $is_contribution; - return $this; - } - - private function isContribution() { - return $this->isContribution; - } - public function getTransactionTypes() { $types = parent::getTransactionTypes(); @@ -29,99 +18,25 @@ final class LegalpadDocumentEditor $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; - $types[] = LegalpadTransaction::TYPE_TITLE; - $types[] = LegalpadTransaction::TYPE_TEXT; - $types[] = LegalpadTransaction::TYPE_SIGNATURE_TYPE; - $types[] = LegalpadTransaction::TYPE_PREAMBLE; - $types[] = LegalpadTransaction::TYPE_REQUIRE_SIGNATURE; - return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TITLE: - return $object->getDocumentBody()->getTitle(); - case LegalpadTransaction::TYPE_TEXT: - return $object->getDocumentBody()->getText(); - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - return $object->getSignatureType(); - case LegalpadTransaction::TYPE_PREAMBLE: - return $object->getPreamble(); - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - return (bool)$object->getRequireSignature(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TITLE: - case LegalpadTransaction::TYPE_TEXT: - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - case LegalpadTransaction::TYPE_PREAMBLE: - return $xaction->getNewValue(); - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - return (bool)$xaction->getNewValue(); - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TITLE: - $object->setTitle($xaction->getNewValue()); - $body = $object->getDocumentBody(); - $body->setTitle($xaction->getNewValue()); - $this->setIsContribution(true); - break; - case LegalpadTransaction::TYPE_TEXT: - $body = $object->getDocumentBody(); - $body->setText($xaction->getNewValue()); - $this->setIsContribution(true); - break; - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - $object->setSignatureType($xaction->getNewValue()); - break; - case LegalpadTransaction::TYPE_PREAMBLE: - $object->setPreamble($xaction->getNewValue()); - break; - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - $object->setRequireSignature((int)$xaction->getNewValue()); - break; - } - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - if ($xaction->getNewValue()) { - $session = new PhabricatorAuthSession(); - queryfx( - $session->establishConnection('w'), - 'UPDATE %T SET signedLegalpadDocuments = 0', - $session->getTableName()); - } - break; - } - return; - } - protected function applyFinalEffects( PhabricatorLiskDAO $object, array $xactions) { - if ($this->isContribution()) { + $is_contribution = false; + + foreach ($xactions as $xaction) { + switch ($xaction->getTransactionType()) { + case LegalpadDocumentTitleTransaction::TRANSACTIONTYPE: + case LegalpadDocumentTextTransaction::TRANSACTIONTYPE: + $is_contribution = true; + break; + } + } + + if ($is_contribution) { $object->setVersions($object->getVersions() + 1); $body = $object->getDocumentBody(); $body->setVersion($object->getVersions()); @@ -149,22 +64,6 @@ final class LegalpadDocumentEditor return $xactions; } - protected function mergeTransactions( - PhabricatorApplicationTransaction $u, - PhabricatorApplicationTransaction $v) { - - $type = $u->getTransactionType(); - switch ($type) { - case LegalpadTransaction::TYPE_TITLE: - case LegalpadTransaction::TYPE_TEXT: - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - case LegalpadTransaction::TYPE_PREAMBLE: - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - return $v; - } - - return parent::mergeTransactions($u, $v); - } /* -( Sending Mail )------------------------------------------------------- */ @@ -201,10 +100,10 @@ final class LegalpadDocumentEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TEXT: - case LegalpadTransaction::TYPE_TITLE: - case LegalpadTransaction::TYPE_PREAMBLE: - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: + case LegalpadDocumentTextTransaction::TRANSACTIONTYPE: + case LegalpadDocumentTitleTransaction::TRANSACTIONTYPE: + case LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE: + case LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE: return true; } diff --git a/src/applications/legalpad/storage/LegalpadTransaction.php b/src/applications/legalpad/storage/LegalpadTransaction.php index f85c569279..c43c86c5fc 100644 --- a/src/applications/legalpad/storage/LegalpadTransaction.php +++ b/src/applications/legalpad/storage/LegalpadTransaction.php @@ -1,12 +1,6 @@ getOldValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - case self::TYPE_TEXT: - return ($old === null); - case self::TYPE_SIGNATURE_TYPE: - return true; - } - - return parent::shouldHide(); - } - - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_TITLE: - return pht( - '%s renamed this document from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - case self::TYPE_TEXT: - return pht( - "%s updated the document's text.", - $this->renderHandleLink($author_phid)); - case self::TYPE_PREAMBLE: - return pht( - '%s updated the preamble.', - $this->renderHandleLink($author_phid)); - case self::TYPE_REQUIRE_SIGNATURE: - if ($new) { - $text = pht( - '%s set the document to require signatures.', - $this->renderHandleLink($author_phid)); - } else { - $text = pht( - '%s set the document to not require signatures.', - $this->renderHandleLink($author_phid)); - } - return $text; - } - - return parent::getTitle(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - case self::TYPE_TEXT: - case self::TYPE_PREAMBLE: - return true; - } - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - return $this->renderTextCorpusChangeDetails( - $viewer, - $this->getOldValue(), - $this->getNewValue()); + public function getBaseTransactionClass() { + return 'LegalpadDocumentTransactionType'; } } diff --git a/src/applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php new file mode 100644 index 0000000000..a2b5e1f5cd --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php @@ -0,0 +1,57 @@ +getPreamble(); + } + + public function applyInternalEffects($object, $value) { + $object->setPreamble($value); + } + + public function getTitle() { + return pht( + '%s updated the document preamble.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the document preamble for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO DOCUMENT PREAMBLE'); + } + + 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; + } + + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php new file mode 100644 index 0000000000..ffef42f0ce --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php @@ -0,0 +1,58 @@ +getRequireSignature(); + } + + public function applyInternalEffects($object, $value) { + $object->setRequireSignature($value); + } + + public function applyExternalEffects($object, $value) { + if (strlen($value)) { + $session = new PhabricatorAuthSession(); + queryfx( + $session->establishConnection('w'), + 'UPDATE %T SET signedLegalpadDocuments = 0', + $session->getTableName()); + } + } + + public function getTitle() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s set the document to require signatures.', + $this->renderAuthor()); + } else { + return pht( + '%s set the document to not require signatures.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s set the document %s to require signatures.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s set the document %s to not require signatures.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + return 'fa-pencil-square'; + } + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php new file mode 100644 index 0000000000..df9cf60457 --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php @@ -0,0 +1,29 @@ +getSignatureType(); + } + + public function applyInternalEffects($object, $value) { + $object->setSignatureType($value); + } + + public function getTitle() { + return pht( + '%s set the document signature type.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s set the document signature type for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentTextTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentTextTransaction.php new file mode 100644 index 0000000000..c17ebc890d --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentTextTransaction.php @@ -0,0 +1,60 @@ +getDocumentBody(); + return $body->getText(); + } + + public function applyInternalEffects($object, $value) { + $body = $object->getDocumentBody(); + $body->setText($value); + $object->attachDocumentBody($body); + } + + public function getTitle() { + return pht( + '%s updated the document text.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the document text for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO DOCUMENT TEXT'); + } + + 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; + } + + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php new file mode 100644 index 0000000000..c6a4b5b509 --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php @@ -0,0 +1,58 @@ +getTitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setTitle($value); + $body = $object->getDocumentBody(); + $body->setTitle($value); + $object->attachDocumentBody($body); + } + + public function getTitle() { + return pht( + '%s renamed this document from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s renamed document %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Documents must have a title.')); + } + + $max_length = $object->getColumnMaximumByteLength('title'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The title can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentTransactionType.php b/src/applications/legalpad/xaction/LegalpadDocumentTransactionType.php new file mode 100644 index 0000000000..58763914ee --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentTransactionType.php @@ -0,0 +1,4 @@ +