private function buildProperties(PhabricatorProject $project)
 {
     $viewer = $this->getViewer();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setObject($project);
     if ($project->isMilestone()) {
         $icon_key = PhabricatorProjectIconSet::getMilestoneIconKey();
         $icon = PhabricatorProjectIconSet::getIconIcon($icon_key);
         $target = PhabricatorProjectIconSet::getIconName($icon_key);
         $note = pht('Members of the parent project are members of this project.');
         $show_join = false;
     } else {
         if ($project->getHasSubprojects()) {
             $icon = 'fa-sitemap';
             $target = pht('Parent Project');
             $note = pht('Members of all subprojects are members of this project.');
             $show_join = false;
         } else {
             if ($project->getIsMembershipLocked()) {
                 $icon = 'fa-lock';
                 $target = pht('Locked Project');
                 $note = pht('Users with access may join this project, but may not leave.');
                 $show_join = true;
             } else {
                 $icon = 'fa-briefcase';
                 $target = pht('Normal Project');
                 $note = pht('Users with access may join and leave this project.');
                 $show_join = true;
             }
         }
     }
     $item = id(new PHUIStatusItemView())->setIcon($icon)->setTarget(phutil_tag('strong', array(), $target))->setNote($note);
     $status = id(new PHUIStatusListView())->addItem($item);
     $view->addProperty(pht('Membership'), $status);
     if ($show_join) {
         $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions($viewer, $project);
         $view->addProperty(pht('Joinable By'), $descriptions[PhabricatorPolicyCapability::CAN_JOIN]);
     }
     $viewer_phid = $viewer->getPHID();
     if ($project->isUserWatcher($viewer_phid)) {
         $watch_item = id(new PHUIStatusItemView())->setIcon('fa-eye green')->setTarget(phutil_tag('strong', array(), pht('Watching')))->setNote(pht('You will receive mail about changes made to any related ' . 'object.'));
         $watch_status = id(new PHUIStatusListView())->addItem($watch_item);
         $view->addProperty(pht('Watching'), $watch_status);
     }
     if ($project->isUserMember($viewer_phid)) {
         $is_silenced = $this->isProjectSilenced($project);
         if ($is_silenced) {
             $mail_icon = 'fa-envelope-o grey';
             $mail_target = pht('Disabled');
             $mail_note = pht('When mail is sent to project members, you will not receive ' . 'a copy.');
         } else {
             $mail_icon = 'fa-envelope-o green';
             $mail_target = pht('Enabled');
             $mail_note = pht('You will receive mail that is sent to project members.');
         }
         $mail_item = id(new PHUIStatusItemView())->setIcon($mail_icon)->setTarget(phutil_tag('strong', array(), $mail_target))->setNote($mail_note);
         $mail_status = id(new PHUIStatusListView())->addItem($mail_item);
         $view->addProperty(pht('Mail to Members'), $mail_status);
     }
     return $view;
 }
    public function getOptions()
    {
        $default_icons = PhabricatorProjectIconSet::getDefaultConfiguration();
        $icons_type = 'custom:PhabricatorProjectTypeConfigOptionType';
        $icons_description = $this->deformat(pht(<<<EOTEXT
Allows you to change and customize the available project icons.

You can find a list of available icons in {nav UIExamples > Icons and Images}.

Configure a list of icon specifications. Each icon specification should be
a dictionary, which may contain these keys:

  - `key` //Required string.// Internal key identifying the icon.
  - `name` //Required string.// Human-readable icon name.
  - `icon` //Required string.// Specifies which actual icon image to use.
  - `default` //Optional bool.// Selects a default icon. Exactly one icon must
    be selected as the default.
  - `disabled` //Optional bool.// If true, this icon will no longer be
    available for selection when creating or editing projects.
  - `special` //Optional string.// Marks an icon as a special icon:
    - `milestone` This is the icon for milestones. Exactly one icon must be
      selected as the milestone icon.

You can look at the default configuration below for an example of a valid
configuration.
EOTEXT
));
        $default_fields = array('std:project:internal:description' => true);
        foreach ($default_fields as $key => $enabled) {
            $default_fields[$key] = array('disabled' => !$enabled);
        }
        $custom_field_type = 'custom:PhabricatorCustomFieldConfigOptionType';
        return array($this->newOption('projects.custom-field-definitions', 'wild', array())->setSummary(pht('Custom Projects fields.'))->setDescription(pht('Array of custom fields for Projects.'))->addExample('{"mycompany:motto": {"name": "Project Motto", ' . '"type": "text"}}', pht('Valid Setting')), $this->newOption('projects.fields', $custom_field_type, $default_fields)->setCustomData(id(new PhabricatorProject())->getCustomFieldBaseClass())->setDescription(pht('Select and reorder project fields.')), $this->newOption('projects.icons', $icons_type, $default_icons)->setSummary(pht('Adjust project icons.'))->setDescription($icons_description));
    }
 public function getFieldValuesForConduit()
 {
     $color_key = $this->getColor();
     $color_name = PhabricatorProjectIconSet::getColorName($color_key);
     return array('name' => $this->getName(), 'slug' => $this->getPrimarySlug(), 'icon' => array('key' => $this->getDisplayIconKey(), 'name' => $this->getDisplayIconName(), 'icon' => $this->getDisplayIconIcon()), 'color' => array('key' => $color_key, 'name' => $color_name));
 }
 private function getColorOptions()
 {
     $options = array();
     foreach (PhabricatorProjectIconSet::getColorMap() as $color => $name) {
         $options[$color] = array(id(new PHUITagView())->setType(PHUITagView::TYPE_SHADE)->setShade($color)->setName($name), ' ', $name);
     }
     return $options;
 }
 public function buildIconNavView(PhabricatorProject $project)
 {
     $this->setProject($project);
     $viewer = $this->getViewer();
     $id = $project->getID();
     $picture = $project->getProfileImageURI();
     $name = $project->getName();
     $columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
     if ($columns) {
         $board_icon = 'fa-columns';
     } else {
         $board_icon = 'fa-columns grey';
     }
     $nav = new AphrontSideNavFilterView();
     $nav->setIconNav(true);
     $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
     $nav->addIcon("profile/{$id}/", $name, null, $picture);
     $class = 'PhabricatorManiphestApplication';
     if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
         $phid = $project->getPHID();
         $nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
         $query_uri = urisprintf('/maniphest/?statuses=open()&projects=%s#R', $phid);
         $nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
     }
     $nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o');
     $nav->addIcon("members/{$id}/", pht('Members'), 'fa-group');
     if (false && PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
         if ($project->supportsSubprojects()) {
             $subprojects_icon = 'fa-sitemap';
         } else {
             $subprojects_icon = 'fa-sitemap grey';
         }
         $key = PhabricatorProjectIconSet::getMilestoneIconKey();
         $milestones_icon = PhabricatorProjectIconSet::getIconIcon($key);
         if (!$project->supportsMilestones()) {
             $milestones_icon = "{$milestones_icon} grey";
         }
         $nav->addIcon("subprojects/{$id}/", pht('Subprojects'), $subprojects_icon);
         $nav->addIcon("milestones/{$id}/", pht('Milestones'), $milestones_icon);
     }
     return $nav;
 }
 public function getTitleForFeed()
 {
     $author_phid = $this->getAuthorPHID();
     $object_phid = $this->getObjectPHID();
     $author_handle = $this->renderHandleLink($author_phid);
     $object_handle = $this->renderHandleLink($object_phid);
     $old = $this->getOldValue();
     $new = $this->getNewValue();
     switch ($this->getTransactionType()) {
         case self::TYPE_NAME:
             if ($old === null) {
                 return pht('%s created %s.', $author_handle, $object_handle);
             } else {
                 return pht('%s renamed %s from "%s" to "%s".', $author_handle, $object_handle, $old, $new);
             }
         case self::TYPE_STATUS:
             if ($old == 0) {
                 return pht('%s archived %s.', $author_handle, $object_handle);
             } else {
                 return pht('%s activated %s.', $author_handle, $object_handle);
             }
         case self::TYPE_IMAGE:
             // TODO: Some day, it would be nice to show the images.
             if (!$old) {
                 return pht('%s set the image for %s to %s.', $author_handle, $object_handle, $this->renderHandleLink($new));
             } else {
                 if (!$new) {
                     return pht('%s removed the image for %s.', $author_handle, $object_handle);
                 } else {
                     return pht('%s updated the image for %s from %s to %s.', $author_handle, $object_handle, $this->renderHandleLink($old), $this->renderHandleLink($new));
                 }
             }
         case self::TYPE_ICON:
             $set = new PhabricatorProjectIconSet();
             return pht('%s set the icon for %s to %s.', $author_handle, $object_handle, $set->getIconLabel($new));
         case self::TYPE_COLOR:
             return pht('%s set the color for %s to %s.', $author_handle, $object_handle, PHUITagView::getShadeName($new));
         case self::TYPE_LOCKED:
             if ($new) {
                 return pht('%s locked %s membership.', $author_handle, $object_handle);
             } else {
                 return pht('%s unlocked %s membership.', $author_handle, $object_handle);
             }
         case self::TYPE_SLUGS:
             $add = array_diff($new, $old);
             $rem = array_diff($old, $new);
             if ($add && $rem) {
                 return pht('%s changed %s hashtag(s), added %d: %s; removed %d: %s.', $author_handle, $object_handle, count($add), $this->renderSlugList($add), count($rem), $this->renderSlugList($rem));
             } else {
                 if ($add) {
                     return pht('%s added %d %s hashtag(s): %s.', $author_handle, count($add), $object_handle, $this->renderSlugList($add));
                 } else {
                     if ($rem) {
                         return pht('%s removed %d %s hashtag(s): %s.', $author_handle, count($rem), $object_handle, $this->renderSlugList($rem));
                     }
                 }
             }
     }
     return parent::getTitleForFeed();
 }
 public function validateOption(PhabricatorConfigOption $option, $value)
 {
     PhabricatorProjectIconSet::validateConfiguration($value);
 }
Example #8
0
 public function getDisplayIconName()
 {
     $key = $this->getDisplayIconKey();
     return PhabricatorProjectIconSet::getIconName($key);
 }
 protected function buildCustomEditFields($object)
 {
     $slugs = mpull($object->getSlugs(), 'getSlug');
     $slugs = array_fuse($slugs);
     unset($slugs[$object->getPrimarySlug()]);
     $slugs = array_values($slugs);
     $milestone = $this->getMilestoneProject();
     $parent = $this->getParentProject();
     if ($parent) {
         $parent_phid = $parent->getPHID();
     } else {
         $parent_phid = null;
     }
     if ($milestone) {
         $milestone_phid = $milestone->getPHID();
     } else {
         $milestone_phid = null;
     }
     $fields = array(id(new PhabricatorHandlesEditField())->setKey('parent')->setLabel(pht('Parent'))->setDescription(pht('Create a subproject of an existing project.'))->setConduitDescription(pht('Choose a parent project to create a subproject beneath.'))->setConduitTypeDescription(pht('PHID of the parent project.'))->setAliases(array('parentPHID'))->setTransactionType(PhabricatorProjectTransaction::TYPE_PARENT)->setHandleParameterType(new AphrontPHIDHTTPParameterType())->setSingleValue($parent_phid)->setIsReorderable(false)->setIsDefaultable(false)->setIsLockable(false)->setIsLocked(true), id(new PhabricatorHandlesEditField())->setKey('milestone')->setLabel(pht('Milestone Of'))->setDescription(pht('Parent project to create a milestone for.'))->setConduitDescription(pht('Choose a parent project to create a new milestone for.'))->setConduitTypeDescription(pht('PHID of the parent project.'))->setAliases(array('milestonePHID'))->setTransactionType(PhabricatorProjectTransaction::TYPE_MILESTONE)->setHandleParameterType(new AphrontPHIDHTTPParameterType())->setSingleValue($milestone_phid)->setIsReorderable(false)->setIsDefaultable(false)->setIsLockable(false)->setIsLocked(true), id(new PhabricatorTextEditField())->setKey('name')->setLabel(pht('Name'))->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME)->setIsRequired(true)->setDescription(pht('Project name.'))->setConduitDescription(pht('Rename the project'))->setConduitTypeDescription(pht('New project name.'))->setValue($object->getName()), id(new PhabricatorIconSetEditField())->setKey('icon')->setLabel(pht('Icon'))->setTransactionType(PhabricatorProjectTransaction::TYPE_ICON)->setIconSet(new PhabricatorProjectIconSet())->setDescription(pht('Project icon.'))->setConduitDescription(pht('Change the project icon.'))->setConduitTypeDescription(pht('New project icon.'))->setValue($object->getIcon()), id(new PhabricatorSelectEditField())->setKey('color')->setLabel(pht('Color'))->setTransactionType(PhabricatorProjectTransaction::TYPE_COLOR)->setOptions(PhabricatorProjectIconSet::getColorMap())->setDescription(pht('Project tag color.'))->setConduitDescription(pht('Change the project tag color.'))->setConduitTypeDescription(pht('New project tag color.'))->setValue($object->getColor()), id(new PhabricatorStringListEditField())->setKey('slugs')->setLabel(pht('Additional Hashtags'))->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)->setDescription(pht('Additional project slugs.'))->setConduitDescription(pht('Change project slugs.'))->setConduitTypeDescription(pht('New list of slugs.'))->setValue($slugs));
     $can_edit_members = !$milestone && !$object->isMilestone() && !$object->getHasSubprojects();
     if ($can_edit_members) {
         // Show this on the web UI when creating a project, but not when editing
         // one. It is always available via Conduit.
         $conduit_only = !$this->getIsCreate();
         $members_field = id(new PhabricatorUsersEditField())->setKey('members')->setAliases(array('memberPHIDs'))->setLabel(pht('Initial Members'))->setIsConduitOnly($conduit_only)->setUseEdgeTransactions(true)->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', PhabricatorProjectProjectHasMemberEdgeType::EDGECONST)->setDescription(pht('Initial project members.'))->setConduitDescription(pht('Set project members.'))->setConduitTypeDescription(pht('New list of members.'))->setValue(array());
         $members_field->setViewer($this->getViewer());
         $edit_add = $members_field->getConduitEditType('members.add')->setConduitDescription(pht('Add members.'));
         $edit_set = $members_field->getConduitEditType('members.set')->setConduitDescription(pht('Set members, overwriting the current value.'));
         $edit_rem = $members_field->getConduitEditType('members.remove')->setConduitDescription(pht('Remove members.'));
         $fields[] = $members_field;
     }
     return $fields;
 }
 protected function buildCustomEditFields($object)
 {
     $slugs = mpull($object->getSlugs(), 'getSlug');
     $slugs = array_fuse($slugs);
     unset($slugs[$object->getPrimarySlug()]);
     $slugs = array_values($slugs);
     $milestone = $this->getMilestoneProject();
     $parent = $this->getParentProject();
     if ($parent) {
         $parent_phid = $parent->getPHID();
     } else {
         $parent_phid = null;
     }
     if ($milestone) {
         $milestone_phid = $milestone->getPHID();
     } else {
         $milestone_phid = null;
     }
     return array(id(new PhabricatorHandlesEditField())->setKey('parent')->setLabel(pht('Parent'))->setDescription(pht('Create a subproject of an existing project.'))->setConduitDescription(pht('Choose a parent project to create a subproject beneath.'))->setConduitTypeDescription(pht('PHID of the parent project.'))->setAliases(array('parentPHID'))->setTransactionType(PhabricatorProjectTransaction::TYPE_PARENT)->setHandleParameterType(new AphrontPHIDHTTPParameterType())->setSingleValue($parent_phid)->setIsReorderable(false)->setIsDefaultable(false)->setIsLockable(false)->setIsLocked(true), id(new PhabricatorHandlesEditField())->setKey('milestone')->setLabel(pht('Milestone Of'))->setDescription(pht('Parent project to create a milestone for.'))->setConduitDescription(pht('Choose a parent project to create a new milestone for.'))->setConduitTypeDescription(pht('PHID of the parent project.'))->setAliases(array('milestonePHID'))->setTransactionType(PhabricatorProjectTransaction::TYPE_MILESTONE)->setHandleParameterType(new AphrontPHIDHTTPParameterType())->setSingleValue($milestone_phid)->setIsReorderable(false)->setIsDefaultable(false)->setIsLockable(false)->setIsLocked(true), id(new PhabricatorTextEditField())->setKey('name')->setLabel(pht('Name'))->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME)->setIsRequired(true)->setDescription(pht('Project name.'))->setConduitDescription(pht('Rename the project'))->setConduitTypeDescription(pht('New project name.'))->setValue($object->getName()), id(new PhabricatorIconSetEditField())->setKey('icon')->setLabel(pht('Icon'))->setTransactionType(PhabricatorProjectTransaction::TYPE_ICON)->setIconSet(new PhabricatorProjectIconSet())->setDescription(pht('Project icon.'))->setConduitDescription(pht('Change the project icon.'))->setConduitTypeDescription(pht('New project icon.'))->setValue($object->getIcon()), id(new PhabricatorSelectEditField())->setKey('color')->setLabel(pht('Color'))->setTransactionType(PhabricatorProjectTransaction::TYPE_COLOR)->setOptions(PhabricatorProjectIconSet::getColorMap())->setDescription(pht('Project tag color.'))->setConduitDescription(pht('Change the project tag color.'))->setConduitTypeDescription(pht('New project tag color.'))->setValue($object->getColor()), id(new PhabricatorStringListEditField())->setKey('slugs')->setLabel(pht('Additional Hashtags'))->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)->setDescription(pht('Additional project slugs.'))->setConduitDescription(pht('Change project slugs.'))->setConduitTypeDescription(pht('New list of slugs.'))->setValue($slugs));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     if ($id) {
         $id = $request->getURIData('id');
         $is_new = false;
         $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($id))->needSlugs(true)->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$project) {
             return new Aphront404Response();
         }
     } else {
         $is_new = true;
         $this->requireApplicationCapability(ProjectCreateProjectsCapability::CAPABILITY);
         $project = PhabricatorProject::initializeNewProject($viewer);
     }
     $field_list = PhabricatorCustomField::getObjectFields($project, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($viewer)->readFieldsFromStorage($project);
     $e_name = true;
     $e_slugs = false;
     $e_edit = null;
     $v_name = $project->getName();
     $project_slugs = $project->getSlugs();
     $project_slugs = mpull($project_slugs, 'getSlug', 'getSlug');
     $v_primary_slug = $project->getPrimarySlug();
     unset($project_slugs[$v_primary_slug]);
     $v_slugs = $project_slugs;
     $v_color = $project->getColor();
     $v_icon = $project->getIcon();
     $v_locked = $project->getIsMembershipLocked();
     $validation_exception = null;
     if ($request->isFormPost()) {
         $e_name = null;
         $e_slugs = null;
         $v_name = $request->getStr('name');
         $v_slugs = $request->getStrList('slugs');
         $v_view = $request->getStr('can_view');
         $v_edit = $request->getStr('can_edit');
         $v_join = $request->getStr('can_join');
         $v_color = $request->getStr('color');
         $v_icon = $request->getStr('icon');
         $v_locked = $request->getInt('is_membership_locked', 0);
         $type_name = PhabricatorProjectTransaction::TYPE_NAME;
         $type_slugs = PhabricatorProjectTransaction::TYPE_SLUGS;
         $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
         $type_icon = PhabricatorProjectTransaction::TYPE_ICON;
         $type_color = PhabricatorProjectTransaction::TYPE_COLOR;
         $type_locked = PhabricatorProjectTransaction::TYPE_LOCKED;
         $xactions = array();
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_name)->setNewValue($v_name);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_slugs)->setNewValue($v_slugs);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($v_view);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_edit)->setNewValue($v_edit);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY)->setNewValue($v_join);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_icon)->setNewValue($v_icon);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_color)->setNewValue($v_color);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_locked)->setNewValue($v_locked);
         $xactions = array_merge($xactions, $field_list->buildFieldTransactionsFromRequest(new PhabricatorProjectTransaction(), $request));
         $editor = id(new PhabricatorProjectTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
         if ($is_new) {
             $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', PhabricatorProjectProjectHasMemberEdgeType::EDGECONST)->setNewValue(array('+' => array($viewer->getPHID() => $viewer->getPHID())));
         }
         try {
             $editor->applyTransactions($project, $xactions);
             if ($request->isAjax()) {
                 return id(new AphrontAjaxResponse())->setContent(array('phid' => $project->getPHID(), 'name' => $project->getName()));
             }
             $redirect_uri = $this->getApplicationURI('profile/' . $project->getID() . '/');
             return id(new AphrontRedirectResponse())->setURI($redirect_uri);
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $validation_exception = $ex;
             $e_name = $ex->getShortMessage($type_name);
             $e_slugs = $ex->getShortMessage($type_slugs);
             $e_edit = $ex->getShortMessage($type_edit);
             $project->setViewPolicy($v_view);
             $project->setEditPolicy($v_edit);
             $project->setJoinPolicy($v_join);
         }
     }
     if ($is_new) {
         $header_name = pht('Create a New Project');
         $title = pht('Create Project');
     } else {
         $header_name = pht('Edit Project');
         $title = pht('Edit Project');
     }
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($project)->execute();
     $v_slugs = implode(', ', $v_slugs);
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Name'))->setName('name')->setValue($v_name)->setError($e_name));
     $field_list->appendFieldsToForm($form);
     $shades = PhabricatorProjectIconSet::getColorMap();
     list($can_lock, $lock_message) = $this->explainApplicationCapability(ProjectCanLockProjectsCapability::CAPABILITY, pht('You can update the Lock Project setting.'), pht('You can not update the Lock Project setting.'));
     $form->appendChild(id(new PHUIFormIconSetControl())->setLabel(pht('Icon'))->setName('icon')->setIconSet(new PhabricatorProjectIconSet())->setValue($v_icon))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Color'))->setName('color')->setValue($v_color)->setOptions($shades));
     if (!$is_new) {
         $form->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Primary Hashtag'))->setCaption(pht('The primary hashtag is derived from the name.'))->setValue($v_primary_slug));
     }
     $form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Additional Hashtags'))->setCaption(pht('Specify a comma-separated list of additional hashtags.'))->setName('slugs')->setValue($v_slugs)->setError($e_slugs))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setName('can_view')->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_VIEW))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setName('can_edit')->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_EDIT)->setError($e_edit))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setName('can_join')->setCaption(pht('Users who can edit a project can always join a project.'))->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_JOIN))->appendChild(id(new AphrontFormCheckboxControl())->setLabel(pht('Lock Project'))->setDisabled(!$can_lock)->addCheckbox('is_membership_locked', 1, pht('Prevent members from leaving this project.'), $v_locked)->setCaption($lock_message));
     if ($request->isAjax()) {
         $errors = array();
         if ($validation_exception) {
             $errors = mpull($ex->getErrors(), 'getMessage');
         }
         $dialog = id(new AphrontDialogView())->setUser($viewer)->setWidth(AphrontDialogView::WIDTH_FULL)->setTitle($header_name)->setErrors($errors)->appendForm($form)->addSubmitButton($title)->addCancelButton('/project/');
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($this->getApplicationURI())->setValue(pht('Save')));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setValidationException($validation_exception)->setForm($form);
     if (!$is_new) {
         $nav = $this->buildIconNavView($project);
         $nav->selectFilter("details/{$id}/");
         $nav->appendChild($form_box);
     } else {
         $nav = array($form_box);
     }
     return $this->buildApplicationPage($nav, array('title' => $title));
 }