diff --git a/src/applications/pholio/controller/PholioMockEditController.php b/src/applications/pholio/controller/PholioMockEditController.php index f3c0c265df..0eb46aa9ae 100644 --- a/src/applications/pholio/controller/PholioMockEditController.php +++ b/src/applications/pholio/controller/PholioMockEditController.php @@ -1,264 +1,265 @@ id = idx($data, 'id'); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); if ($this->id) { $mock = id(new PholioMockQuery()) ->setViewer($user) ->needImages(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->withIDs(array($this->id)) ->executeOne(); if (!$mock) { return new Aphront404Response(); } $title = pht('Edit Mock'); $is_new = false; $mock_images = $mock->getImages(); $files = mpull($mock_images, 'getFile'); $mock_images = mpull($mock_images, null, 'getFilePHID'); } else { $mock = id(new PholioMock()) ->setAuthorPHID($user->getPHID()) ->attachImages(array()) ->setViewPolicy(PhabricatorPolicies::POLICY_USER); $title = pht('Create Mock'); $is_new = true; $files = array(); $mock_images = array(); } $e_name = true; $e_images = true; $errors = array(); $v_name = $mock->getName(); $v_desc = $mock->getDescription(); $v_view = $mock->getViewPolicy(); $v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID( $mock->getPHID()); if ($request->isFormPost()) { $xactions = array(); $type_name = PholioTransactionType::TYPE_NAME; $type_desc = PholioTransactionType::TYPE_DESCRIPTION; $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_cc = PhabricatorTransactions::TYPE_SUBSCRIBERS; $v_name = $request->getStr('name'); $v_desc = $request->getStr('description'); $v_view = $request->getStr('can_view'); $v_cc = $request->getArr('cc'); $mock_xactions = array(); $mock_xactions[$type_name] = $v_name; $mock_xactions[$type_desc] = $v_desc; $mock_xactions[$type_view] = $v_view; $mock_xactions[$type_cc] = array('=' => $v_cc); if (!strlen($request->getStr('name'))) { $e_name = 'Required'; + $errors[] = pht('You must give the mock a name.'); } $file_phids = $request->getArr('file_phids'); if ($file_phids) { $files = id(new PhabricatorFileQuery()) ->setViewer($user) ->withPHIDs($file_phids) ->execute(); $files = mpull($files, null, 'getPHID'); $files = array_select_keys($files, $file_phids); } if (!$files) { $e_images = pht('Required'); $errors[] = pht('You must add at least one image to the mock.'); } else { $mock->setCoverPHID(head($files)->getPHID()); } if (!$errors) { foreach ($mock_xactions as $type => $value) { $xactions[$type] = id(new PholioTransaction()) ->setTransactionType($type) ->setNewValue($value); } $sequence = 0; foreach ($files as $file_phid => $file) { $mock_image = idx($mock_images, $file_phid); $title = $request->getStr('title_'.$file_phid); $description = $request->getStr('description_'.$file_phid); if (!$mock_image) { // this is an add $add_image = id(new PholioImage()) ->setFilePhid($file_phid) ->setName(strlen($title) ? $title : $file->getName()) ->setDescription($description) ->setSequence($sequence); $xactions[] = id(new PholioTransaction()) ->setTransactionType(PholioTransactionType::TYPE_IMAGE_FILE) ->setNewValue( array('+' => array($add_image))); } else { // update (maybe) $xactions[] = id(new PholioTransaction()) ->setTransactionType(PholioTransactionType::TYPE_IMAGE_NAME) ->setNewValue( array($mock_image->getPHID() => $title)); $xactions[] = id(new PholioTransaction()) ->setTransactionType( PholioTransactionType::TYPE_IMAGE_DESCRIPTION) ->setNewValue(array($mock_image->getPHID() => $description)); $mock_image->setSequence($sequence); } $sequence++; } foreach ($mock_images as $file_phid => $mock_image) { if (!isset($files[$file_phid])) { // this is a delete $xactions[] = id(new PholioTransaction()) ->setTransactionType(PholioTransactionType::TYPE_IMAGE_FILE) ->setNewValue( array('-' => array($mock_image))); } } $mock->openTransaction(); $editor = id(new PholioMockEditor()) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->setActor($user); $xactions = $editor->applyTransactions($mock, $xactions); $mock->saveTransaction(); return id(new AphrontRedirectResponse()) ->setURI('/M'.$mock->getID()); } } if ($errors) { $error_view = id(new AphrontErrorView()) ->setTitle(pht('Form Errors')) ->setErrors($errors); } else { $error_view = null; } if ($this->id) { $submit = id(new AphrontFormSubmitControl()) ->addCancelButton('/M'.$this->id) ->setValue(pht('Save')); } else { $submit = id(new AphrontFormSubmitControl()) ->addCancelButton($this->getApplicationURI()) ->setValue(pht('Create')); } $policies = id(new PhabricatorPolicyQuery()) ->setViewer($user) ->setObject($mock) ->execute(); // NOTE: Make this show up correctly on the rendered form. $mock->setViewPolicy($v_view); $handles = id(new PhabricatorObjectHandleData($v_cc)) ->setViewer($user) ->loadHandles(); $cc_tokens = mpull($handles, 'getFullName', 'getPHID'); $images_controller = id(new PholioDragAndDropUploadControl($request)) ->setUploadURI($this->getApplicationURI('image/upload/')) ->setValue($files) ->setImages($mock_images) ->setName('file_phids') ->setLabel(pht('Images')) ->setActivatedClass('aphront-textarea-drag-and-drop') ->setError($e_images); require_celerity_resource('pholio-edit-css'); $form = id(new AphrontFormView()) ->setUser($user) ->setFlexible(true) ->appendChild( id(new AphrontFormTextControl()) ->setName('name') ->setValue($v_name) ->setLabel(pht('Name')) ->setError($e_name)) ->appendChild( id(new PhabricatorRemarkupControl()) ->setName('description') ->setValue($v_desc) ->setLabel(pht('Description')) ->setUser($user)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setLabel(pht('CC')) ->setName('cc') ->setValue($cc_tokens) ->setUser($user) ->setDatasource('/typeahead/common/mailable/')) ->appendChild( id(new AphrontFormPolicyControl()) ->setUser($user) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicyObject($mock) ->setPolicies($policies) ->setName('can_view')) ->appendChild($images_controller) ->appendChild($submit); $crumbs = $this->buildApplicationCrumbs($this->buildSideNav()); $crumbs->addCrumb( id(new PhabricatorCrumbView()) ->setName($title) ->setHref($this->getApplicationURI())); $content = array( $crumbs, $error_view, $form, ); $nav = $this->buildSideNav(); $nav->selectFilter(null); $nav->appendChild($content); return $this->buildApplicationPage( $nav, array( 'title' => $title, 'device' => true, )); } } diff --git a/src/applications/pholio/editor/PholioMockEditor.php b/src/applications/pholio/editor/PholioMockEditor.php index da59ca2476..d52a514251 100644 --- a/src/applications/pholio/editor/PholioMockEditor.php +++ b/src/applications/pholio/editor/PholioMockEditor.php @@ -1,367 +1,367 @@ newImages = $new_images; return $this; } private function getNewImages() { return $this->newImages; } public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PholioTransactionType::TYPE_NAME; $types[] = PholioTransactionType::TYPE_DESCRIPTION; $types[] = PholioTransactionType::TYPE_INLINE; $types[] = PholioTransactionType::TYPE_IMAGE_FILE; $types[] = PholioTransactionType::TYPE_IMAGE_NAME; $types[] = PholioTransactionType::TYPE_IMAGE_DESCRIPTION; return $types; } protected function getCustomTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_NAME: return $object->getName(); case PholioTransactionType::TYPE_DESCRIPTION: return $object->getDescription(); case PholioTransactionType::TYPE_IMAGE_FILE: $images = $object->getImages(); return mpull($images, 'getPHID'); case PholioTransactionType::TYPE_IMAGE_NAME: $name = null; $phid = null; $image = $this->getImageForXaction($object, $xaction); - if ($image && $image->getName()) { + if ($image) { $name = $image->getName(); $phid = $image->getPHID(); } return array ($phid => $name); case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: $description = null; $phid = null; $image = $this->getImageForXaction($object, $xaction); - if ($image && $image->getDescription()) { + if ($image) { $description = $image->getDescription(); $phid = $image->getPHID(); } return array($phid => $description); } } protected function getCustomTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_NAME: case PholioTransactionType::TYPE_DESCRIPTION: case PholioTransactionType::TYPE_IMAGE_NAME: case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: return $xaction->getNewValue(); case PholioTransactionType::TYPE_IMAGE_FILE: $raw_new_value = $xaction->getNewValue(); $new_value = array(); foreach ($raw_new_value as $key => $images) { $new_value[$key] = mpull($images, 'getPHID'); } $xaction->setNewValue($new_value); return $this->getPHIDTransactionNewValue($xaction); } } protected function transactionHasEffect( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_INLINE: return true; } return parent::transactionHasEffect($object, $xaction); } protected function shouldApplyInitialEffects( PhabricatorLiskDAO $object, array $xactions) { foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_IMAGE_FILE: return true; break; } } return false; } protected function applyInitialEffects( PhabricatorLiskDAO $object, array $xactions) { $new_images = array(); foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_IMAGE_FILE: $new_value = $xaction->getNewValue(); foreach ($new_value as $key => $txn_images) { if ($key != '+') { continue; } foreach ($txn_images as $image) { $image->save(); $new_images[] = $image; } } break; } } $this->setNewImages($new_images); } protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_NAME: $object->setName($xaction->getNewValue()); if ($object->getOriginalName() === null) { $object->setOriginalName($xaction->getNewValue()); } break; case PholioTransactionType::TYPE_DESCRIPTION: $object->setDescription($xaction->getNewValue()); break; } } private function getImageForXaction( PholioMock $mock, PhabricatorApplicationTransaction $xaction) { $raw_new_value = $xaction->getNewValue(); $image_phid = key($raw_new_value); $images = $mock->getImages(); foreach ($images as $image) { if ($image->getPHID() == $image_phid) { return $image; } } return null; } protected function applyCustomExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_IMAGE_FILE: $old_map = array_fuse($xaction->getOldValue()); $new_map = array_fuse($xaction->getNewValue()); $obsolete_map = array_diff_key($old_map, $new_map); $images = $object->getImages(); foreach ($images as $seq => $image) { if (isset($obsolete_map[$image->getPHID()])) { $image->setIsObsolete(1); $image->save(); unset($images[$seq]); } } $object->attachImages($images); break; case PholioTransactionType::TYPE_IMAGE_NAME: $image = $this->getImageForXaction($object, $xaction); $value = (string) head($xaction->getNewValue()); $image->setName($value); $image->save(); break; case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: $image = $this->getImageForXaction($object, $xaction); $value = (string) head($xaction->getNewValue()); $image->setDescription($value); $image->save(); break; } } protected function applyFinalEffects( PhabricatorLiskDAO $object, array $xactions) { $images = $this->getNewImages(); foreach ($images as $image) { $image->setMockID($object->getID()); $image->save(); } } protected function mergeTransactions( PhabricatorApplicationTransaction $u, PhabricatorApplicationTransaction $v) { $type = $u->getTransactionType(); switch ($type) { case PholioTransactionType::TYPE_NAME: case PholioTransactionType::TYPE_DESCRIPTION: return $v; case PholioTransactionType::TYPE_IMAGE_FILE: return $this->mergePHIDOrEdgeTransactions($u, $v); case PholioTransactionType::TYPE_IMAGE_NAME: case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: $raw_new_value_u = $u->getNewValue(); $raw_new_value_v = $v->getNewValue(); $phid_u = key($raw_new_value_u); $phid_v = key($raw_new_value_v); if ($phid_u == $phid_v) { return $v; } break; } return parent::mergeTransactions($u, $v); } protected function supportsMail() { return true; } protected function buildReplyHandler(PhabricatorLiskDAO $object) { return id(new PholioReplyHandler()) ->setMailReceiver($object); } protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $name = $object->getName(); $original_name = $object->getOriginalName(); return id(new PhabricatorMetaMTAMail()) ->setSubject("M{$id}: {$name}") ->addHeader('Thread-Topic', "M{$id}: {$original_name}"); } protected function getMailTo(PhabricatorLiskDAO $object) { return array( $object->getAuthorPHID(), $this->requireActor()->getPHID(), ); } protected function buildMailBody( PhabricatorLiskDAO $object, array $xactions) { $body = new PhabricatorMetaMTAMailBody(); $headers = array(); $comments = array(); $inline_comments = array(); foreach ($xactions as $xaction) { if ($xaction->shouldHide()) { continue; } $comment = $xaction->getComment(); switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_INLINE: 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; } } $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); } } $body->addTextSection( pht('MOCK DETAIL'), PhabricatorEnv::getProductionURI('/M'.$object->getID())); return $body; } protected function getMailSubjectPrefix() { return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix'); } protected function supportsFeed() { return true; } protected function supportsSearch() { return true; } protected function sortTransactions(array $xactions) { $head = array(); $tail = array(); // Move inline comments to the end, so the comments precede them. foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); if ($type == PholioTransactionType::TYPE_INLINE) { $tail[] = $xaction; } else { $head[] = $xaction; } } return array_values(array_merge($head, $tail)); } protected function shouldImplyCC( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PholioTransactionType::TYPE_INLINE: return true; } return parent::shouldImplyCC($object, $xaction); } } diff --git a/src/applications/pholio/storage/PholioTransaction.php b/src/applications/pholio/storage/PholioTransaction.php index 50353a000d..feee223603 100644 --- a/src/applications/pholio/storage/PholioTransaction.php +++ b/src/applications/pholio/storage/PholioTransaction.php @@ -1,268 +1,276 @@ getObjectPHID(); $new = $this->getNewValue(); $old = $this->getOldValue(); switch ($this->getTransactionType()) { case PholioTransactionType::TYPE_IMAGE_FILE: $phids = array_merge($phids, $new, $old); break; case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: case PholioTransactionType::TYPE_IMAGE_NAME: $phids[] = key($new); break; } return $phids; } public function shouldHide() { $old = $this->getOldValue(); switch ($this->getTransactionType()) { - case PholioTransactionType::TYPE_NAME: case PholioTransactionType::TYPE_DESCRIPTION: return ($old === null); case PholioTransactionType::TYPE_IMAGE_NAME: case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: - $old_value = reset($old); - return ($old_value === null); + return ($old === array(null => null)); } return parent::shouldHide(); } public function getIcon() { switch ($this->getTransactionType()) { case PholioTransactionType::TYPE_INLINE: return 'comment'; case PholioTransactionType::TYPE_NAME: case PholioTransactionType::TYPE_DESCRIPTION: case PholioTransactionType::TYPE_IMAGE_NAME: case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: return 'edit'; case PholioTransactionType::TYPE_IMAGE_FILE: return 'attach'; } return parent::getIcon(); } public function getTitle() { $author_phid = $this->getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $type = $this->getTransactionType(); switch ($type) { case PholioTransactionType::TYPE_NAME: - return pht( - '%s renamed this mock from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); + if ($old === null) { + return pht( + '%s created "%s".', + $this->renderHandleLink($author_phid), + $new); + } else { + return pht( + '%s renamed this mock from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $old, + $new); + } break; case PholioTransactionType::TYPE_DESCRIPTION: return pht( "%s updated the mock's description.", $this->renderHandleLink($author_phid)); break; case PholioTransactionType::TYPE_INLINE: $count = 1; foreach ($this->getTransactionGroup() as $xaction) { if ($xaction->getTransactionType() == $type) { $count++; } } return pht( '%s added %d inline comment(s).', $this->renderHandleLink($author_phid), $count); break; case PholioTransactionType::TYPE_IMAGE_FILE: $add = array_diff($new, $old); $rem = array_diff($old, $new); if ($add && $rem) { return pht( '%s edited image(s), added %d: %s; removed %d: %s.', $this->renderHandleLink($author_phid), count($add), $this->renderHandleList($add), count($rem), $this->renderHandleList($rem)); } else if ($add) { return pht( '%s added %d image(s): %s.', $this->renderHandleLink($author_phid), count($add), $this->renderHandleList($add)); } else { return pht( '%s removed %d image(s): %s.', $this->renderHandleLink($author_phid), count($rem), $this->renderHandleList($rem)); } break; case PholioTransactionType::TYPE_IMAGE_NAME: return pht( '%s renamed an image (%s) from "%s" to "%s".', $this->renderHandleLink($author_phid), $this->renderHandleLink(key($new)), reset($old), reset($new)); break; case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: return pht( '%s updated an image\'s (%s) description.', $this->renderHandleLink($author_phid), $this->renderHandleLink(key($new))); break; } return parent::getTitle(); } public function getTitleForFeed() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $type = $this->getTransactionType(); switch ($type) { case PholioTransactionType::TYPE_NAME: if ($old === null) { return pht( '%s created %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } else { return pht( '%s renamed %s from "%s" to "%s".', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), $old, $new); } break; case PholioTransactionType::TYPE_DESCRIPTION: return pht( '%s updated the description for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; case PholioTransactionType::TYPE_INLINE: return pht( '%s added an inline comment to %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; case PholioTransactionType::TYPE_IMAGE_FILE: return pht( '%s updated images of %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; case PholioTransactionType::TYPE_IMAGE_NAME: return pht( '%s updated the image names of %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: return pht( '%s updated image descriptions of %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; } return parent::getTitleForFeed(); } public function hasChangeDetails() { switch ($this->getTransactionType()) { case PholioTransactionType::TYPE_DESCRIPTION: case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: return true; } return parent::hasChangeDetails(); } public function renderChangeDetails(PhabricatorUser $viewer) { $old = $this->getOldValue(); $new = $this->getNewValue(); if ($this->getTransactionType() == PholioTransactionType::TYPE_IMAGE_DESCRIPTION) { $old = reset($old); $new = reset($new); } $view = id(new PhabricatorApplicationTransactionTextDiffDetailView()) ->setUser($viewer) ->setOldText($old) ->setNewText($new); return $view->render(); } public function getColor() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case PholioTransactionType::TYPE_NAME: + if ($old === null) { + return PhabricatorTransactions::COLOR_GREEN; + } case PholioTransactionType::TYPE_DESCRIPTION: case PholioTransactionType::TYPE_IMAGE_NAME: case PholioTransactionType::TYPE_IMAGE_DESCRIPTION: return PhabricatorTransactions::COLOR_BLUE; case PholioTransactionType::TYPE_IMAGE_FILE: $add = array_diff($new, $old); $rem = array_diff($old, $new); if ($add && $rem) { return PhabricatorTransactions::COLOR_YELLOW; } else if ($add) { return PhabricatorTransactions::COLOR_GREEN; } else { return PhabricatorTransactions::COLOR_RED; } } return parent::getColor(); } } diff --git a/src/applications/pholio/view/PholioMockImagesView.php b/src/applications/pholio/view/PholioMockImagesView.php index d96a87f509..39654709b9 100644 --- a/src/applications/pholio/view/PholioMockImagesView.php +++ b/src/applications/pholio/view/PholioMockImagesView.php @@ -1,176 +1,175 @@ commentFormID = $comment_form_id; return $this; } public function getCommentFormID() { return $this->commentFormID; } public function setRequestURI(PhutilURI $request_uri) { $this->requestURI = $request_uri; return $this; } public function getRequestURI() { return $this->requestURI; } public function setImageID($image_id) { $this->imageID = $image_id; return $this; } public function getImageID() { return $this->imageID; } public function setMock(PholioMock $mock) { $this->mock = $mock; return $this; } public function render() { if (!$this->mock) { throw new Exception("Call setMock() before render()!"); } $mock = $this->mock; require_celerity_resource('javelin-behavior-pholio-mock-view'); $images = array(); $panel_id = celerity_generate_unique_node_id(); $viewport_id = celerity_generate_unique_node_id(); $ids = mpull($mock->getImages(), 'getID'); if ($this->imageID && isset($ids[$this->imageID])) { $selected_id = $this->imageID; } else { $selected_id = head_key($ids); } foreach ($mock->getImages() as $image) { $file = $image->getFile(); $metadata = $file->getMetadata(); $x = idx($metadata, PhabricatorFile::METADATA_IMAGE_WIDTH); $y = idx($metadata, PhabricatorFile::METADATA_IMAGE_HEIGHT); $images[] = array( 'id' => $image->getID(), 'fullURI' => $image->getFile()->getBestURI(), 'pageURI' => '/M'.$mock->getID().'/'.$image->getID().'/', 'width' => $x, 'height' => $y, - 'title' => $file->getName(), - 'desc' => 'Lorem ipsum dolor sit amet: there is no way to set any '. - 'descriptive text yet; were there, it would appear here.', + 'title' => $image->getName(), + 'desc' => $image->getDescription(), ); } $login_uri = id(new PhutilURI('/login/')) ->setQueryParam('next', (string) $this->getRequestURI()); $config = array( 'mockID' => $mock->getID(), 'panelID' => $panel_id, 'viewportID' => $viewport_id, 'commentFormID' => $this->getCommentFormID(), 'images' => $images, 'selectedID' => $selected_id, 'loggedIn' => $this->getUser()->isLoggedIn(), 'logInLink' => (string) $login_uri ); Javelin::initBehavior('pholio-mock-view', $config); $mockview = ''; $mock_wrapper = javelin_tag( 'div', array( 'id' => $viewport_id, 'sigil' => 'mock-viewport', 'class' => 'pholio-mock-image-viewport' ), ''); $mock_wrapper = javelin_tag( 'div', array( 'id' => $panel_id, 'sigil' => 'mock-panel touchable', 'class' => 'pholio-mock-image-panel', ), $mock_wrapper); $inline_comments_holder = javelin_tag( 'div', array( 'id' => 'mock-inline-comments', 'sigil' => 'mock-inline-comments', 'class' => 'pholio-mock-inline-comments' ), ''); $carousel_holder = ''; if (count($mock->getImages()) > 0) { $thumbnails = array(); foreach ($mock->getImages() as $image) { $thumbfile = $image->getFile(); $dimensions = PhabricatorImageTransformer::getPreviewDimensions( $thumbfile, 140); $tag = phutil_tag( 'img', array( 'width' => $dimensions['sdx'], 'height' => $dimensions['sdy'], 'src' => $thumbfile->getPreview140URI(), 'class' => 'pholio-mock-carousel-thumbnail', 'style' => 'top: '.floor((140 - $dimensions['sdy'] ) / 2).'px', )); $thumbnails[] = javelin_tag( 'a', array( 'sigil' => 'mock-thumbnail', 'class' => 'pholio-mock-carousel-thumb-item', 'href' => '/M'.$mock->getID().'/'.$image->getID().'/', 'meta' => array( 'imageID' => $image->getID(), ), ), $tag); } $carousel_holder = phutil_tag( 'div', array( 'id' => 'pholio-mock-carousel', 'class' => 'pholio-mock-carousel', ), $thumbnails); } $mockview[] = phutil_tag( 'div', array( 'class' => 'pholio-mock-image-container', 'id' => 'pholio-mock-image-container' ), array($mock_wrapper, $carousel_holder, $inline_comments_holder)); return $mockview; } }