id = $data['id']; } 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, '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 AphrontFormFileControl()) ->setLabel('Change Image') ->setName('image')) ->appendChild( '

Resources

'. ''. '
'. '
'. javelin_render_tag( 'a', array( 'href' => '#', 'class' => 'button green', 'sigil' => 'add-resource', 'mustcapture' => true, ), 'Add New Resource'). '
'. '

'. '
'. 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, )); } }