diff --git a/src/applications/differential/editor/DifferentialTransactionEditor.php b/src/applications/differential/editor/DifferentialTransactionEditor.php index c452cb9346..5bc33dabe1 100644 --- a/src/applications/differential/editor/DifferentialTransactionEditor.php +++ b/src/applications/differential/editor/DifferentialTransactionEditor.php @@ -636,8 +636,8 @@ final class DifferentialTransactionEditor $viewer = $this->requireActor(); - $body = new PhabricatorMetaMTAMailBody(); - $body->setViewer($this->requireActor()); + $body = id(new PhabricatorMetaMTAMailBody()) + ->setViewer($viewer); $revision_uri = $object->getURI(); $revision_uri = PhabricatorEnv::getProductionURI($revision_uri); diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php index 727a4ca184..bc93de2db2 100644 --- a/src/applications/differential/query/DifferentialRevisionQuery.php +++ b/src/applications/differential/query/DifferentialRevisionQuery.php @@ -25,6 +25,8 @@ final class DifferentialRevisionQuery private $updatedEpochMax; private $statuses; private $isOpen; + private $createdEpochMin; + private $createdEpochMax; const ORDER_MODIFIED = 'order-modified'; const ORDER_CREATED = 'order-created'; @@ -206,6 +208,12 @@ final class DifferentialRevisionQuery return $this; } + public function withCreatedEpochBetween($min, $max) { + $this->createdEpochMin = $min; + $this->createdEpochMax = $max; + return $this; + } + /** * Set whether or not the query should load the active diff for each @@ -687,6 +695,20 @@ final class DifferentialRevisionQuery $this->updatedEpochMax); } + if ($this->createdEpochMin !== null) { + $where[] = qsprintf( + $conn_r, + 'r.dateCreated >= %d', + $this->createdEpochMin); + } + + if ($this->createdEpochMax !== null) { + $where[] = qsprintf( + $conn_r, + 'r.dateCreated <= %d', + $this->createdEpochMax); + } + if ($this->statuses !== null) { $where[] = qsprintf( $conn_r, diff --git a/src/applications/differential/query/DifferentialRevisionSearchEngine.php b/src/applications/differential/query/DifferentialRevisionSearchEngine.php index 835291fba8..557ca23078 100644 --- a/src/applications/differential/query/DifferentialRevisionSearchEngine.php +++ b/src/applications/differential/query/DifferentialRevisionSearchEngine.php @@ -45,6 +45,12 @@ final class DifferentialRevisionSearchEngine $query->withStatuses($map['statuses']); } + if ($map['createdStart'] || $map['createdEnd']) { + $query->withCreatedEpochBetween( + $map['createdStart'], + $map['createdEnd']); + } + return $query; } @@ -84,6 +90,16 @@ final class DifferentialRevisionSearchEngine ->setDatasource(new DifferentialRevisionStatusFunctionDatasource()) ->setDescription( pht('Find revisions with particular statuses.')), + id(new PhabricatorSearchDateField()) + ->setLabel(pht('Created After')) + ->setKey('createdStart') + ->setDescription( + pht('Find revisions created at or after a particular time.')), + id(new PhabricatorSearchDateField()) + ->setLabel(pht('Created Before')) + ->setKey('createdEnd') + ->setDescription( + pht('Find revisions created at or before a particular time.')), ); } diff --git a/src/applications/pholio/editor/PholioMockEditor.php b/src/applications/pholio/editor/PholioMockEditor.php index 6bd49d2e7b..d1f7daf3a5 100644 --- a/src/applications/pholio/editor/PholioMockEditor.php +++ b/src/applications/pholio/editor/PholioMockEditor.php @@ -128,51 +128,30 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor { PhabricatorLiskDAO $object, array $xactions) { - $body = new PhabricatorMetaMTAMailBody(); - $headers = array(); - $comments = array(); - $inline_comments = array(); + $viewer = $this->requireActor(); + $body = id(new PhabricatorMetaMTAMailBody()) + ->setViewer($viewer); + + $mock_uri = $object->getURI(); + $mock_uri = PhabricatorEnv::getProductionURI($mock_uri); + + $this->addHeadersAndCommentsToMailBody( + $body, + $xactions, + pht('View Mock'), + $mock_uri); + + $type_inline = PholioMockInlineTransaction::TRANSACTIONTYPE; + + $inlines = array(); foreach ($xactions as $xaction) { - if ($xaction->shouldHide()) { - continue; - } - $comment = $xaction->getComment(); - switch ($xaction->getTransactionType()) { - case PholioMockInlineTransaction::TRANSACTIONTYPE: - if ($comment && strlen($comment->getContent())) { - $inline_comments[] = $comment; - } - break; - case PhabricatorTransactions::TYPE_COMMENT: - if ($comment && strlen($comment->getContent())) { - $comments[] = $comment->getContent(); - } - // fallthrough - default: - $headers[] = id(clone $xaction) - ->setRenderingTarget('text') - ->getTitle(); - break; + if ($xaction->getTransactionType() == $type_inline) { + $inlines[] = $xaction; } } - $body->addRawSection(implode("\n", $headers)); - - foreach ($comments as $comment) { - $body->addRawSection($comment); - } - - if ($inline_comments) { - $body->addRawSection(pht('INLINE COMMENTS')); - foreach ($inline_comments as $comment) { - $text = pht( - 'Image %d: %s', - $comment->getImageID(), - $comment->getContent()); - $body->addRawSection($text); - } - } + $this->appendInlineCommentsForMail($object, $inlines, $body); $body->addLinkSection( pht('MOCK DETAIL'), @@ -181,6 +160,51 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor { return $body; } + private function appendInlineCommentsForMail( + $object, + array $inlines, + PhabricatorMetaMTAMailBody $body) { + + if (!$inlines) { + return; + } + + $viewer = $this->requireActor(); + + $header = pht('INLINE COMMENTS'); + $body->addRawPlaintextSection($header); + $body->addRawHTMLSection(phutil_tag('strong', array(), $header)); + + $image_ids = array(); + foreach ($inlines as $inline) { + $comment = $inline->getComment(); + $image_id = $comment->getImageID(); + $image_ids[$image_id] = $image_id; + } + + $images = id(new PholioImageQuery()) + ->setViewer($viewer) + ->withIDs($image_ids) + ->execute(); + $images = mpull($images, null, 'getID'); + + foreach ($inlines as $inline) { + $comment = $inline->getComment(); + $content = $comment->getContent(); + $image_id = $comment->getImageID(); + $image = idx($images, $image_id); + if ($image) { + $image_name = $image->getName(); + } else { + $image_name = pht('Unknown (ID %d)', $image_id); + } + + $body->addRemarkupSection( + pht('Image "%s":', $image_name), + $content); + } + } + protected function getMailSubjectPrefix() { return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix'); } diff --git a/src/applications/pholio/storage/PholioMock.php b/src/applications/pholio/storage/PholioMock.php index 523733b3df..569513cb46 100644 --- a/src/applications/pholio/storage/PholioMock.php +++ b/src/applications/pholio/storage/PholioMock.php @@ -58,6 +58,10 @@ final class PholioMock extends PholioDAO return 'M'.$this->getID(); } + public function getURI() { + return '/'.$this->getMonogram(); + } + protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, diff --git a/src/applications/pholio/storage/PholioTransaction.php b/src/applications/pholio/storage/PholioTransaction.php index a932cf2a60..240b9d93e6 100644 --- a/src/applications/pholio/storage/PholioTransaction.php +++ b/src/applications/pholio/storage/PholioTransaction.php @@ -53,4 +53,13 @@ final class PholioTransaction extends PhabricatorModularTransaction { return $tags; } + public function isInlineCommentTransaction() { + switch ($this->getTransactionType()) { + case PholioMockInlineTransaction::TRANSACTIONTYPE: + return true; + } + + return parent::isInlineCommentTransaction(); + } + }