public function buildCustomEditFields(PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $viewer = $engine->getViewer(); $editor = $object->getApplicationTransactionEditor(); $types = $editor->getTransactionTypesForObject($object); $types = array_fuse($types); $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($object)->execute(); $map = array(PhabricatorTransactions::TYPE_VIEW_POLICY => array('key' => 'policy.view', 'aliases' => array('view'), 'capability' => PhabricatorPolicyCapability::CAN_VIEW, 'label' => pht('View Policy'), 'description' => pht('Controls who can view the object.'), 'edit' => 'view'), PhabricatorTransactions::TYPE_EDIT_POLICY => array('key' => 'policy.edit', 'aliases' => array('edit'), 'capability' => PhabricatorPolicyCapability::CAN_EDIT, 'label' => pht('Edit Policy'), 'description' => pht('Controls who can edit the object.'), 'edit' => 'edit'), PhabricatorTransactions::TYPE_JOIN_POLICY => array('key' => 'policy.join', 'aliases' => array('join'), 'capability' => PhabricatorPolicyCapability::CAN_JOIN, 'label' => pht('Join Policy'), 'description' => pht('Controls who can join the object.'), 'edit' => 'join')); $fields = array(); foreach ($map as $type => $spec) { if (empty($types[$type])) { continue; } $capability = $spec['capability']; $key = $spec['key']; $aliases = $spec['aliases']; $label = $spec['label']; $description = $spec['description']; $edit = $spec['edit']; $policy_field = id(new PhabricatorPolicyEditField())->setKey($key)->setLabel($label)->setDescription($description)->setAliases($aliases)->setIsCopyable(true)->setCapability($capability)->setPolicies($policies)->setTransactionType($type)->setEditTypeKey($edit)->setValue($object->getPolicy($capability)); $fields[] = $policy_field; if (!$object instanceof PhabricatorSpacesInterface) { if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { $type_space = PhabricatorTransactions::TYPE_SPACE; if (isset($types[$type_space])) { $space_field = id(new PhabricatorSpaceEditField())->setKey('spacePHID')->setLabel(pht('Space'))->setEditTypeKey('space')->setDescription(pht('Shifts the object in the Spaces application.'))->setIsCopyable(true)->setIsReorderable(false)->setAliases(array('space', 'policy.space'))->setTransactionType($type_space)->setValue($object->getSpacePHID()); $fields[] = $space_field; $policy_field->setSpaceField($space_field); } } } } return $fields; }
public function newEditEngineFields(PhabricatorEditEngine $engine, PhabricatorCalendarImport $import) { $fields = array(); if ($engine->getIsCreate()) { $fields[] = id(new PhabricatorTextEditField())->setKey('uri')->setLabel(pht('URI'))->setDescription(pht('URI to import.'))->setTransactionType(PhabricatorCalendarImportICSURITransaction::TRANSACTIONTYPE)->setConduitDescription(pht('URI to import.'))->setConduitTypeDescription(pht('New URI.')); } return $fields; }
public function newEditEngineFields(PhabricatorEditEngine $engine, PhabricatorCalendarImport $import) { $fields = array(); if ($engine->getIsCreate()) { $fields[] = id(new PhabricatorFileEditField())->setKey('icsFilePHID')->setLabel(pht('ICS File'))->setDescription(pht('ICS file to import.'))->setTransactionType(PhabricatorCalendarImportICSFileTransaction::TRANSACTIONTYPE)->setConduitDescription(pht('File PHID to import.'))->setConduitTypeDescription(pht('File PHID.')); } return $fields; }
private function buildCurtain(ManiphestTask $task, PhabricatorEditEngine $edit_engine) { $viewer = $this->getViewer(); $id = $task->getID(); $phid = $task->getPHID(); $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $task, PhabricatorPolicyCapability::CAN_EDIT); $curtain = $this->newCurtainView($task); $curtain->addAction(id(new PhabricatorActionView())->setName(pht('Edit Task'))->setIcon('fa-pencil')->setHref($this->getApplicationURI("/task/edit/{$id}/"))->setDisabled(!$can_edit)->setWorkflow(!$can_edit)); $edit_config = $edit_engine->loadDefaultEditConfiguration(); $can_create = (bool) $edit_config; $can_reassign = $edit_engine->hasEditAccessToTransaction(ManiphestTransaction::TYPE_OWNER); if ($can_create) { $form_key = $edit_config->getIdentifier(); $edit_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))->setQueryParam('parent', $id)->setQueryParam('template', $id)->setQueryParam('status', ManiphestTaskStatus::getDefaultStatus()); $edit_uri = $this->getApplicationURI($edit_uri); } else { // TODO: This will usually give us a somewhat-reasonable error page, but // could be a bit cleaner. $edit_uri = "/task/edit/{$id}/"; $edit_uri = $this->getApplicationURI($edit_uri); } $subtask_item = id(new PhabricatorActionView())->setName(pht('Create Subtask'))->setHref($edit_uri)->setIcon('fa-level-down')->setDisabled(!$can_create)->setWorkflow(!$can_create); $relationship_list = PhabricatorObjectRelationshipList::newForObject($viewer, $task); $submenu_actions = array($subtask_item, ManiphestTaskHasParentRelationship::RELATIONSHIPKEY, ManiphestTaskHasSubtaskRelationship::RELATIONSHIPKEY, ManiphestTaskMergeInRelationship::RELATIONSHIPKEY, ManiphestTaskCloseAsDuplicateRelationship::RELATIONSHIPKEY); $task_submenu = $relationship_list->newActionSubmenu($submenu_actions)->setName(pht('Edit Related Tasks...'))->setIcon('fa-anchor'); $curtain->addAction($task_submenu); $relationship_submenu = $relationship_list->newActionMenu(); if ($relationship_submenu) { $curtain->addAction($relationship_submenu); } $owner_phid = $task->getOwnerPHID(); $author_phid = $task->getAuthorPHID(); $handles = $viewer->loadHandles(array($owner_phid, $author_phid)); if ($owner_phid) { $image_uri = $handles[$owner_phid]->getImageURI(); $image_href = $handles[$owner_phid]->getURI(); $owner = $viewer->renderHandle($owner_phid)->render(); $content = phutil_tag('strong', array(), $owner); $assigned_to = id(new PHUIHeadThingView())->setImage($image_uri)->setImageHref($image_href)->setContent($content); } else { $assigned_to = phutil_tag('em', array(), pht('None')); } $curtain->newPanel()->setHeaderText(pht('Assigned To'))->appendChild($assigned_to); $author_uri = $handles[$author_phid]->getImageURI(); $author_href = $handles[$author_phid]->getURI(); $author = $viewer->renderHandle($author_phid)->render(); $content = phutil_tag('strong', array(), $author); $date = phabricator_date($task->getDateCreated(), $viewer); $content = pht('%s, %s', $content, $date); $authored_by = id(new PHUIHeadThingView())->setImage($author_uri)->setImageHref($author_href)->setContent($content); $curtain->newPanel()->setHeaderText(pht('Authored By'))->appendChild($authored_by); return $curtain; }
public function getQuickMenuItems() { $viewer = $this->getViewer(); $engines = PhabricatorEditEngine::getAllEditEngines(); foreach ($engines as $key => $engine) { if (!$engine->hasQuickCreateActions()) { unset($engines[$key]); } } if (!$engines) { return array(); } $engine_keys = array_keys($engines); $configs = id(new PhabricatorEditEngineConfigurationQuery())->setViewer($viewer)->withEngineKeys($engine_keys)->withIsDefault(true)->withIsDisabled(false)->execute(); $configs = msort($configs, 'getCreateSortKey'); $configs = mgroup($configs, 'getEngineKey'); $items = array(); foreach ($engines as $key => $engine) { $engine_configs = idx($configs, $key, array()); $engine_items = $engine->newQuickCreateActions($engine_configs); foreach ($engine_items as $engine_item) { $items[] = $engine_item; } } return $items; }
public function buildCustomEditFields(PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $subscribers_type = PhabricatorTransactions::TYPE_SUBSCRIBERS; $object_phid = $object->getPHID(); if ($object_phid) { $sub_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID($object_phid); } else { $sub_phids = array(); } $subscribers_field = id(new PhabricatorSubscribersEditField())->setKey('subscriberPHIDs')->setLabel(pht('Subscribers'))->setEditTypeKey('subscribers')->setAliases(array('subscriber', 'subscribers'))->setIsCopyable(true)->setUseEdgeTransactions(true)->setCommentActionLabel(pht('Change Subscribers'))->setTransactionType($subscribers_type)->setValue($sub_phids); $subscribers_field->setViewer($engine->getViewer()); $edit_add = $subscribers_field->getConduitEditType('subscribers.add')->setConduitDescription(pht('Add subscribers.')); $edit_set = $subscribers_field->getConduitEditType('subscribers.set')->setConduitDescription(pht('Set subscribers, overwriting current value.')); $edit_rem = $subscribers_field->getConduitEditType('subscribers.remove')->setConduitDescription(pht('Remove subscribers.')); return array($subscribers_field); }
private function buildCurtain(ManiphestTask $task, PhabricatorEditEngine $edit_engine) { $viewer = $this->getViewer(); $id = $task->getID(); $phid = $task->getPHID(); $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $task, PhabricatorPolicyCapability::CAN_EDIT); $curtain = $this->newCurtainView($task); $curtain->addAction(id(new PhabricatorActionView())->setName(pht('Edit Task'))->setIcon('fa-pencil')->setHref($this->getApplicationURI("/task/edit/{$id}/"))->setDisabled(!$can_edit)->setWorkflow(!$can_edit)); $curtain->addAction(id(new PhabricatorActionView())->setName(pht('Merge Duplicates In'))->setHref("/search/attach/{$phid}/TASK/merge/")->setWorkflow(true)->setIcon('fa-compress')->setDisabled(!$can_edit)->setWorkflow(true)); $edit_config = $edit_engine->loadDefaultEditConfiguration(); $can_create = (bool) $edit_config; $can_reassign = $edit_engine->hasEditAccessToTransaction(ManiphestTransaction::TYPE_OWNER); if ($can_create) { $form_key = $edit_config->getIdentifier(); $edit_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))->setQueryParam('parent', $id)->setQueryParam('template', $id)->setQueryParam('status', ManiphestTaskStatus::getDefaultStatus()); $edit_uri = $this->getApplicationURI($edit_uri); } else { // TODO: This will usually give us a somewhat-reasonable error page, but // could be a bit cleaner. $edit_uri = "/task/edit/{$id}/"; $edit_uri = $this->getApplicationURI($edit_uri); } $curtain->addAction(id(new PhabricatorActionView())->setName(pht('Create Subtask'))->setHref($edit_uri)->setIcon('fa-level-down')->setDisabled(!$can_create)->setWorkflow(!$can_create)); $curtain->addAction(id(new PhabricatorActionView())->setName(pht('Edit Blocking Tasks'))->setHref("/search/attach/{$phid}/TASK/blocks/")->setWorkflow(true)->setIcon('fa-link')->setDisabled(!$can_edit)->setWorkflow(true)); $owner_phid = $task->getOwnerPHID(); $author_phid = $task->getAuthorPHID(); $handles = $viewer->loadHandles(array($owner_phid, $author_phid)); if ($owner_phid) { $image_uri = $handles[$owner_phid]->getImageURI(); $image_href = $handles[$owner_phid]->getURI(); $owner = $viewer->renderHandle($owner_phid)->render(); $content = phutil_tag('strong', array(), $owner); $assigned_to = id(new PHUIHeadThingView())->setImage($image_uri)->setImageHref($image_href)->setContent($content); } else { $assigned_to = phutil_tag('em', array(), pht('None')); } $curtain->newPanel()->setHeaderText(pht('Assigned To'))->appendChild($assigned_to); $author_uri = $handles[$author_phid]->getImageURI(); $author_href = $handles[$author_phid]->getURI(); $author = $viewer->renderHandle($author_phid)->render(); $content = phutil_tag('strong', array(), $author); $date = phabricator_date($task->getDateCreated(), $viewer); $content = pht('%s, %s', $content, $date); $authored_by = id(new PHUIHeadThingView())->setImage($author_uri)->setImageHref($author_href)->setContent($content); $curtain->newPanel()->setHeaderText(pht('Authored By'))->appendChild($authored_by); return $curtain; }
public function buildCustomEditFields(PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $viewer = $this->getViewer(); $field_list = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_EDIT); $field_list->setViewer($viewer); if (!$engine->getIsCreate()) { $field_list->readFieldsFromStorage($object); } $results = array(); foreach ($field_list->getFields() as $field) { $edit_fields = $field->getEditEngineFields($engine); foreach ($edit_fields as $edit_field) { $results[] = $edit_field; } } return $results; }
protected function loadPage() { $engines = PhabricatorEditEngine::getAllEditEngines(); if ($this->engineKeys !== null) { $engines = array_select_keys($engines, $this->engineKeys); } return $engines; }
protected function getCommentViewHeaderText($object) { $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); if (!$is_serious) { return pht('Eat Paste'); } return parent::getCommentViewHeaderText($object); }
public function applyConfigurationToFields(PhabricatorEditEngine $engine, array $fields) { $fields = mpull($fields, null, 'getKey'); $values = $this->getProperty('defaults', array()); foreach ($fields as $key => $field) { if ($engine->getIsCreate()) { if (array_key_exists($key, $values)) { $field->readDefaultValueFromConfiguration($values[$key]); } } } $fields = $this->reorderFields($fields); $head_instructions = $this->getProperty('instructions.head'); if (strlen($head_instructions)) { $fields = array('config.instructions.head' => id(new PhabricatorInstructionsEditField())->setKey('config.instructions.head')->setValue($head_instructions)) + $fields; } return $fields; }
protected function buildApplicationCrumbs() { $viewer = $this->getViewer(); $crumbs = parent::buildApplicationCrumbs(); $target_key = $this->getEngineKey(); $target_engine = PhabricatorEditEngine::getByKey($viewer, $target_key); id(new PhabricatorEditEngineConfigurationEditEngine())->setTargetEngine($target_engine)->setViewer($viewer)->addActionToCrumbs($crumbs); return $crumbs; }
public function buildCustomEditFields(PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $edge_type = PhabricatorTransactions::TYPE_EDGE; $project_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $object_phid = $object->getPHID(); if ($object_phid) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object_phid, $project_edge_type); $project_phids = array_reverse($project_phids); } else { $project_phids = array(); } $projects_field = id(new PhabricatorProjectsEditField())->setKey('projectPHIDs')->setLabel(pht('Projects'))->setEditTypeKey('projects')->setAliases(array('project', 'projects'))->setIsCopyable(true)->setUseEdgeTransactions(true)->setCommentActionLabel(pht('Change Projects'))->setDescription(pht('Select projects for the object.'))->setTransactionType($edge_type)->setMetadataValue('edge:type', $project_edge_type)->setValue($project_phids); $projects_field->setViewer($engine->getViewer()); $edit_add = $projects_field->getConduitEditType('projects.add')->setConduitDescription(pht('Add projects.')); $edit_set = $projects_field->getConduitEditType('projects.set')->setConduitDescription(pht('Set projects, overwriting current value.')); $edit_rem = $projects_field->getConduitEditType('projects.remove')->setConduitDescription(pht('Remove projects.')); return array($projects_field); }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $target_engine_key = $request->getURIData('engineKey'); $target_engine = PhabricatorEditEngine::getByKey($viewer, $target_engine_key); if (!$target_engine) { return new Aphront404Response(); } $this->setEngineKey($target_engine->getEngineKey()); return id(new PhabricatorEditEngineConfigurationEditEngine())->setTargetEngine($target_engine)->setController($this)->buildResponse(); }
protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Edit Engines'), '/transactions/editengine/'); $engine_key = $this->getEngineKey(); if ($engine_key !== null) { $engine = PhabricatorEditEngine::getByKey($this->getViewer(), $engine_key); if ($engine) { $crumbs->addTextCrumb($engine->getEngineName(), "/transactions/editengine/{$engine_key}/"); } } return $crumbs; }
public function applyConfigurationToFields(PhabricatorEditEngine $engine, array $fields) { $fields = mpull($fields, null, 'getKey'); $values = $this->getProperty('defaults', array()); foreach ($fields as $key => $field) { if ($engine->getIsCreate()) { if (array_key_exists($key, $values)) { $field->readDefaultValueFromConfiguration($values[$key]); } } } $locks = $this->getFieldLocks(); foreach ($fields as $field) { $key = $field->getKey(); switch (idx($locks, $key)) { case self::LOCK_LOCKED: $field->setIsHidden(false); $field->setIsLocked(true); break; case self::LOCK_HIDDEN: $field->setIsHidden(true); $field->setIsLocked(false); break; case self::LOCK_VISIBLE: $field->setIsHidden(false); $field->setIsLocked(false); break; default: // If we don't have an explicit value, don't make any adjustments. break; } } $fields = $this->reorderFields($fields); $preamble = $this->getPreamble(); if (strlen($preamble)) { $fields = array('config.preamble' => id(new PhabricatorInstructionsEditField())->setKey('config.preamble')->setIsReorderable(false)->setIsDefaultable(false)->setIsLockable(false)->setValue($preamble)) + $fields; } return $fields; }
protected function newEditResponse(AphrontRequest $request, $object, array $xactions) { if ($request->isAjax()) { // Reload the task to make sure we pick up the final task state. $viewer = $this->getViewer(); $task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($object->getID()))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->executeOne(); switch ($request->getStr('responseType')) { case 'card': return $this->buildCardResponse($task); default: return $this->buildListResponse($task); } } return parent::newEditResponse($request, $object, $xactions); }
protected function loadPage() { // TODO: The logic here is a little flimsy and won't survive pagination. // For now, I'm just not bothering with pagination since I believe it will // take some time before any install manages to produce a large enough // number of edit forms for any particular engine for the lack of UI // pagination to become a problem. $page = $this->loadStandardPage($this->newResultObject()); // Now that we've loaded the real results from the database, we're going // to load builtins from the edit engines and add them to the list. $engines = PhabricatorEditEngine::getAllEditEngines(); if ($this->engineKeys) { $engines = array_select_keys($engines, $this->engineKeys); } foreach ($engines as $engine) { $engine->setViewer($this->getViewer()); } // List all the builtins which have already been saved to the database as // real objects. $concrete = array(); foreach ($page as $config) { $builtin_key = $config->getBuiltinKey(); if ($builtin_key !== null) { $engine_key = $config->getEngineKey(); $concrete[$engine_key][$builtin_key] = $config; } } $builtins = array(); foreach ($engines as $engine_key => $engine) { $engine_builtins = $engine->getBuiltinEngineConfigurations(); foreach ($engine_builtins as $engine_builtin) { $builtin_key = $engine_builtin->getBuiltinKey(); if (isset($concrete[$engine_key][$builtin_key])) { continue; } else { $builtins[] = $engine_builtin; } } } foreach ($builtins as $builtin) { $page[] = $builtin; } // Now we have to do some extra filtering to make sure everything we're // about to return really satisfies the query. if ($this->ids !== null) { $ids = array_fuse($this->ids); foreach ($page as $key => $config) { if (empty($ids[$config->getID()])) { unset($page[$key]); } } } if ($this->phids !== null) { $phids = array_fuse($this->phids); foreach ($page as $key => $config) { if (empty($phids[$config->getPHID()])) { unset($page[$key]); } } } if ($this->builtinKeys !== null) { $builtin_keys = array_fuse($this->builtinKeys); foreach ($page as $key => $config) { if (empty($builtin_keys[$config->getBuiltinKey()])) { unset($page[$key]); } } } if ($this->default !== null) { foreach ($page as $key => $config) { if ($config->getIsDefault() != $this->default) { unset($page[$key]); } } } if ($this->disabled !== null) { foreach ($page as $key => $config) { if ($config->getIsDisabled() != $this->disabled) { unset($page[$key]); } } } if ($this->identifiers !== null) { $identifiers = array_fuse($this->identifiers); foreach ($page as $key => $config) { if (isset($identifiers[$config->getBuiltinKey()])) { continue; } if (isset($identifiers[$config->getID()])) { continue; } unset($page[$key]); } } return $page; }
protected function newBuiltinEngineConfigurations() { $configuration = head(parent::newBuiltinEngineConfigurations()); // TODO: This whole method is clumsy, and the ordering for the custom // field is especially clumsy. Maybe try to make this more natural to // express. $configuration->setFieldOrder(array('parent', 'milestone', 'name', 'std:project:internal:description', 'icon', 'color', 'slugs')); return array($configuration); }
protected function getValidationExceptionShortMessage(PhabricatorApplicationTransactionValidationException $ex, PhabricatorEditField $field) { // Settings fields all have the same transaction type so we need to make // sure the transaction is changing the same setting before matching an // error to a given field. $xaction_type = $field->getTransactionType(); if ($xaction_type == PhabricatorUserPreferencesTransaction::TYPE_SETTING) { $property = PhabricatorUserPreferencesTransaction::PROPERTY_SETTING; $field_setting = idx($field->getMetadata(), $property); foreach ($ex->getErrors() as $error) { if ($error->getType() !== $xaction_type) { continue; } $xaction = $error->getTransaction(); if (!$xaction) { continue; } $xaction_setting = $xaction->getMetadataValue($property); if ($xaction_setting != $field_setting) { continue; } $short_message = $error->getShortMessage(); if ($short_message !== null) { return $short_message; } } return null; } return parent::getValidationExceptionShortMessage($ex, $field); }