コード例 #1
0
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getUser();
     $file = PhabricatorFile::initializeNewFile();
     $e_file = true;
     $errors = array();
     if ($request->isFormPost()) {
         $view_policy = $request->getStr('viewPolicy');
         if (!$request->getFileExists('file')) {
             $e_file = pht('Required');
             $errors[] = pht('You must select a file to upload.');
         } else {
             $file = PhabricatorFile::newFromPHPUpload(idx($_FILES, 'file'), array('name' => $request->getStr('name'), 'authorPHID' => $viewer->getPHID(), 'viewPolicy' => $view_policy, 'isExplicitUpload' => true));
         }
         if (!$errors) {
             return id(new AphrontRedirectResponse())->setURI($file->getInfoURI());
         }
         $file->setViewPolicy($view_policy);
     }
     $support_id = celerity_generate_unique_node_id();
     $instructions = id(new AphrontFormMarkupControl())->setControlID($support_id)->setControlStyle('display: none')->setValue(hsprintf('<br /><br /><strong>%s</strong> %s<br /><br />', pht('Drag and Drop:'), pht('You can also upload files by dragging and dropping them from your ' . 'desktop onto this page or the Phabricator home page.')));
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($file)->execute();
     $form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setLabel(pht('File'))->setName('file')->setError($e_file))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Name'))->setName('name')->setValue($request->getStr('name')))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setCapability(PhabricatorPolicyCapability::CAN_VIEW)->setPolicyObject($file)->setPolicies($policies)->setName('viewPolicy'))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Upload'))->addCancelButton('/file/'))->appendChild($instructions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Upload'), $request->getRequestURI());
     $crumbs->setBorder(true);
     $title = pht('Upload File');
     $global_upload = id(new PhabricatorGlobalUploadTargetView())->setUser($viewer)->setShowIfSupportedID($support_id);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('File'))->setFormErrors($errors)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon('fa-upload');
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($form_box, $global_upload));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function processRequest()
 {
     // No CSRF for SendGrid.
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     $request = $this->getRequest();
     $user = $request->getUser();
     $raw_headers = $request->getStr('headers');
     $raw_headers = explode("\n", rtrim($raw_headers));
     $raw_dict = array();
     foreach (array_filter($raw_headers) as $header) {
         list($name, $value) = explode(':', $header, 2);
         $raw_dict[$name] = ltrim($value);
     }
     $headers = array('to' => $request->getStr('to'), 'from' => $request->getStr('from'), 'subject' => $request->getStr('subject')) + $raw_dict;
     $received = new PhabricatorMetaMTAReceivedMail();
     $received->setHeaders($headers);
     $received->setBodies(array('text' => $request->getStr('text'), 'html' => $request->getStr('from')));
     $file_phids = array();
     foreach ($_FILES as $file_raw) {
         try {
             $file = PhabricatorFile::newFromPHPUpload($file_raw, array('authorPHID' => $user->getPHID()));
             $file_phids[] = $file->getPHID();
         } catch (Exception $ex) {
             phlog($ex);
         }
     }
     $received->setAttachments($file_phids);
     $received->save();
     $received->processReceivedMail();
     $response = new AphrontWebpageResponse();
     $response->setContent("Got it! Thanks, SendGrid!\n");
     return $response;
 }
コード例 #3
0
 public function readRequest(PhabricatorConfigOption $option, AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $view_policy = PhabricatorPolicies::POLICY_PUBLIC;
     if ($request->getBool('removeLogo')) {
         $logo_image_phid = null;
     } else {
         if ($request->getFileExists('logoImage')) {
             $logo_image = PhabricatorFile::newFromPHPUpload(idx($_FILES, 'logoImage'), array('name' => 'logo', 'authorPHID' => $viewer->getPHID(), 'viewPolicy' => $view_policy, 'canCDN' => true, 'isExplicitUpload' => true));
             $logo_image_phid = $logo_image->getPHID();
         } else {
             $logo_image_phid = self::getLogoImagePHID();
         }
     }
     $wordmark_text = $request->getStr('wordmarkText');
     $value = array('logoImagePHID' => $logo_image_phid, 'wordmarkText' => $wordmark_text);
     $errors = array();
     $e_value = null;
     try {
         $this->validateOption($option, $value);
     } catch (Exception $ex) {
         $e_value = pht('Invalid');
         $errors[] = $ex->getMessage();
         $value = array();
     }
     return array($e_value, $errors, $value, phutil_json_encode($value));
 }
 public function handleRequest(AphrontRequest $request)
 {
     // No CSRF for Mailgun.
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     if (!$this->verifyMessage()) {
         throw new Exception(pht('Mail signature is not valid. Check your Mailgun API key.'));
     }
     $user = $request->getUser();
     $raw_headers = $request->getStr('headers');
     $raw_headers = explode("\n", rtrim($raw_headers));
     $raw_dict = array();
     foreach (array_filter($raw_headers) as $header) {
         list($name, $value) = explode(':', $header, 2);
         $raw_dict[$name] = ltrim($value);
     }
     $headers = array('to' => $request->getStr('recipient'), 'from' => $request->getStr('from'), 'subject' => $request->getStr('subject')) + $raw_dict;
     $received = new PhabricatorMetaMTAReceivedMail();
     $received->setHeaders($headers);
     $received->setBodies(array('text' => $request->getStr('stripped-text'), 'html' => $request->getStr('stripped-html')));
     $file_phids = array();
     foreach ($_FILES as $file_raw) {
         try {
             $file = PhabricatorFile::newFromPHPUpload($file_raw, array('viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
             $file_phids[] = $file->getPHID();
         } catch (Exception $ex) {
             phlog($ex);
         }
     }
     $received->setAttachments($file_phids);
     $received->save();
     $received->processReceivedMail();
     $response = new AphrontWebpageResponse();
     $response->setContent(pht("Got it! Thanks, Mailgun!\n"));
     return $response;
 }
コード例 #5
0
 public function processRequest()
 {
     if ($this->id) {
         $macro = id(new PhabricatorFileImageMacro())->load($this->id);
         if (!$macro) {
             return new Aphront404Response();
         }
     } else {
         $macro = new PhabricatorFileImageMacro();
     }
     $errors = array();
     $e_name = true;
     $request = $this->getRequest();
     $user = $request->getUser();
     if ($request->isFormPost()) {
         $macro->setName($request->getStr('name'));
         if (!strlen($macro->getName())) {
             $errors[] = 'Macro name is required.';
             $e_name = 'Required';
         } else {
             if (!preg_match('/^[a-z0-9_-]{3,}$/', $macro->getName())) {
                 $errors[] = 'Macro must be at least three characters long and contain ' . 'only lowercase letters, digits, hyphen and underscore.';
                 $e_name = 'Invalid';
             } else {
                 $e_name = null;
             }
         }
         if (!$errors) {
             $file = PhabricatorFile::newFromPHPUpload(idx($_FILES, 'file'), array('name' => $request->getStr('name'), 'authorPHID' => $user->getPHID()));
             $macro->setFilePHID($file->getPHID());
             try {
                 $macro->save();
                 return id(new AphrontRedirectResponse())->setURI('/file/macro/');
             } catch (AphrontQueryDuplicateKeyException $ex) {
                 $errors[] = 'Macro name is not unique!';
                 $e_name = 'Duplicate';
             }
         }
     }
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     } else {
         $error_view = null;
     }
     $form = new AphrontFormView();
     $form->setAction('/file/macro/edit/');
     $form->setUser($request->getUser());
     $form->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel('Name')->setName('name')->setValue($macro->getName())->setCaption('This word or phrase will be replaced with the image.')->setError($e_name))->appendChild(id(new AphrontFormFileControl())->setLabel('File')->setName('file')->setError(true))->appendChild(id(new AphrontFormSubmitControl())->setValue('Save Image Macro')->addCancelButton('/file/macro/'));
     $panel = new AphrontPanelView();
     if ($macro->getID()) {
         $panel->setHeader('Edit Image Macro');
     } else {
         $panel->setHeader('Create Image Macro');
     }
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Edit Image Macro'));
 }
コード例 #6
0
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $this->requireApplicationCapability(PhabricatorMacroManageCapability::CAPABILITY);
     $macro = id(new PhabricatorMacroQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW))->withIDs(array($id))->executeOne();
     if (!$macro) {
         return new Aphront404Response();
     }
     $errors = array();
     $view_uri = $this->getApplicationURI('/view/' . $macro->getID() . '/');
     $e_file = null;
     $file = null;
     if ($request->isFormPost()) {
         $xactions = array();
         if ($request->getBool('behaviorForm')) {
             $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransaction::TYPE_AUDIO_BEHAVIOR)->setNewValue($request->getStr('audioBehavior'));
         } else {
             $file = null;
             if ($request->getFileExists('file')) {
                 $file = PhabricatorFile::newFromPHPUpload($_FILES['file'], array('name' => $request->getStr('name'), 'authorPHID' => $viewer->getPHID(), 'isExplicitUpload' => true));
             }
             if ($file) {
                 if (!$file->isAudio()) {
                     $errors[] = pht('You must upload audio.');
                     $e_file = pht('Invalid');
                 } else {
                     $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransaction::TYPE_AUDIO)->setNewValue($file->getPHID());
                 }
             } else {
                 $errors[] = pht('You must upload an audio file.');
                 $e_file = pht('Required');
             }
         }
         if (!$errors) {
             id(new PhabricatorMacroEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request)->applyTransactions($macro, $xactions);
             return id(new AphrontRedirectResponse())->setURI($view_uri);
         }
     }
     $form = id(new AphrontFormView())->addHiddenInput('behaviorForm', 1)->setUser($viewer);
     $options = id(new AphrontFormRadioButtonControl())->setLabel(pht('Audio Behavior'))->setName('audioBehavior')->setValue(nonempty($macro->getAudioBehavior(), PhabricatorFileImageMacro::AUDIO_BEHAVIOR_NONE));
     $options->addButton(PhabricatorFileImageMacro::AUDIO_BEHAVIOR_NONE, pht('Do Not Play'), pht('Do not play audio.'));
     $options->addButton(PhabricatorFileImageMacro::AUDIO_BEHAVIOR_ONCE, pht('Play Once'), pht('Play audio once, when the viewer looks at the macro.'));
     $options->addButton(PhabricatorFileImageMacro::AUDIO_BEHAVIOR_LOOP, pht('Play Continuously'), pht('Play audio continuously, treating the macro as an audio source. ' . 'Best for ambient sounds.'));
     $form->appendChild($options);
     $form->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Audio Behavior'))->addCancelButton($view_uri));
     $crumbs = $this->buildApplicationCrumbs();
     $title = pht('Edit Audio: %s', $macro->getName());
     $crumb = pht('Edit Audio');
     $crumbs->addTextCrumb(pht('Macro "%s"', $macro->getName()), $view_uri);
     $crumbs->addTextCrumb($crumb, $request->getRequestURI());
     $crumbs->setBorder(true);
     $upload_form = id(new AphrontFormView())->setEncType('multipart/form-data')->setUser($viewer)->appendChild(id(new AphrontFormFileControl())->setLabel(pht('Audio File'))->setName('file'))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Upload File')));
     $upload = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Audio'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($upload_form);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Behavior'))->setFormErrors($errors)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon('fa-pencil');
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($form_box, $upload));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
コード例 #7
0
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $blog = id(new PhameBlogQuery())->setViewer($viewer)->withIDs(array($id))->needHeaderImage(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$blog) {
         return new Aphront404Response();
     }
     $blog_uri = '/phame/blog/manage/' . $id;
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_file = true;
     $errors = array();
     $delete_header = $request->getInt('delete') == 1;
     if ($request->isFormPost()) {
         if ($request->getFileExists('header')) {
             $file = PhabricatorFile::newFromPHPUpload($_FILES['header'], array('authorPHID' => $viewer->getPHID(), 'canCDN' => true));
         } else {
             if (!$delete_header) {
                 $e_file = pht('Required');
                 $errors[] = pht('You must choose a file when uploading a new blog header.');
             }
         }
         if (!$errors && !$delete_header) {
             if (!$file->isTransformableImage()) {
                 $e_file = pht('Not Supported');
                 $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats));
             }
         }
         if (!$errors) {
             if ($delete_header) {
                 $new_value = null;
             } else {
                 $file->attachToObject($blog->getPHID());
                 $new_value = $file->getPHID();
             }
             $xactions = array();
             $xactions[] = id(new PhameBlogTransaction())->setTransactionType(PhameBlogTransaction::TYPE_HEADERIMAGE)->setNewValue($new_value);
             $editor = id(new PhameBlogEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true);
             $editor->applyTransactions($blog, $xactions);
             return id(new AphrontRedirectResponse())->setURI($blog_uri);
         }
     }
     $title = pht('Edit Blog Header');
     $upload_form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setName('header')->setLabel(pht('Upload Header'))->setError($e_file)->setCaption(pht('Supported formats: %s', implode(', ', $supported_formats))))->appendChild(id(new AphrontFormCheckboxControl())->setName('delete')->setLabel(pht('Delete Header'))->addCheckbox('delete', 1, null, null))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($blog_uri)->setValue(pht('Upload Header')));
     $upload_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Header'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($upload_form);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Blogs'), $this->getApplicationURI('blog/'));
     $crumbs->addTextCrumb($blog->getName(), $this->getApplicationURI('blog/view/' . $id));
     $crumbs->addTextCrumb(pht('Blog Header'));
     $crumbs->setBorder(true);
     $header = id(new PHUIHeaderView())->setHeader(pht('Edit Blog Header'))->setHeaderIcon('fa-camera');
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($upload_box));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($view));
 }
コード例 #8
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     if ($request->isFormPost()) {
         $file = PhabricatorFile::newFromPHPUpload(idx($_FILES, 'file'), array('name' => $request->getStr('name'), 'authorPHID' => $user->getPHID()));
         return id(new AphrontRedirectResponse())->setURI($file->getBestURI());
     }
     $panel = new PhabricatorFileUploadView();
     $panel->setUser($user);
     return $this->buildStandardPageResponse(array($panel), array('title' => 'Upload File'));
 }
 public function handleRequest(AphrontRequest $request)
 {
     // No CSRF for Mailgun.
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     if (!$this->verifyMessage()) {
         throw new Exception(pht('Mail signature is not valid. Check your Mailgun API key.'));
     }
     $raw_headers = $request->getStr('message-headers');
     $raw_dict = array();
     if (strlen($raw_headers)) {
         $raw_headers = phutil_json_decode($raw_headers);
         foreach ($raw_headers as $raw_header) {
             list($name, $value) = $raw_header;
             $raw_dict[$name] = $value;
         }
     }
     $headers = array('to' => $request->getStr('recipient'), 'from' => $request->getStr('from'), 'subject' => $request->getStr('subject')) + $raw_dict;
     $received = new PhabricatorMetaMTAReceivedMail();
     $received->setHeaders($headers);
     $received->setBodies(array('text' => $request->getStr('stripped-text'), 'html' => $request->getStr('stripped-html')));
     $file_phids = array();
     foreach ($_FILES as $file_raw) {
         try {
             $file = PhabricatorFile::newFromPHPUpload($file_raw, array('viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
             $file_phids[] = $file->getPHID();
         } catch (Exception $ex) {
             phlog($ex);
         }
     }
     $received->setAttachments($file_phids);
     try {
         $received->save();
         $received->processReceivedMail();
     } catch (Exception $ex) {
         // We can get exceptions here in two cases.
         // First, saving the message may throw if we have already received a
         // message with the same Message ID. In this case, we're declining to
         // process a duplicate message, so failing silently is correct.
         // Second, processing the message may throw (for example, if it contains
         // an invalid !command). This will generate an email as a side effect,
         // so we don't need to explicitly handle the exception here.
         // In these cases, we want to return HTTP 200. If we do not, MailGun will
         // re-transmit the message later.
         phlog($ex);
     }
     $response = new AphrontWebpageResponse();
     $response->setContent(pht("Got it! Thanks, Mailgun!\n"));
     return $response;
 }
コード例 #10
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     if ($request->isFormPost()) {
         $file = PhabricatorFile::newFromPHPUpload(idx($_FILES, 'file'), array('name' => $request->getStr('name'), 'authorPHID' => $user->getPHID()));
         return id(new AphrontRedirectResponse())->setURI($file->getBestURI());
     }
     $form = new AphrontFormView();
     $form->setAction('/file/upload/');
     $form->setUser($request->getUser());
     $form->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setLabel('File')->setName('file')->setError(true))->appendChild(id(new AphrontFormTextControl())->setLabel('Name')->setName('name')->setCaption('Optional file display name.'))->appendChild(id(new AphrontFormSubmitControl())->setValue('Upload')->addCancelButton('/file/'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Upload File');
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     return $this->buildStandardPageResponse(array($panel), array('title' => 'Upload File'));
 }
コード例 #11
0
 protected function getParameterValue(AphrontRequest $request, $key)
 {
     $value = $request->getStrList($key);
     if ($value) {
         return head($value);
     }
     // NOTE: At least for now, we'll attempt to read a direct upload if we
     // miss on a PHID. Currently, PHUIFormFileControl does a client-side
     // upload on workflow forms (which is good) but doesn't have a hook for
     // non-workflow forms (which isn't as good). Giving it a hook is desirable,
     // but complicated. Even if we do hook it, it may be reasonable to keep
     // this code around as a fallback if the client-side JS goes awry.
     $file_key = $this->getFileKey($key);
     if (!$request->getFileExists($file_key)) {
         return null;
     }
     $viewer = $this->getViewer();
     $file = PhabricatorFile::newFromPHPUpload(idx($_FILES, $file_key), array('authorPHID' => $viewer->getPHID(), 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
     return $file->getPHID();
 }
コード例 #12
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($this->id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$project) {
         return new Aphront404Response();
     }
     $edit_uri = $this->getApplicationURI('edit/' . $project->getID() . '/');
     $view_uri = $this->getApplicationURI('view/' . $project->getID() . '/');
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_file = true;
     $errors = array();
     if ($request->isFormPost()) {
         $phid = $request->getStr('phid');
         $is_default = false;
         if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
             $phid = null;
             $is_default = true;
         } else {
             if ($phid) {
                 $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
             } else {
                 if ($request->getFileExists('picture')) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['picture'], array('authorPHID' => $viewer->getPHID(), 'canCDN' => true));
                 } else {
                     $e_file = pht('Required');
                     $errors[] = pht('You must choose a file when uploading a new project picture.');
                 }
             }
         }
         if (!$errors && !$is_default) {
             if (!$file->isTransformableImage()) {
                 $e_file = pht('Not Supported');
                 $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats));
             } else {
                 $xformer = new PhabricatorImageTransformer();
                 $xformed = $xformer->executeProfileTransform($file, $width = 50, $min_height = 50, $max_height = 50);
             }
         }
         if (!$errors) {
             if ($is_default) {
                 $new_value = null;
             } else {
                 $new_value = $xformed->getPHID();
             }
             $xactions = array();
             $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorProjectTransaction::TYPE_IMAGE)->setNewValue($new_value);
             $editor = id(new PhabricatorProjectTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true);
             $editor->applyTransactions($project, $xactions);
             return id(new AphrontRedirectResponse())->setURI($edit_uri);
         }
     }
     $title = pht('Edit Project Picture');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($project->getName(), $view_uri);
     $crumbs->addTextCrumb(pht('Edit'), $edit_uri);
     $crumbs->addTextCrumb(pht('Picture'));
     $form = id(new PHUIFormLayoutView())->setUser($viewer);
     $default_image = PhabricatorFile::loadBuiltin($viewer, 'project.png');
     $images = array();
     $current = $project->getProfileImagePHID();
     $has_current = false;
     if ($current) {
         $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($current))->execute();
         if ($files) {
             $file = head($files);
             if ($file->isTransformableImage()) {
                 $has_current = true;
                 $images[$current] = array('uri' => $file->getBestURI(), 'tip' => pht('Current Picture'));
             }
         }
     }
     $images[PhabricatorPHIDConstants::PHID_VOID] = array('uri' => $default_image->getBestURI(), 'tip' => pht('Default Picture'));
     require_celerity_resource('people-profile-css');
     Javelin::initBehavior('phabricator-tooltips', array());
     $buttons = array();
     foreach ($images as $phid => $spec) {
         $button = javelin_tag('button', array('class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array('tip' => $spec['tip'], 'size' => 300)), phutil_tag('img', array('height' => 50, 'width' => 50, 'src' => $spec['uri'])));
         $button = array(phutil_tag('input', array('type' => 'hidden', 'name' => 'phid', 'value' => $phid)), $button);
         $button = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST'), $button);
         $buttons[] = $button;
     }
     if ($has_current) {
         $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Current Picture'))->setValue(array_shift($buttons)));
     }
     $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Use Picture'))->setValue($buttons));
     $launch_id = celerity_generate_unique_node_id();
     $input_id = celerity_generate_unique_node_id();
     Javelin::initBehavior('launch-icon-composer', array('launchID' => $launch_id, 'inputID' => $input_id));
     $compose_button = javelin_tag('button', array('class' => 'grey', 'id' => $launch_id, 'sigil' => 'icon-composer'), pht('Choose Icon and Color...'));
     $compose_input = javelin_tag('input', array('type' => 'hidden', 'id' => $input_id, 'name' => 'phid'));
     $compose_form = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST'), array($compose_input, $compose_button));
     $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Quick Create'))->setValue($compose_form));
     $upload_form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setName('picture')->setLabel(pht('Upload Picture'))->setError($e_file)->setCaption(pht('Supported formats: %s', implode(', ', $supported_formats))))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($edit_uri)->setValue(pht('Upload Picture')));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     $upload_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Picture'))->setForm($upload_form);
     return $this->buildApplicationPage(array($crumbs, $form_box, $upload_box), array('title' => $title));
 }
コード例 #13
0
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $conpherence = id(new ConpherenceThreadQuery())->setViewer($viewer)->withIDs(array($id))->needProfileImage(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$conpherence) {
         return new Aphront404Response();
     }
     $monogram = $conpherence->getMonogram();
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_file = true;
     $errors = array();
     if ($request->isFormPost()) {
         $phid = $request->getStr('phid');
         $is_default = false;
         if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
             $phid = null;
             $is_default = true;
         } else {
             if ($phid) {
                 $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
             } else {
                 if ($request->getFileExists('picture')) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['picture'], array('authorPHID' => $viewer->getPHID(), 'canCDN' => true));
                 } else {
                     $e_file = pht('Required');
                     $errors[] = pht('You must choose a file when uploading a new room picture.');
                 }
             }
         }
         if (!$errors && !$is_default) {
             if (!$file->isTransformableImage()) {
                 $e_file = pht('Not Supported');
                 $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats));
             } else {
                 $xform = PhabricatorFileTransform::getTransformByKey(PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE);
                 $xformed = $xform->executeTransform($file);
             }
         }
         if (!$errors) {
             if ($is_default) {
                 $new_value = null;
             } else {
                 $xformed->attachToObject($conpherence->getPHID());
                 $new_value = $xformed->getPHID();
             }
             $xactions = array();
             $xactions[] = id(new ConpherenceTransaction())->setTransactionType(ConpherenceTransaction::TYPE_PICTURE)->setNewValue($new_value);
             $editor = id(new ConpherenceEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true);
             $editor->applyTransactions($conpherence, $xactions);
             return id(new AphrontRedirectResponse())->setURI('/' . $monogram);
         }
     }
     $title = pht('Edit Room Picture');
     $form = id(new PHUIFormLayoutView())->setUser($viewer);
     $default_image = PhabricatorFile::loadBuiltin($viewer, 'conpherence.png');
     $images = array();
     $current = $conpherence->getProfileImagePHID();
     $has_current = false;
     if ($current) {
         $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($current))->executeOne();
         if ($file) {
             if ($file->isTransformableImage()) {
                 $has_current = true;
                 $images[$current] = array('uri' => $file->getBestURI(), 'tip' => pht('Current Picture'));
             }
         }
     }
     $images[PhabricatorPHIDConstants::PHID_VOID] = array('uri' => $default_image->getBestURI(), 'tip' => pht('Default Picture'));
     require_celerity_resource('people-profile-css');
     Javelin::initBehavior('phabricator-tooltips', array());
     $buttons = array();
     foreach ($images as $phid => $spec) {
         $button = javelin_tag('button', array('class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array('tip' => $spec['tip'], 'size' => 300)), phutil_tag('img', array('height' => 50, 'width' => 50, 'src' => $spec['uri'])));
         $button = array(phutil_tag('input', array('type' => 'hidden', 'name' => 'phid', 'value' => $phid)), $button);
         $button = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST'), $button);
         $buttons[] = $button;
     }
     if ($has_current) {
         $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Current Picture'))->setValue(array_shift($buttons)));
     }
     $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Use Picture'))->setValue($buttons));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $upload_form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setName('picture')->setLabel(pht('Upload Picture'))->setError($e_file)->setCaption(pht('Supported formats: %s', implode(', ', $supported_formats))))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton('/' . $monogram)->setValue(pht('Upload Picture')));
     $upload_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Picture'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($upload_form);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($conpherence->getTitle(), '/' . $monogram);
     $crumbs->addTextCrumb(pht('Room Picture'));
     $crumbs->setBorder(true);
     $header = id(new PHUIHeaderView())->setHeader(pht('Edit Room Picture'))->setHeaderIcon('fa-camera');
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($form_box, $upload_box));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($view));
 }
コード例 #14
0
 public function processRequest()
 {
     $this->requireApplicationCapability(PhabricatorMacroManageCapability::CAPABILITY);
     $request = $this->getRequest();
     $user = $request->getUser();
     if ($this->id) {
         $macro = id(new PhabricatorMacroQuery())->setViewer($user)->withIDs(array($this->id))->needFiles(true)->executeOne();
         if (!$macro) {
             return new Aphront404Response();
         }
     } else {
         $macro = new PhabricatorFileImageMacro();
         $macro->setAuthorPHID($user->getPHID());
     }
     $errors = array();
     $e_name = true;
     $e_file = null;
     $file = null;
     $can_fetch = PhabricatorEnv::getEnvConfig('security.allow-outbound-http');
     if ($request->isFormPost()) {
         $original = clone $macro;
         $new_name = null;
         if ($request->getBool('name_form') || !$macro->getID()) {
             $new_name = $request->getStr('name');
             $macro->setName($new_name);
             if (!strlen($macro->getName())) {
                 $errors[] = pht('Macro name is required.');
                 $e_name = pht('Required');
             } else {
                 if (!preg_match('/^[a-z0-9:_-]{3,}\\z/', $macro->getName())) {
                     $errors[] = pht('Macro must be at least three characters long and contain only ' . 'lowercase letters, digits, hyphens, colons and underscores.');
                     $e_name = pht('Invalid');
                 } else {
                     $e_name = null;
                 }
             }
         }
         $file = null;
         if ($request->getFileExists('file')) {
             $file = PhabricatorFile::newFromPHPUpload($_FILES['file'], array('name' => $request->getStr('name'), 'authorPHID' => $user->getPHID(), 'isExplicitUpload' => true, 'canCDN' => true));
         } else {
             if ($request->getStr('url')) {
                 try {
                     $file = PhabricatorFile::newFromFileDownload($request->getStr('url'), array('name' => $request->getStr('name'), 'authorPHID' => $user->getPHID(), 'isExplicitUpload' => true, 'canCDN' => true));
                 } catch (Exception $ex) {
                     $errors[] = pht('Could not fetch URL: %s', $ex->getMessage());
                 }
             } else {
                 if ($request->getStr('phid')) {
                     $file = id(new PhabricatorFileQuery())->setViewer($user)->withPHIDs(array($request->getStr('phid')))->executeOne();
                 }
             }
         }
         if ($file) {
             if (!$file->isViewableInBrowser()) {
                 $errors[] = pht('You must upload an image.');
                 $e_file = pht('Invalid');
             } else {
                 $macro->setFilePHID($file->getPHID());
                 $macro->attachFile($file);
                 $e_file = null;
             }
         }
         if (!$macro->getID() && !$file) {
             $errors[] = pht('You must upload an image to create a macro.');
             $e_file = pht('Required');
         }
         if (!$errors) {
             try {
                 $xactions = array();
                 if ($new_name !== null) {
                     $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransactionType::TYPE_NAME)->setNewValue($new_name);
                 }
                 if ($file) {
                     $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransactionType::TYPE_FILE)->setNewValue($file->getPHID());
                 }
                 $editor = id(new PhabricatorMacroEditor())->setActor($user)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
                 $xactions = $editor->applyTransactions($original, $xactions);
                 $view_uri = $this->getApplicationURI('/view/' . $original->getID() . '/');
                 return id(new AphrontRedirectResponse())->setURI($view_uri);
             } catch (AphrontDuplicateKeyQueryException $ex) {
                 throw $ex;
                 $errors[] = pht('Macro name is not unique!');
                 $e_name = pht('Duplicate');
             }
         }
     }
     $current_file = null;
     if ($macro->getFilePHID()) {
         $current_file = $macro->getFile();
     }
     $form = new AphrontFormView();
     $form->addHiddenInput('name_form', 1);
     $form->setUser($request->getUser());
     $form->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Name'))->setName('name')->setValue($macro->getName())->setCaption(pht('This word or phrase will be replaced with the image.'))->setError($e_name));
     if (!$macro->getID()) {
         if ($current_file) {
             $current_file_view = id(new PhabricatorFileLinkView())->setFilePHID($current_file->getPHID())->setFileName($current_file->getName())->setFileViewable(true)->setFileViewURI($current_file->getBestURI())->render();
             $form->addHiddenInput('phid', $current_file->getPHID());
             $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Selected File'))->setValue($current_file_view));
             $other_label = pht('Change File');
         } else {
             $other_label = pht('File');
         }
         if ($can_fetch) {
             $form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('URL'))->setName('url')->setValue($request->getStr('url'))->setError($request->getFileExists('file') ? false : $e_file));
         }
         $form->appendChild(id(new AphrontFormFileControl())->setLabel($other_label)->setName('file')->setError($request->getStr('url') ? false : $e_file));
     }
     $view_uri = $this->getApplicationURI('/view/' . $macro->getID() . '/');
     if ($macro->getID()) {
         $cancel_uri = $view_uri;
     } else {
         $cancel_uri = $this->getApplicationURI();
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Image Macro'))->addCancelButton($cancel_uri));
     $crumbs = $this->buildApplicationCrumbs();
     if ($macro->getID()) {
         $title = pht('Edit Image Macro');
         $crumb = pht('Edit Macro');
         $crumbs->addTextCrumb(pht('Macro "%s"', $macro->getName()), $view_uri);
     } else {
         $title = pht('Create Image Macro');
         $crumb = pht('Create Macro');
     }
     $crumbs->addTextCrumb($crumb, $request->getRequestURI());
     $upload = null;
     if ($macro->getID()) {
         $upload_form = id(new AphrontFormView())->setEncType('multipart/form-data')->setUser($request->getUser());
         if ($can_fetch) {
             $upload_form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('URL'))->setName('url')->setValue($request->getStr('url')));
         }
         $upload_form->appendChild(id(new AphrontFormFileControl())->setLabel(pht('File'))->setName('file'))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Upload File')));
         $upload = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New File'))->setForm($upload_form);
     }
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box, $upload), array('title' => $title));
 }
コード例 #15
0
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $this->requireApplicationCapability(PhabricatorMacroManageCapability::CAPABILITY);
     if ($id) {
         $macro = id(new PhabricatorMacroQuery())->setViewer($viewer)->withIDs(array($id))->needFiles(true)->executeOne();
         if (!$macro) {
             return new Aphront404Response();
         }
     } else {
         $macro = new PhabricatorFileImageMacro();
         $macro->setAuthorPHID($viewer->getPHID());
     }
     $errors = array();
     $e_name = true;
     $e_file = null;
     $file = null;
     if ($request->isFormPost()) {
         $original = clone $macro;
         $new_name = null;
         if ($request->getBool('name_form') || !$macro->getID()) {
             $new_name = $request->getStr('name');
             $macro->setName($new_name);
             if (!strlen($macro->getName())) {
                 $errors[] = pht('Macro name is required.');
                 $e_name = pht('Required');
             } else {
                 if (!preg_match('/^[a-z0-9:_-]{3,}\\z/', $macro->getName())) {
                     $errors[] = pht('Macro must be at least three characters long and contain only ' . 'lowercase letters, digits, hyphens, colons and underscores.');
                     $e_name = pht('Invalid');
                 } else {
                     $e_name = null;
                 }
             }
         }
         $uri = $request->getStr('url');
         $engine = new PhabricatorDestructionEngine();
         $file = null;
         if ($request->getFileExists('file')) {
             $file = PhabricatorFile::newFromPHPUpload($_FILES['file'], array('name' => $request->getStr('name'), 'authorPHID' => $viewer->getPHID(), 'isExplicitUpload' => true, 'canCDN' => true));
         } else {
             if ($uri) {
                 try {
                     // Rate limit outbound fetches to make this mechanism less useful for
                     // scanning networks and ports.
                     PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorFilesOutboundRequestAction(), 1);
                     $file = PhabricatorFile::newFromFileDownload($uri, array('name' => $request->getStr('name'), 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, 'isExplicitUpload' => true, 'canCDN' => true));
                     if (!$file->isViewableInBrowser()) {
                         $mime_type = $file->getMimeType();
                         $engine->destroyObject($file);
                         $file = null;
                         throw new Exception(pht('The URI "%s" does not correspond to a valid image file, got ' . 'a file with MIME type "%s". You must specify the URI of a ' . 'valid image file.', $uri, $mime_type));
                     } else {
                         $file->setAuthorPHID($viewer->getPHID())->save();
                     }
                 } catch (HTTPFutureHTTPResponseStatus $status) {
                     $errors[] = pht('The URI "%s" could not be loaded, got %s error.', $uri, $status->getStatusCode());
                 } catch (Exception $ex) {
                     $errors[] = $ex->getMessage();
                 }
             } else {
                 if ($request->getStr('phid')) {
                     $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($request->getStr('phid')))->executeOne();
                 }
             }
         }
         if ($file) {
             if (!$file->isViewableInBrowser()) {
                 $errors[] = pht('You must upload an image.');
                 $e_file = pht('Invalid');
             } else {
                 $macro->setFilePHID($file->getPHID());
                 $macro->attachFile($file);
                 $e_file = null;
             }
         }
         if (!$macro->getID() && !$file) {
             $errors[] = pht('You must upload an image to create a macro.');
             $e_file = pht('Required');
         }
         if (!$errors) {
             try {
                 $xactions = array();
                 if ($new_name !== null) {
                     $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransaction::TYPE_NAME)->setNewValue($new_name);
                 }
                 if ($file) {
                     $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransaction::TYPE_FILE)->setNewValue($file->getPHID());
                 }
                 $editor = id(new PhabricatorMacroEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
                 $xactions = $editor->applyTransactions($original, $xactions);
                 $view_uri = $this->getApplicationURI('/view/' . $original->getID() . '/');
                 return id(new AphrontRedirectResponse())->setURI($view_uri);
             } catch (AphrontDuplicateKeyQueryException $ex) {
                 throw $ex;
                 $errors[] = pht('Macro name is not unique!');
                 $e_name = pht('Duplicate');
             }
         }
     }
     $current_file = null;
     if ($macro->getFilePHID()) {
         $current_file = $macro->getFile();
     }
     $form = new AphrontFormView();
     $form->addHiddenInput('name_form', 1);
     $form->setUser($request->getUser());
     $form->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Name'))->setName('name')->setValue($macro->getName())->setCaption(pht('This word or phrase will be replaced with the image.'))->setError($e_name));
     if (!$macro->getID()) {
         if ($current_file) {
             $current_file_view = id(new PhabricatorFileLinkView())->setFilePHID($current_file->getPHID())->setFileName($current_file->getName())->setFileViewable(true)->setFileViewURI($current_file->getBestURI())->render();
             $form->addHiddenInput('phid', $current_file->getPHID());
             $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Selected File'))->setValue($current_file_view));
             $other_label = pht('Change File');
         } else {
             $other_label = pht('File');
         }
         $form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('URL'))->setName('url')->setValue($request->getStr('url'))->setError($request->getFileExists('file') ? false : $e_file));
         $form->appendChild(id(new AphrontFormFileControl())->setLabel($other_label)->setName('file')->setError($request->getStr('url') ? false : $e_file));
     }
     $view_uri = $this->getApplicationURI('/view/' . $macro->getID() . '/');
     if ($macro->getID()) {
         $cancel_uri = $view_uri;
     } else {
         $cancel_uri = $this->getApplicationURI();
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Image Macro'))->addCancelButton($cancel_uri));
     $crumbs = $this->buildApplicationCrumbs();
     if ($macro->getID()) {
         $title = pht('Edit Image Macro');
         $crumb = pht('Edit Macro');
         $crumbs->addTextCrumb(pht('Macro "%s"', $macro->getName()), $view_uri);
     } else {
         $title = pht('Create Image Macro');
         $crumb = pht('Create Macro');
     }
     $crumbs->addTextCrumb($crumb, $request->getRequestURI());
     $upload = null;
     if ($macro->getID()) {
         $upload_form = id(new AphrontFormView())->setEncType('multipart/form-data')->setUser($request->getUser());
         $upload_form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('URL'))->setName('url')->setValue($request->getStr('url')));
         $upload_form->appendChild(id(new AphrontFormFileControl())->setLabel(pht('File'))->setName('file'))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Upload File')));
         $upload = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New File'))->setForm($upload_form);
     }
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box, $upload), array('title' => $title));
 }
コード例 #16
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $project = id(new PhabricatorProjectQuery())->setViewer($user)->withIDs(array($this->id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$project) {
         return new Aphront404Response();
     }
     $profile = $project->loadProfile();
     if (empty($profile)) {
         $profile = new PhabricatorProjectProfile();
     }
     $img_src = $profile->loadProfileImageURI();
     $options = PhabricatorProjectStatus::getStatusMap();
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_name = true;
     $e_image = null;
     $errors = array();
     if ($request->isFormPost()) {
         try {
             $xactions = array();
             $xaction = new PhabricatorProjectTransaction();
             $xaction->setTransactionType(PhabricatorProjectTransactionType::TYPE_NAME);
             $xaction->setNewValue($request->getStr('name'));
             $xactions[] = $xaction;
             $xaction = new PhabricatorProjectTransaction();
             $xaction->setTransactionType(PhabricatorProjectTransactionType::TYPE_STATUS);
             $xaction->setNewValue($request->getStr('status'));
             $xactions[] = $xaction;
             $xaction = new PhabricatorProjectTransaction();
             $xaction->setTransactionType(PhabricatorProjectTransactionType::TYPE_CAN_VIEW);
             $xaction->setNewValue($request->getStr('can_view'));
             $xactions[] = $xaction;
             $xaction = new PhabricatorProjectTransaction();
             $xaction->setTransactionType(PhabricatorProjectTransactionType::TYPE_CAN_EDIT);
             $xaction->setNewValue($request->getStr('can_edit'));
             $xactions[] = $xaction;
             $xaction = new PhabricatorProjectTransaction();
             $xaction->setTransactionType(PhabricatorProjectTransactionType::TYPE_CAN_JOIN);
             $xaction->setNewValue($request->getStr('can_join'));
             $xactions[] = $xaction;
             $editor = new PhabricatorProjectEditor($project);
             $editor->setUser($user);
             $editor->applyTransactions($xactions);
         } catch (PhabricatorProjectNameCollisionException $ex) {
             $e_name = 'Not Unique';
             $errors[] = $ex->getMessage();
         }
         $profile->setBlurb($request->getStr('blurb'));
         if (!strlen($project->getName())) {
             $e_name = 'Required';
             $errors[] = 'Project name is required.';
         } else {
             $e_name = null;
         }
         $default_image = $request->getExists('default_image');
         if ($default_image) {
             $profile->setProfileImagePHID(null);
         } else {
             if (!empty($_FILES['image'])) {
                 $err = idx($_FILES['image'], 'error');
                 if ($err != UPLOAD_ERR_NO_FILE) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['image'], array('authorPHID' => $user->getPHID()));
                     $okay = $file->isTransformableImage();
                     if ($okay) {
                         $xformer = new PhabricatorImageTransformer();
                         $xformed = $xformer->executeThumbTransform($file, $x = 50, $y = 50);
                         $profile->setProfileImagePHID($xformed->getPHID());
                     } else {
                         $e_image = 'Not Supported';
                         $errors[] = 'This server only supports these image formats: ' . implode(', ', $supported_formats) . '.';
                     }
                 }
             }
         }
         if (!$errors) {
             $project->save();
             $profile->setProjectPHID($project->getPHID());
             $profile->save();
             return id(new AphrontRedirectResponse())->setURI('/project/view/' . $project->getID() . '/');
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     }
     $header_name = 'Edit Project';
     $title = 'Edit Project';
     $action = '/project/edit/' . $project->getID() . '/';
     $policies = id(new PhabricatorPolicyQuery())->setViewer($user)->setObject($project)->execute();
     $form = new AphrontFormView();
     $form->setID('project-edit-form')->setUser($user)->setAction($action)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel('Name')->setName('name')->setValue($project->getName())->setError($e_name))->appendChild(id(new AphrontFormSelectControl())->setLabel('Project Status')->setName('status')->setOptions($options)->setValue($project->getStatus()))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Blurb')->setName('blurb')->setValue($profile->getBlurb()))->appendChild('<p class="aphront-form-instructions">NOTE: Policy settings are not ' . 'yet fully implemented. Some interfaces still ignore these settings, ' . 'particularly "Visible To".</p>')->appendChild(id(new AphrontFormPolicyControl())->setUser($user)->setName('can_view')->setCaption('Members can always view a project.')->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_VIEW))->appendChild(id(new AphrontFormPolicyControl())->setUser($user)->setName('can_edit')->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_EDIT))->appendChild(id(new AphrontFormPolicyControl())->setUser($user)->setName('can_join')->setCaption('Users who can edit a project can always join a project.')->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_JOIN))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Profile Image')->setValue(phutil_render_tag('img', array('src' => $img_src))))->appendChild(id(new AphrontFormImageControl())->setLabel('Change Image')->setName('image')->setError($e_image)->setCaption('Supported formats: ' . implode(', ', $supported_formats)))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton('/project/view/' . $project->getID() . '/')->setValue('Save'));
     $panel = new AphrontPanelView();
     $panel->setHeader($header_name);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     $panel->appendChild($form);
     $nav = $this->buildLocalNavigation($project);
     $nav->selectFilter('edit');
     $nav->appendChild(array($error_view, $panel));
     return $this->buildStandardPageResponse($nav, array('title' => $title));
 }
コード例 #17
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withIDs(array($this->id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$user) {
         return new Aphront404Response();
     }
     $profile_uri = '/p/' . $user->getUsername() . '/';
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_file = true;
     $errors = array();
     if ($request->isFormPost()) {
         $phid = $request->getStr('phid');
         $is_default = false;
         if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
             $phid = null;
             $is_default = true;
         } else {
             if ($phid) {
                 $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
             } else {
                 if ($request->getFileExists('picture')) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['picture'], array('authorPHID' => $viewer->getPHID(), 'canCDN' => true));
                 } else {
                     $e_file = pht('Required');
                     $errors[] = pht('You must choose a file when uploading a new profile picture.');
                 }
             }
         }
         if (!$errors && !$is_default) {
             if (!$file->isTransformableImage()) {
                 $e_file = pht('Not Supported');
                 $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats));
             } else {
                 $xformer = new PhabricatorImageTransformer();
                 $xformed = $xformer->executeProfileTransform($file, $width = 50, $min_height = 50, $max_height = 50);
             }
         }
         if (!$errors) {
             if ($is_default) {
                 $user->setProfileImagePHID(null);
             } else {
                 $user->setProfileImagePHID($xformed->getPHID());
                 $xformed->attachToObject($user->getPHID());
             }
             $user->save();
             return id(new AphrontRedirectResponse())->setURI($profile_uri);
         }
     }
     $title = pht('Edit Profile Picture');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($user->getUsername(), $profile_uri);
     $crumbs->addTextCrumb($title);
     $form = id(new PHUIFormLayoutView())->setUser($viewer);
     $default_image = PhabricatorFile::loadBuiltin($viewer, 'profile.png');
     $images = array();
     $current = $user->getProfileImagePHID();
     $has_current = false;
     if ($current) {
         $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($current))->execute();
         if ($files) {
             $file = head($files);
             if ($file->isTransformableImage()) {
                 $has_current = true;
                 $images[$current] = array('uri' => $file->getBestURI(), 'tip' => pht('Current Picture'));
             }
         }
     }
     // Try to add external account images for any associated external accounts.
     $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($user->getPHID()))->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     foreach ($accounts as $account) {
         $file = $account->getProfileImageFile();
         if ($account->getProfileImagePHID() != $file->getPHID()) {
             // This is a default image, just skip it.
             continue;
         }
         $provider = PhabricatorAuthProvider::getEnabledProviderByKey($account->getProviderKey());
         if ($provider) {
             $tip = pht('Picture From %s', $provider->getProviderName());
         } else {
             $tip = pht('Picture From External Account');
         }
         if ($file->isTransformableImage()) {
             $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => $tip);
         }
     }
     // Try to add Gravatar images for any email addresses associated with the
     // account.
     if (PhabricatorEnv::getEnvConfig('security.allow-outbound-http')) {
         $emails = id(new PhabricatorUserEmail())->loadAllWhere('userPHID = %s ORDER BY address', $user->getPHID());
         $futures = array();
         foreach ($emails as $email_object) {
             $email = $email_object->getAddress();
             $hash = md5(strtolower(trim($email)));
             $uri = id(new PhutilURI("https://secure.gravatar.com/avatar/{$hash}"))->setQueryParams(array('size' => 200, 'default' => '404', 'rating' => 'x'));
             $futures[$email] = new HTTPSFuture($uri);
         }
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         foreach (Futures($futures) as $email => $future) {
             try {
                 list($body) = $future->resolvex();
                 $file = PhabricatorFile::newFromFileData($body, array('name' => 'profile-gravatar', 'ttl' => 60 * 60 * 4));
                 if ($file->isTransformableImage()) {
                     $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => pht('Gravatar for %s', $email));
                 }
             } catch (Exception $ex) {
                 // Just continue.
             }
         }
         unset($unguarded);
     }
     $images[PhabricatorPHIDConstants::PHID_VOID] = array('uri' => $default_image->getBestURI(), 'tip' => pht('Default Picture'));
     require_celerity_resource('people-profile-css');
     Javelin::initBehavior('phabricator-tooltips', array());
     $buttons = array();
     foreach ($images as $phid => $spec) {
         $button = javelin_tag('button', array('class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array('tip' => $spec['tip'], 'size' => 300)), phutil_tag('img', array('height' => 50, 'width' => 50, 'src' => $spec['uri'])));
         $button = array(phutil_tag('input', array('type' => 'hidden', 'name' => 'phid', 'value' => $phid)), $button);
         $button = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST'), $button);
         $buttons[] = $button;
     }
     if ($has_current) {
         $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Current Picture'))->setValue(array_shift($buttons)));
     }
     $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Use Picture'))->setValue($buttons));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     $upload_form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setName('picture')->setLabel(pht('Upload Picture'))->setError($e_file)->setCaption(pht('Supported formats: %s', implode(', ', $supported_formats))))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($profile_uri)->setValue(pht('Upload Picture')));
     $upload_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Picture'))->setForm($upload_form);
     return $this->buildApplicationPage(array($crumbs, $form_box, $upload_box), array('title' => $title));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withIDs(array($id))->needProfileImage(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$user) {
         return new Aphront404Response();
     }
     $this->setUser($user);
     $done_uri = $this->getApplicationURI("manage/{$id}/");
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_file = true;
     $errors = array();
     if ($request->isFormPost()) {
         $phid = $request->getStr('phid');
         $is_default = false;
         if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
             $phid = null;
             $is_default = true;
         } else {
             if ($phid) {
                 $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
             } else {
                 if ($request->getFileExists('picture')) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['picture'], array('authorPHID' => $viewer->getPHID(), 'canCDN' => true));
                 } else {
                     $e_file = pht('Required');
                     $errors[] = pht('You must choose a file when uploading a new profile picture.');
                 }
             }
         }
         if (!$errors && !$is_default) {
             if (!$file->isTransformableImage()) {
                 $e_file = pht('Not Supported');
                 $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats));
             } else {
                 $xform = PhabricatorFileTransform::getTransformByKey(PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE);
                 $xformed = $xform->executeTransform($file);
             }
         }
         if (!$errors) {
             if ($is_default) {
                 $user->setProfileImagePHID(null);
             } else {
                 $user->setProfileImagePHID($xformed->getPHID());
                 $xformed->attachToObject($user->getPHID());
             }
             $user->save();
             return id(new AphrontRedirectResponse())->setURI($done_uri);
         }
     }
     $title = pht('Edit Profile Picture');
     $form = id(new PHUIFormLayoutView())->setUser($viewer);
     $default_image = PhabricatorFile::loadBuiltin($viewer, 'profile.png');
     $images = array();
     $current = $user->getProfileImagePHID();
     $has_current = false;
     if ($current) {
         $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($current))->execute();
         if ($files) {
             $file = head($files);
             if ($file->isTransformableImage()) {
                 $has_current = true;
                 $images[$current] = array('uri' => $file->getBestURI(), 'tip' => pht('Current Picture'));
             }
         }
     }
     $builtins = array('user1.png', 'user2.png', 'user3.png', 'user4.png', 'user5.png', 'user6.png', 'user7.png', 'user8.png', 'user9.png');
     foreach ($builtins as $builtin) {
         $file = PhabricatorFile::loadBuiltin($viewer, $builtin);
         $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => pht('Builtin Image'));
     }
     // Try to add external account images for any associated external accounts.
     $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($user->getPHID()))->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     foreach ($accounts as $account) {
         $file = $account->getProfileImageFile();
         if ($account->getProfileImagePHID() != $file->getPHID()) {
             // This is a default image, just skip it.
             continue;
         }
         $provider = PhabricatorAuthProvider::getEnabledProviderByKey($account->getProviderKey());
         if ($provider) {
             $tip = pht('Picture From %s', $provider->getProviderName());
         } else {
             $tip = pht('Picture From External Account');
         }
         if ($file->isTransformableImage()) {
             $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => $tip);
         }
     }
     $images[PhabricatorPHIDConstants::PHID_VOID] = array('uri' => $default_image->getBestURI(), 'tip' => pht('Default Picture'));
     require_celerity_resource('people-profile-css');
     Javelin::initBehavior('phabricator-tooltips', array());
     $buttons = array();
     foreach ($images as $phid => $spec) {
         $button = javelin_tag('button', array('class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array('tip' => $spec['tip'], 'size' => 300)), phutil_tag('img', array('height' => 50, 'width' => 50, 'src' => $spec['uri'])));
         $button = array(phutil_tag('input', array('type' => 'hidden', 'name' => 'phid', 'value' => $phid)), $button);
         $button = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST'), $button);
         $buttons[] = $button;
     }
     if ($has_current) {
         $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Current Picture'))->setValue(array_shift($buttons)));
     }
     $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Use Picture'))->setValue($buttons));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     $upload_form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setName('picture')->setLabel(pht('Upload Picture'))->setError($e_file)->setCaption(pht('Supported formats: %s', implode(', ', $supported_formats))))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($done_uri)->setValue(pht('Upload Picture')));
     $upload_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Picture'))->setForm($upload_form);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Edit Profile Picture'));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($form_box, $upload_box));
 }
コード例 #19
0
 public function processRequest(AphrontRequest $request)
 {
     $user = $request->getUser();
     $profile = id(new PhabricatorUserProfile())->loadOneWhere('userPHID = %s', $user->getPHID());
     if (!$profile) {
         $profile = new PhabricatorUserProfile();
         $profile->setUserPHID($user->getPHID());
     }
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_image = null;
     $errors = array();
     if ($request->isFormPost()) {
         $profile->setTitle($request->getStr('title'));
         $profile->setBlurb($request->getStr('blurb'));
         $sex = $request->getStr('sex');
         $sexes = array(PhutilPerson::SEX_MALE, PhutilPerson::SEX_FEMALE);
         if (in_array($sex, $sexes)) {
             $user->setSex($sex);
         } else {
             $user->setSex(null);
         }
         // Checked in runtime.
         $user->setTranslation($request->getStr('translation'));
         $default_image = $request->getExists('default_image');
         if ($default_image) {
             $profile->setProfileImagePHID(null);
             $user->setProfileImagePHID(null);
         } else {
             if (!empty($_FILES['image'])) {
                 $err = idx($_FILES['image'], 'error');
                 if ($err != UPLOAD_ERR_NO_FILE) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['image'], array('authorPHID' => $user->getPHID()));
                     $okay = $file->isTransformableImage();
                     if ($okay) {
                         $xformer = new PhabricatorImageTransformer();
                         // Generate the large picture for the profile page.
                         $large_xformed = $xformer->executeProfileTransform($file, $width = 280, $min_height = 140, $max_height = 420);
                         $profile->setProfileImagePHID($large_xformed->getPHID());
                         // Generate the small picture for comments, etc.
                         $small_xformed = $xformer->executeProfileTransform($file, $width = 50, $min_height = 50, $max_height = 50);
                         $user->setProfileImagePHID($small_xformed->getPHID());
                     } else {
                         $e_image = 'Not Supported';
                         $errors[] = 'This server only supports these image formats: ' . implode(', ', $supported_formats) . '.';
                     }
                 }
             }
         }
         if (!$errors) {
             $user->save();
             $profile->save();
             $response = id(new AphrontRedirectResponse())->setURI($this->getPanelURI('?saved=true'));
             return $response;
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     } else {
         if ($request->getStr('saved')) {
             $error_view = new AphrontErrorView();
             $error_view->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
             $error_view->setTitle('Changes Saved');
             $error_view->appendChild('<p>Your changes have been saved.</p>');
             $error_view = $error_view->render();
         }
     }
     $img_src = $user->loadProfileImageURI();
     $profile_uri = PhabricatorEnv::getURI('/p/' . $user->getUsername() . '/');
     $sexes = array(PhutilPerson::SEX_UNKNOWN => 'Unknown', PhutilPerson::SEX_MALE => 'Male', PhutilPerson::SEX_FEMALE => 'Female');
     $translations = array();
     $symbols = id(new PhutilSymbolLoader())->setType('class')->setAncestorClass('PhabricatorTranslation')->setConcreteOnly(true)->selectAndLoadSymbols();
     foreach ($symbols as $symbol) {
         $class = $symbol['name'];
         $translations[$class] = newv($class, array())->getName();
     }
     asort($translations);
     $default = PhabricatorEnv::newObjectFromConfig('translation.provider');
     $translations = array('' => 'Server Default (' . $default->getName() . ')') + $translations;
     $form = new AphrontFormView();
     $form->setUser($request->getUser())->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel('Title')->setName('title')->setValue($profile->getTitle())->setCaption('Serious business title.'))->appendChild(id(new AphrontFormSelectControl())->setOptions($sexes)->setLabel('Sex')->setName('sex')->setValue($user->getSex()))->appendChild(id(new AphrontFormSelectControl())->setOptions($translations)->setLabel('Translation')->setName('translation')->setValue($user->getTranslation()))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Profile URI')->setValue(phutil_render_tag('a', array('href' => $profile_uri), phutil_escape_html($profile_uri))))->appendChild('<p class="aphront-form-instructions">Write something about yourself! ' . 'Make sure to include <strong>important information</strong> like ' . 'your favorite Pokemon and which Starcraft race you play.</p>')->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Blurb')->setName('blurb')->setValue($profile->getBlurb()))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Profile Image')->setValue(phutil_render_tag('img', array('src' => $img_src))))->appendChild(id(new AphrontFormImageControl())->setLabel('Change Image')->setName('image')->setError($e_image)->setCaption('Supported formats: ' . implode(', ', $supported_formats)))->appendChild(id(new AphrontFormSubmitControl())->setValue('Save')->addCancelButton('/p/' . $user->getUsername() . '/'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Edit Profile Details');
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     return array($error_view, $panel);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $project = id(new PhabricatorProject())->load($this->id);
     if (!$project) {
         return new Aphront404Response();
     }
     $profile = $project->loadProfile();
     if (empty($profile)) {
         $profile = new PhabricatorProjectProfile();
     }
     if ($project->getSubprojectPHIDs()) {
         $phids = $project->getSubprojectPHIDs();
         $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
         $subprojects = mpull($handles, 'getFullName', 'getPHID');
     } else {
         $subprojects = array();
     }
     $options = PhabricatorProjectStatus::getStatusMap();
     $affiliations = $project->loadAffiliations();
     $affiliations = mpull($affiliations, null, 'getUserPHID');
     $e_name = true;
     $errors = array();
     $state = null;
     if ($request->isFormPost()) {
         $project->setName($request->getStr('name'));
         $project->setStatus($request->getStr('status'));
         $project->setSubprojectPHIDs($request->getArr('set_subprojects'));
         $profile->setBlurb($request->getStr('blurb'));
         if (!strlen($project->getName())) {
             $e_name = 'Required';
             $errors[] = 'Project name is required.';
         } else {
             $e_name = null;
         }
         if (!empty($_FILES['image'])) {
             $err = idx($_FILES['image'], 'error');
             if ($err != UPLOAD_ERR_NO_FILE) {
                 $file = PhabricatorFile::newFromPHPUpload($_FILES['image'], array('authorPHID' => $user->getPHID()));
                 $okay = $file->isTransformableImage();
                 if ($okay) {
                     $xformer = new PhabricatorImageTransformer();
                     $xformed = $xformer->executeProfileTransform($file, $width = 280, $min_height = 140, $max_height = 420);
                     $profile->setProfileImagePHID($xformed->getPHID());
                 } else {
                     $errors[] = 'Only valid image files (jpg, jpeg, png or gif) ' . 'will be accepted.';
                 }
             }
         }
         $resources = $request->getStr('resources');
         $resources = json_decode($resources, true);
         if (!is_array($resources)) {
             throw new Exception("Project resource information was not correctly encoded in the " . "request.");
         }
         $state = array();
         foreach ($resources as $resource) {
             $user_phid = $resource['phid'];
             if (!$user_phid) {
                 continue;
             }
             if (isset($state[$user_phid])) {
                 // TODO: We should deal with this better -- the user has entered
                 // the same resource more than once.
             }
             $state[$user_phid] = array('phid' => $user_phid, 'status' => $resource['status'], 'role' => $resource['role'], 'owner' => $resource['owner']);
         }
         $all_phids = array_merge(array_keys($state), array_keys($affiliations));
         $all_phids = array_unique($all_phids);
         $delete_affiliations = array();
         $save_affiliations = array();
         foreach ($all_phids as $phid) {
             $old = idx($affiliations, $phid);
             $new = idx($state, $phid);
             if ($old && !$new) {
                 $delete_affiliations[] = $affiliations[$phid];
                 continue;
             }
             if (!$old) {
                 $affil = new PhabricatorProjectAffiliation();
                 $affil->setUserPHID($phid);
             } else {
                 $affil = $old;
             }
             $affil->setRole((string) $new['role']);
             $affil->setStatus((string) $new['status']);
             $affil->setIsOwner((int) $new['owner']);
             $save_affiliations[] = $affil;
         }
         if (!$errors) {
             $project->save();
             $profile->setProjectPHID($project->getPHID());
             $profile->save();
             foreach ($delete_affiliations as $affil) {
                 $affil->delete();
             }
             foreach ($save_affiliations as $save) {
                 $save->setProjectPHID($project->getPHID());
                 $save->save();
             }
             return id(new AphrontRedirectResponse())->setURI('/project/view/' . $project->getID() . '/');
         } else {
             $phids = array_keys($state);
             $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
             foreach ($state as $phid => $info) {
                 $state[$phid]['name'] = $handles[$phid]->getFullName();
             }
         }
     } else {
         $phids = mpull($affiliations, 'getUserPHID');
         $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
         $state = array();
         foreach ($affiliations as $affil) {
             $user_phid = $affil->getUserPHID();
             $state[] = array('phid' => $user_phid, 'name' => $handles[$user_phid]->getFullName(), 'status' => $affil->getStatus(), 'role' => $affil->getRole(), 'owner' => $affil->getIsOwner());
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     }
     $header_name = 'Edit Project';
     $title = 'Edit Project';
     $action = '/project/edit/' . $project->getID() . '/';
     require_celerity_resource('project-edit-css');
     $form = new AphrontFormView();
     $form->setID('project-edit-form')->setUser($user)->setAction($action)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel('Name')->setName('name')->setValue($project->getName())->setError($e_name))->appendChild(id(new AphrontFormSelectControl())->setLabel('Project Status')->setName('status')->setOptions($options)->setValue($project->getStatus()))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Blurb')->setName('blurb')->setValue($profile->getBlurb()))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource('/typeahead/common/projects/')->setLabel('Subprojects')->setName('set_subprojects')->setValue($subprojects))->appendChild(id(new AphrontFormFileControl())->setLabel('Change Image')->setName('image'))->appendChild('<h1>Resources</h1>' . '<input type="hidden" name="resources" id="resources" />' . '<div class="aphront-form-inset">' . '<div style="float: right;">' . javelin_render_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'add-resource', 'mustcapture' => true), 'Add New Resource') . '</div>' . '<p></p>' . '<div style="clear: both;"></div>' . javelin_render_tag('table', array('sigil' => 'resources', 'class' => 'project-resource-table'), '') . '</div>')->appendChild(id(new AphrontFormSubmitControl())->addCancelButton('/project/view/' . $project->getID() . '/')->setValue('Save'));
     $template = new AphrontTokenizerTemplateView();
     $template = $template->render();
     Javelin::initBehavior('projects-resource-editor', array('root' => 'project-edit-form', 'tokenizerTemplate' => $template, 'tokenizerSource' => '/typeahead/common/users/', 'input' => 'resources', 'state' => array_values($state)));
     $panel = new AphrontPanelView();
     $panel->setHeader($header_name);
     $panel->setWidth(AphrontPanelView::WIDTH_WIDE);
     $panel->appendChild($form);
     return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => $title));
 }
コード例 #21
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $project = id(new PhabricatorProject())->load($this->id);
     if (!$project) {
         return new Aphront404Response();
     }
     $profile = $project->loadProfile();
     if (empty($profile)) {
         $profile = new PhabricatorProjectProfile();
     }
     $img_src = $profile->loadProfileImageURI();
     if ($project->getSubprojectPHIDs()) {
         $phids = $project->getSubprojectPHIDs();
         $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
         $subprojects = mpull($handles, 'getFullName', 'getPHID');
     } else {
         $subprojects = array();
     }
     $options = PhabricatorProjectStatus::getStatusMap();
     $affiliations = $project->loadAffiliations();
     $affiliations = mpull($affiliations, null, 'getUserPHID');
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_name = true;
     $e_image = null;
     $errors = array();
     $state = null;
     if ($request->isFormPost()) {
         try {
             $xactions = array();
             $xaction = new PhabricatorProjectTransaction();
             $xaction->setTransactionType(PhabricatorProjectTransactionType::TYPE_NAME);
             $xaction->setNewValue($request->getStr('name'));
             $xactions[] = $xaction;
             $xaction = new PhabricatorProjectTransaction();
             $xaction->setTransactionType(PhabricatorProjectTransactionType::TYPE_STATUS);
             $xaction->setNewValue($request->getStr('status'));
             $xactions[] = $xaction;
             $editor = new PhabricatorProjectEditor($project);
             $editor->setUser($user);
             $editor->applyTransactions($xactions);
         } catch (PhabricatorProjectNameCollisionException $ex) {
             $e_name = 'Not Unique';
             $errors[] = $ex->getMessage();
         }
         $project->setSubprojectPHIDs($request->getArr('set_subprojects'));
         $profile->setBlurb($request->getStr('blurb'));
         if (!strlen($project->getName())) {
             $e_name = 'Required';
             $errors[] = 'Project name is required.';
         } else {
             $e_name = null;
         }
         $default_image = $request->getExists('default_image');
         if ($default_image) {
             $profile->setProfileImagePHID(null);
         } else {
             if (!empty($_FILES['image'])) {
                 $err = idx($_FILES['image'], 'error');
                 if ($err != UPLOAD_ERR_NO_FILE) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['image'], array('authorPHID' => $user->getPHID()));
                     $okay = $file->isTransformableImage();
                     if ($okay) {
                         $xformer = new PhabricatorImageTransformer();
                         $xformed = $xformer->executeThumbTransform($file, $x = 50, $y = 50);
                         $profile->setProfileImagePHID($xformed->getPHID());
                     } else {
                         $e_image = 'Not Supported';
                         $errors[] = 'This server only supports these image formats: ' . implode(', ', $supported_formats) . '.';
                     }
                 }
             }
         }
         $resources = $request->getStr('resources');
         $resources = json_decode($resources, true);
         if (!is_array($resources)) {
             throw new Exception("Project resource information was not correctly encoded in the " . "request.");
         }
         $state = array();
         foreach ($resources as $resource) {
             $user_phid = $resource['phid'];
             if (!$user_phid) {
                 continue;
             }
             if (isset($state[$user_phid])) {
                 // TODO: We should deal with this better -- the user has entered
                 // the same resource more than once.
             }
             $state[$user_phid] = array('phid' => $user_phid, 'role' => $resource['role'], 'owner' => $resource['owner']);
         }
         $all_phids = array_merge(array_keys($state), array_keys($affiliations));
         $all_phids = array_unique($all_phids);
         $delete_affiliations = array();
         $save_affiliations = array();
         foreach ($all_phids as $phid) {
             $old = idx($affiliations, $phid);
             $new = idx($state, $phid);
             if ($old && !$new) {
                 $delete_affiliations[] = $affiliations[$phid];
                 continue;
             }
             if (!$old) {
                 $affil = new PhabricatorProjectAffiliation();
                 $affil->setUserPHID($phid);
             } else {
                 $affil = $old;
             }
             $affil->setRole((string) $new['role']);
             $affil->setIsOwner((int) $new['owner']);
             $save_affiliations[] = $affil;
         }
         if (!$errors) {
             $project->save();
             $profile->setProjectPHID($project->getPHID());
             $profile->save();
             foreach ($delete_affiliations as $affil) {
                 $affil->delete();
             }
             foreach ($save_affiliations as $save) {
                 $save->setProjectPHID($project->getPHID());
                 $save->save();
             }
             return id(new AphrontRedirectResponse())->setURI('/project/view/' . $project->getID() . '/');
         } else {
             $phids = array_keys($state);
             $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
             foreach ($state as $phid => $info) {
                 $state[$phid]['name'] = $handles[$phid]->getFullName();
             }
         }
     } else {
         $phids = mpull($affiliations, 'getUserPHID');
         $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
         $state = array();
         foreach ($affiliations as $affil) {
             $user_phid = $affil->getUserPHID();
             $state[] = array('phid' => $user_phid, 'name' => $handles[$user_phid]->getFullName(), 'role' => $affil->getRole(), 'owner' => $affil->getIsOwner());
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     }
     $header_name = 'Edit Project';
     $title = 'Edit Project';
     $action = '/project/edit/' . $project->getID() . '/';
     require_celerity_resource('project-edit-css');
     $form = new AphrontFormView();
     $form->setID('project-edit-form')->setUser($user)->setAction($action)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel('Name')->setName('name')->setValue($project->getName())->setError($e_name))->appendChild(id(new AphrontFormSelectControl())->setLabel('Project Status')->setName('status')->setOptions($options)->setValue($project->getStatus()))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Blurb')->setName('blurb')->setValue($profile->getBlurb()))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource('/typeahead/common/projects/')->setLabel('Subprojects')->setName('set_subprojects')->setValue($subprojects))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Profile Image')->setValue(phutil_render_tag('img', array('src' => $img_src))))->appendChild(id(new AphrontFormImageControl())->setLabel('Change Image')->setName('image')->setError($e_image)->setCaption('Supported formats: ' . implode(', ', $supported_formats)))->appendChild(id(new AphrontFormInsetView())->setTitle('Resources')->setRightButton(javelin_render_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'add-resource', 'mustcapture' => true), 'Add New Resource'))->appendChild(phutil_render_tag('input', array('type' => 'hidden', 'name' => 'resources', 'id' => 'resources')))->setContent(javelin_render_tag('table', array('sigil' => 'resources', 'class' => 'project-resource-table'), '')))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton('/project/view/' . $project->getID() . '/')->setValue('Save'));
     $template = new AphrontTokenizerTemplateView();
     $template = $template->render();
     Javelin::initBehavior('projects-resource-editor', array('root' => 'project-edit-form', 'tokenizerTemplate' => $template, 'tokenizerSource' => '/typeahead/common/users/', 'input' => 'resources', 'state' => array_values($state)));
     $panel = new AphrontPanelView();
     $panel->setHeader($header_name);
     $panel->setWidth(AphrontPanelView::WIDTH_WIDE);
     $panel->appendChild($form);
     return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => $title));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $profile = id(new PhabricatorUserProfile())->loadOneWhere('userPHID = %s', $user->getPHID());
     if (!$profile) {
         $profile = new PhabricatorUserProfile();
         $profile->setUserPHID($user->getPHID());
     }
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_image = null;
     $errors = array();
     if ($request->isFormPost()) {
         $profile->setTitle($request->getStr('title'));
         $profile->setBlurb($request->getStr('blurb'));
         if (!empty($_FILES['image'])) {
             $err = idx($_FILES['image'], 'error');
             if ($err != UPLOAD_ERR_NO_FILE) {
                 $file = PhabricatorFile::newFromPHPUpload($_FILES['image'], array('authorPHID' => $user->getPHID()));
                 $okay = $file->isTransformableImage();
                 if ($okay) {
                     $xformer = new PhabricatorImageTransformer();
                     // Generate the large picture for the profile page.
                     $large_xformed = $xformer->executeProfileTransform($file, $width = 280, $min_height = 140, $max_height = 420);
                     $profile->setProfileImagePHID($large_xformed->getPHID());
                     // Generate the small picture for comments, etc.
                     $small_xformed = $xformer->executeProfileTransform($file, $width = 50, $min_height = 50, $max_height = 50);
                     $user->setProfileImagePHID($small_xformed->getPHID());
                 } else {
                     $e_image = 'Not Supported';
                     $errors[] = 'This server only supports these image formats: ' . implode(', ', $supported_formats) . '.';
                 }
             }
         }
         if (!$errors) {
             $user->save();
             $profile->save();
             $response = id(new AphrontRedirectResponse())->setURI('/settings/page/profile/?saved=true');
             return $response;
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     } else {
         if ($request->getStr('saved')) {
             $error_view = new AphrontErrorView();
             $error_view->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
             $error_view->setTitle('Changes Saved');
             $error_view->appendChild('<p>Your changes have been saved.</p>');
             $error_view = $error_view->render();
         }
     }
     $file = id(new PhabricatorFile())->loadOneWhere('phid = %s', $user->getProfileImagePHID());
     if ($file) {
         $img_src = $file->getBestURI();
     } else {
         $img_src = null;
     }
     $profile_uri = PhabricatorEnv::getURI('/p/' . $user->getUsername() . '/');
     $form = new AphrontFormView();
     $form->setUser($request->getUser())->setAction('/settings/page/profile/')->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel('Title')->setName('title')->setValue($profile->getTitle())->setCaption('Serious business title.'))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Profile URI')->setValue(phutil_render_tag('a', array('href' => $profile_uri), phutil_escape_html($profile_uri))))->appendChild('<p class="aphront-form-instructions">Write something about yourself! ' . 'Make sure to include <strong>important information</strong> like ' . 'your favorite pokemon and which Starcraft race you play.</p>')->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Blurb')->setName('blurb')->setValue($profile->getBlurb()))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Profile Image')->setValue(phutil_render_tag('img', array('src' => $img_src))))->appendChild(id(new AphrontFormFileControl())->setLabel('Change Image')->setName('image')->setError($e_image)->setCaption('Supported formats: ' . implode(', ', $supported_formats)))->appendChild(id(new AphrontFormSubmitControl())->setValue('Save')->addCancelButton('/p/' . $user->getUsername() . '/'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Edit Profile Details');
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     return id(new AphrontNullView())->appendChild(array($error_view, $panel));
 }
コード例 #23
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $task = id(new ManiphestTask())->load($request->getStr('taskID'));
     if (!$task) {
         return new Aphront404Response();
     }
     $transactions = array();
     $action = $request->getStr('action');
     // If we have drag-and-dropped files, attach them first in a separate
     // transaction. These can come in on any transaction type, which is why we
     // handle them separately.
     $files = array();
     // Look for drag-and-drop uploads first.
     $file_phids = $request->getArr('files');
     if ($file_phids) {
         $files = id(new PhabricatorFile())->loadAllWhere('phid in (%Ls)', $file_phids);
     }
     // This means "attach a file" even though we store other types of data
     // as 'attached'.
     if ($action == ManiphestTransactionType::TYPE_ATTACH) {
         if (!empty($_FILES['file'])) {
             $err = idx($_FILES['file'], 'error');
             if ($err != UPLOAD_ERR_NO_FILE) {
                 $file = PhabricatorFile::newFromPHPUpload($_FILES['file'], array('authorPHID' => $user->getPHID()));
                 $files[] = $file;
             }
         }
     }
     // If we had explicit or drag-and-drop files, create a transaction
     // for those before we deal with whatever else might have happened.
     $file_transaction = null;
     if ($files) {
         $files = mpull($files, 'getPHID', 'getPHID');
         $new = $task->getAttached();
         foreach ($files as $phid) {
             if (empty($new[PhabricatorPHIDConstants::PHID_TYPE_FILE])) {
                 $new[PhabricatorPHIDConstants::PHID_TYPE_FILE] = array();
             }
             $new[PhabricatorPHIDConstants::PHID_TYPE_FILE][$phid] = array();
         }
         $transaction = new ManiphestTransaction();
         $transaction->setAuthorPHID($user->getPHID())->setTransactionType(ManiphestTransactionType::TYPE_ATTACH);
         $transaction->setNewValue($new);
         $transactions[] = $transaction;
         $file_transaction = $transaction;
     }
     // Compute new CCs added by @mentions. Several things can cause CCs to
     // be added as side effects: mentions, explicit CCs, users who aren't
     // CC'd interacting with the task, and ownership changes. We build up a
     // list of all the CCs and then construct a transaction for them at the
     // end if necessary.
     $added_ccs = PhabricatorMarkupEngine::extractPHIDsFromMentions(array($request->getStr('comments')));
     $cc_transaction = new ManiphestTransaction();
     $cc_transaction->setAuthorPHID($user->getPHID())->setTransactionType(ManiphestTransactionType::TYPE_CCS);
     $force_cc_transaction = false;
     $transaction = new ManiphestTransaction();
     $transaction->setAuthorPHID($user->getPHID())->setComments($request->getStr('comments'))->setTransactionType($action);
     switch ($action) {
         case ManiphestTransactionType::TYPE_STATUS:
             $transaction->setNewValue($request->getStr('resolution'));
             break;
         case ManiphestTransactionType::TYPE_OWNER:
             $assign_to = $request->getArr('assign_to');
             $assign_to = reset($assign_to);
             $transaction->setNewValue($assign_to);
             break;
         case ManiphestTransactionType::TYPE_PROJECTS:
             $projects = $request->getArr('projects');
             $projects = array_merge($projects, $task->getProjectPHIDs());
             $projects = array_filter($projects);
             $projects = array_unique($projects);
             $transaction->setNewValue($projects);
             break;
         case ManiphestTransactionType::TYPE_CCS:
             // Accumulate the new explicit CCs into the array that we'll add in
             // the CC transaction later.
             $added_ccs = array_merge($added_ccs, $request->getArr('ccs'));
             // Transfer any comments over to the CC transaction.
             $cc_transaction->setComments($transaction->getComments());
             // Make sure we include this transaction, even if the user didn't
             // actually add any CC's, because we'll discard their comment otherwise.
             $force_cc_transaction = true;
             // Throw away the primary transaction.
             $transaction = null;
             break;
         case ManiphestTransactionType::TYPE_PRIORITY:
             $transaction->setNewValue($request->getInt('priority'));
             break;
         case ManiphestTransactionType::TYPE_NONE:
         case ManiphestTransactionType::TYPE_ATTACH:
             // If we have a file transaction, just get rid of this secondary
             // transaction and put the comments on it instead.
             if ($file_transaction) {
                 $file_transaction->setComments($transaction->getComments());
                 $transaction = null;
             }
             break;
         default:
             throw new Exception('unknown action');
     }
     if ($transaction) {
         $transactions[] = $transaction;
     }
     // When you interact with a task, we add you to the CC list so you get
     // further updates, and possibly assign the task to you if you took an
     // ownership action (closing it) but it's currently unowned. We also move
     // previous owners to CC if ownership changes. Detect all these conditions
     // and create side-effect transactions for them.
     $implicitly_claimed = false;
     switch ($action) {
         case ManiphestTransactionType::TYPE_OWNER:
             if ($task->getOwnerPHID() == $transaction->getNewValue()) {
                 // If this is actually no-op, don't generate the side effect.
                 break;
             }
             // Otherwise, when a task is reassigned, move the previous owner to CC.
             $added_ccs[] = $task->getOwnerPHID();
             break;
         case ManiphestTransactionType::TYPE_STATUS:
             if (!$task->getOwnerPHID() && $request->getStr('resolution') != ManiphestTaskStatus::STATUS_OPEN) {
                 // Closing an unassigned task. Assign the user as the owner of
                 // this task.
                 $assign = new ManiphestTransaction();
                 $assign->setAuthorPHID($user->getPHID());
                 $assign->setTransactionType(ManiphestTransactionType::TYPE_OWNER);
                 $assign->setNewValue($user->getPHID());
                 $transactions[] = $assign;
                 $implicitly_claimed = true;
             }
             break;
     }
     $user_owns_task = false;
     if ($implicitly_claimed) {
         $user_owns_task = true;
     } else {
         if ($action == ManiphestTransactionType::TYPE_OWNER) {
             if ($transaction->getNewValue() == $user->getPHID()) {
                 $user_owns_task = true;
             }
         } else {
             if ($task->getOwnerPHID() == $user->getPHID()) {
                 $user_owns_task = true;
             }
         }
     }
     if (!$user_owns_task) {
         // If we aren't making the user the new task owner and they aren't the
         // existing task owner, add them to CC.
         $added_ccs[] = $user->getPHID();
     }
     if ($added_ccs || $force_cc_transaction) {
         // We've added CCs, so include a CC transaction. It's safe to do this even
         // if we're just "adding" CCs which already exist, because the
         // ManiphestTransactionEditor is smart enough to ignore them.
         $all_ccs = array_merge($task->getCCPHIDs(), $added_ccs);
         $cc_transaction->setNewValue($all_ccs);
         $transactions[] = $cc_transaction;
     }
     $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr()));
     foreach ($transactions as $transaction) {
         $transaction->setContentSource($content_source);
     }
     $editor = new ManiphestTransactionEditor();
     $editor->applyTransactions($task, $transactions);
     $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), $task->getPHID());
     if ($draft) {
         $draft->delete();
     }
     return id(new AphrontRedirectResponse())->setURI('/T' . $task->getID());
 }