public function __construct(PhabricatorCustomField $field)
 {
     $key = $field->getFieldKey();
     $name = $field->getFieldName();
     $class = get_class($field);
     parent::__construct("Custom field '{$name}' (with key '{$key}', of class '{$class}') can " . "not have a proxy set with setProxy(), because it returned false from " . "canSetProxy().");
 }
 public function __construct(PhabricatorCustomField $field)
 {
     $key = $field->getFieldKey();
     $name = $field->getFieldName();
     $class = get_class($field);
     parent::__construct("Custom field '{$name}' (with key '{$key}', of class '{$class}') is " . "attempting to access data which is not available in this context.");
 }
 public function setCustomField(PhabricatorCustomField $field)
 {
     $this->customField = $field;
     $this->setKey('custom:' . $field->getFieldIndex());
     $aliases = array();
     $aliases[] = $field->getFieldKey();
     $this->setAliases($aliases);
     return $this;
 }
 public function __construct(PhabricatorCustomField $field, $field_key_is_incomplete = false)
 {
     if ($field_key_is_incomplete) {
         $key = pht('<incomplete key>');
         $name = pht('<incomplete name>');
     } else {
         $key = $field->getFieldKey();
         $name = $field->getFieldName();
     }
     parent::__construct(pht("Custom field '%s' (with key '%s', of class '%s') is incompletely " . "implemented: it claims to support a feature, but does not " . "implement all of the required methods for that feature.", $name, $key, get_class($field)));
 }
 public function addField(PhabricatorCustomField $field)
 {
     $role_storage = PhabricatorCustomField::ROLE_STORAGE;
     if (!$field->shouldEnableForRole($role_storage)) {
         return $this;
     }
     $storage = $field->newStorageObject();
     $source_key = $storage->getStorageSourceKey();
     $this->fieldMap[$source_key][] = $field;
     if (empty($this->storageSources[$source_key])) {
         $this->storageSources[$source_key] = $storage;
     }
     return $this;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $step = id(new HarbormasterBuildStepQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$step) {
         return new Aphront404Response();
     }
     $plan = $step->getBuildPlan();
     $plan_id = $plan->getID();
     $plan_uri = $this->getApplicationURI("plan/{$plan_id}/");
     $field_list = PhabricatorCustomField::getObjectFields($step, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($viewer)->readFieldsFromStorage($step);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Plan %d', $plan_id), $plan_uri);
     $crumbs->addTextCrumb(pht('Step %d', $id));
     $crumbs->setBorder(true);
     $header = id(new PHUIHeaderView())->setHeader(pht('Build Step %d: %s', $id, $step->getName()))->setHeaderIcon('fa-chevron-circle-right');
     $properties = $this->buildPropertyList($step, $field_list);
     $curtain = $this->buildCurtainView($step);
     $timeline = $this->buildTransactionTimeline($step, new HarbormasterBuildStepTransactionQuery());
     $timeline->setShouldTerminate(true);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setCurtain($curtain)->setMainColumn(array($properties, $timeline));
     return $this->newPage()->setTitle(pht('Step %d', $id))->setCrumbs($crumbs)->appendChild($view);
 }
function buildSetFieldTransaction($object, $field_key, $field_value, $template, $viewer)
{
    $role = PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS;
    $fields = PhabricatorCustomField::getObjectFields($object, $role)->setViewer($viewer)->readFieldsFromStorage($object)->getFields();
    $field = idx($fields, $field_key);
    $transaction_type = $field->getApplicationTransactionType();
    $xaction = id(clone $template)->setTransactionType($transaction_type);
    if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) {
        // For TYPE_CUSTOMFIELD transactions only, we provide the old value
        // as an input.
        $old_value = $field->getOldValueForApplicationTransactions();
        $xaction->setOldValue($old_value);
    }
    $field->getProxy()->setFieldValue($field_value);
    $new_value = $field->getNewValueForApplicationTransactions();
    $xaction->setNewValue($new_value);
    if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) {
        // For TYPE_CUSTOMFIELD transactions, add the field key in metadata.
        $xaction->setMetadataValue('customfield:key', $field->getFieldKey());
    }
    $metadata = $field->getApplicationTransactionMetadata();
    foreach ($metadata as $key => $value) {
        $xaction->setMetadataValue($key, $value);
    }
    return $xaction;
}
 protected function execute(ConduitAPIRequest $request)
 {
     $viewer = $request->getUser();
     $corpus = $request->getValue('corpus');
     $is_partial = $request->getValue('partial');
     $revision = new DifferentialRevision();
     $field_list = PhabricatorCustomField::getObjectFields($revision, DifferentialCustomField::ROLE_COMMITMESSAGE);
     $field_list->setViewer($viewer);
     $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit');
     $this->errors = array();
     $label_map = $this->buildLabelMap($field_list);
     $corpus_map = $this->parseCommitMessage($corpus, $label_map);
     $values = array();
     foreach ($corpus_map as $field_key => $text_value) {
         $field = idx($field_map, $field_key);
         if (!$field) {
             throw new Exception(pht('Parser emitted text value for field key "%s", but no such ' . 'field exists.', $field_key));
         }
         try {
             $values[$field_key] = $field->parseValueFromCommitMessage($text_value);
         } catch (DifferentialFieldParseException $ex) {
             $this->errors[] = pht('Error parsing field "%s": %s', $field->renderCommitMessageLabel(), $ex->getMessage());
         }
     }
     if (!$is_partial) {
         foreach ($field_map as $key => $field) {
             try {
                 $field->validateCommitMessageValue(idx($values, $key));
             } catch (DifferentialFieldValidationException $ex) {
                 $this->errors[] = pht('Invalid or missing field "%s": %s', $field->renderCommitMessageLabel(), $ex->getMessage());
             }
         }
     }
     return array('errors' => $this->errors, 'fields' => $values);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $blueprint = id(new DrydockBlueprintQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$blueprint) {
         return new Aphront404Response();
     }
     $title = $blueprint->getBlueprintName();
     $header = id(new PHUIHeaderView())->setHeader($title)->setUser($viewer)->setPolicyObject($blueprint);
     if ($blueprint->getIsDisabled()) {
         $header->setStatus('fa-ban', 'red', pht('Disabled'));
     } else {
         $header->setStatus('fa-check', 'bluegrey', pht('Active'));
     }
     $actions = $this->buildActionListView($blueprint);
     $properties = $this->buildPropertyListView($blueprint, $actions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Blueprint %d', $blueprint->getID()));
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $field_list = PhabricatorCustomField::getObjectFields($blueprint, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($viewer)->readFieldsFromStorage($blueprint);
     $field_list->appendFieldsToPropertyList($blueprint, $viewer, $properties);
     $resource_box = $this->buildResourceBox($blueprint);
     $authorizations_box = $this->buildAuthorizationsBox($blueprint);
     $timeline = $this->buildTransactionTimeline($blueprint, new DrydockBlueprintTransactionQuery());
     $timeline->setShouldTerminate(true);
     $log_query = id(new DrydockLogQuery())->withBlueprintPHIDs(array($blueprint->getPHID()));
     $log_box = $this->buildLogBox($log_query, $this->getApplicationURI("blueprint/{$id}/logs/query/all/"));
     return $this->buildApplicationPage(array($crumbs, $object_box, $resource_box, $authorizations_box, $log_box, $timeline), array('title' => $title));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     // Load all projects with "Sprint" in the name.
     $projects = id(new PhabricatorProjectQuery())->setViewer($viewer)->withDatasourceQuery('sprint')->execute();
     $rows = array();
     foreach ($projects as $project) {
         // We need the custom fields so we can pull out the start and end date
         // TODO: query in a loop is bad
         $field_list = PhabricatorCustomField::getObjectFields($project, PhabricatorCustomField::ROLE_EDIT);
         $field_list->setViewer($viewer);
         $field_list->readFieldsFromStorage($project);
         $aux_fields = $field_list->getFields();
         $start = idx($aux_fields, 'isdc:sprint:startdate')->getProxy()->getFieldValue();
         $end = idx($aux_fields, 'isdc:sprint:enddate')->getProxy()->getFieldValue();
         $rows[] = array('project' => phutil_tag('a', array('href' => '/burndown/view/' . $project->getId(), 'style' => 'font-weight:bold'), $project->getName()), 'start' => phabricator_datetime($start, $viewer), 'end' => phabricator_datetime($end, $viewer));
     }
     $projects_table = id(new AphrontTableView($rows))->setHeaders(array('Project/Sprint name', 'Start Date', 'End Date'))->setColumnClasses(array('wide', 'date', 'date'));
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Burndown List'));
     $help = id(new PHUIBoxView())->appendChild(phutil_tag('p', array(), "To have a project show up in this list, make sure it's name includes" . "\"sprint\" and then edit it to set the start and end date."))->addMargin(PHUI::MARGIN_LARGE);
     $box = id(new PHUIBoxView())->appendChild($projects_table)->addMargin(PHUI::MARGIN_LARGE);
     return $this->buildApplicationPage(array($crumbs, $help, $box), array('title' => array(pht('Burndown List')), 'device' => true));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $step = id(new HarbormasterBuildStepQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$step) {
         return new Aphront404Response();
     }
     $plan = $step->getBuildPlan();
     $plan_id = $plan->getID();
     $plan_uri = $this->getApplicationURI("plan/{$plan_id}/");
     $field_list = PhabricatorCustomField::getObjectFields($step, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($viewer)->readFieldsFromStorage($step);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Plan %d', $plan_id), $plan_uri);
     $crumbs->addTextCrumb(pht('Step %d', $id));
     $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Build Step %d: %s', $id, $step->getName()));
     $properties = $this->buildPropertyList($step, $field_list);
     $actions = $this->buildActionList($step);
     $properties->setActionList($actions);
     $box->addPropertyList($properties);
     $timeline = $this->buildTransactionTimeline($step, new HarbormasterBuildStepTransactionQuery());
     $timeline->setShouldTerminate(true);
     return $this->buildApplicationPage(array($crumbs, $box, $timeline), array('title' => pht('Step %d', $id)));
 }
 public function getCustomFieldList()
 {
     $field_list = PhabricatorCustomField::getObjectFields($this->project, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($this->viewer);
     $field_list->readFieldsFromStorage($this->project);
     return $field_list;
 }
 /**
  * @task apps
  */
 public static function getObjectFields(PhabricatorCustomFieldInterface $object, $role)
 {
     try {
         $attachment = $object->getCustomFields();
     } catch (PhabricatorDataNotAttachedException $ex) {
         $attachment = new PhabricatorCustomFieldAttachment();
         $object->attachCustomFields($attachment);
     }
     try {
         $field_list = $attachment->getCustomFieldList($role);
     } catch (PhabricatorCustomFieldNotAttachedException $ex) {
         $base_class = $object->getCustomFieldBaseClass();
         $spec = $object->getCustomFieldSpecificationForRole($role);
         if (!is_array($spec)) {
             $obj_class = get_class($object);
             throw new Exception("Expected an array from getCustomFieldSpecificationForRole() for " . "object of class '{$obj_class}'.");
         }
         $fields = PhabricatorCustomField::buildFieldList($base_class, $spec, $object);
         foreach ($fields as $key => $field) {
             if (!$field->shouldEnableForRole($role)) {
                 unset($fields[$key]);
             }
         }
         foreach ($fields as $field) {
             $field->setObject($object);
         }
         $field_list = new PhabricatorCustomFieldList($fields);
         $attachment->addCustomFieldList($role, $field_list);
     }
     return $field_list;
 }
 public function renderResultsList(array $requests, PhabricatorSavedQuery $query)
 {
     assert_instances_of($requests, 'ReleephRequest');
     $viewer = $this->getRequest()->getUser();
     // TODO: This is generally a bit sketchy, but we don't do this kind of
     // thing elsewhere at the moment. For the moment it shouldn't be hugely
     // costly, and we can batch things later. Generally, this commits fewer
     // sins than the old code did.
     $engine = id(new PhabricatorMarkupEngine())->setViewer($viewer);
     $list = array();
     foreach ($requests as $pull) {
         $field_list = PhabricatorCustomField::getObjectFields($pull, PhabricatorCustomField::ROLE_VIEW);
         $field_list->setViewer($viewer)->readFieldsFromStorage($pull);
         foreach ($field_list->getFields() as $field) {
             if ($field->shouldMarkup()) {
                 $field->setMarkupEngine($engine);
             }
         }
         $list[] = id(new ReleephRequestView())->setUser($viewer)->setCustomFields($field_list)->setPullRequest($pull)->setIsListView(true);
     }
     // This is quite sketchy, but the list has not actually rendered yet, so
     // this still allows us to batch the markup rendering.
     $engine->process();
     return $list;
 }
 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() . '/';
     $field_list = PhabricatorCustomField::getObjectFields($user, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($viewer)->readFieldsFromStorage($user);
     $validation_exception = null;
     if ($request->isFormPost()) {
         $xactions = $field_list->buildFieldTransactionsFromRequest(new PhabricatorUserTransaction(), $request);
         $editor = id(new PhabricatorUserProfileEditor())->setActor($viewer)->setContentSource(PhabricatorContentSource::newFromRequest($request))->setContinueOnNoEffect(true);
         try {
             $editor->applyTransactions($user, $xactions);
             return id(new AphrontRedirectResponse())->setURI($profile_uri);
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $validation_exception = $ex;
         }
     }
     $title = pht('Edit Profile');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($user->getUsername(), $profile_uri);
     $crumbs->addTextCrumb($title);
     $form = id(new AphrontFormView())->setUser($viewer);
     $field_list->appendFieldsToForm($form);
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($profile_uri)->setValue(pht('Save Profile')));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Edit Profile'))->setValidationException($validation_exception)->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => $title));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $blueprint = id(new DrydockBlueprintQuery())->setViewer($viewer)->withIDs(array($this->id))->executeOne();
     if (!$blueprint) {
         return new Aphront404Response();
     }
     $title = $blueprint->getBlueprintName();
     $header = id(new PHUIHeaderView())->setHeader($title)->setUser($viewer)->setPolicyObject($blueprint);
     $actions = $this->buildActionListView($blueprint);
     $properties = $this->buildPropertyListView($blueprint, $actions);
     $blueprint_uri = 'blueprint/' . $blueprint->getID() . '/';
     $blueprint_uri = $this->getApplicationURI($blueprint_uri);
     $resources = id(new DrydockResourceQuery())->withBlueprintPHIDs(array($blueprint->getPHID()))->setViewer($viewer)->execute();
     $resource_list = id(new DrydockResourceListView())->setUser($viewer)->setResources($resources)->render();
     $resource_list->setNoDataString(pht('This blueprint has no resources.'));
     $pager = new AphrontPagerView();
     $pager->setURI(new PhutilURI($blueprint_uri), 'offset');
     $pager->setOffset($request->getInt('offset'));
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Blueprint %d', $blueprint->getID()));
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $field_list = PhabricatorCustomField::getObjectFields($blueprint, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($viewer)->readFieldsFromStorage($blueprint);
     $field_list->appendFieldsToPropertyList($blueprint, $viewer, $properties);
     $timeline = $this->buildTransactionTimeline($blueprint, new DrydockBlueprintTransactionQuery());
     $timeline->setShouldTerminate(true);
     return $this->buildApplicationPage(array($crumbs, $object_box, $resource_list, $timeline), array('title' => $title));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $request->validateCSRF();
     $pull = id(new ReleephRequestQuery())->setViewer($viewer)->withIDs(array($this->requestID))->executeOne();
     if (!$pull) {
         return new Aphront404Response();
     }
     $branch = $pull->getBranch();
     $product = $branch->getProduct();
     $action = $this->action;
     $origin_uri = '/' . $pull->getMonogram();
     $editor = id(new ReleephRequestTransactionalEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
     $xactions = array();
     switch ($action) {
         case 'want':
         case 'pass':
             static $action_map = array('want' => ReleephRequest::INTENT_WANT, 'pass' => ReleephRequest::INTENT_PASS);
             $intent = $action_map[$action];
             $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_USER_INTENT)->setMetadataValue('isAuthoritative', $product->isAuthoritative($viewer))->setNewValue($intent);
             break;
         case 'mark-manually-picked':
         case 'mark-manually-reverted':
             if ($pull->getRequestUserPHID() === $viewer->getPHID() || $product->isAuthoritative($viewer)) {
                 // We're all good!
             } else {
                 throw new Exception(pht("Bug! Only pushers or the requestor can manually change a " . "request's in-branch status!"));
             }
             if ($action === 'mark-manually-picked') {
                 $in_branch = 1;
                 $intent = ReleephRequest::INTENT_WANT;
             } else {
                 $in_branch = 0;
                 $intent = ReleephRequest::INTENT_PASS;
             }
             $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_USER_INTENT)->setMetadataValue('isManual', true)->setMetadataValue('isAuthoritative', true)->setNewValue($intent);
             $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_MANUAL_IN_BRANCH)->setNewValue($in_branch);
             break;
         default:
             throw new Exception(pht('Unknown or unimplemented action %s.', $action));
     }
     $editor->applyTransactions($pull, $xactions);
     if ($request->getBool('render')) {
         $field_list = PhabricatorCustomField::getObjectFields($pull, PhabricatorCustomField::ROLE_VIEW);
         $field_list->setViewer($viewer)->readFieldsFromStorage($pull);
         // TODO: This should be more modern and general.
         $engine = id(new PhabricatorMarkupEngine())->setViewer($viewer);
         foreach ($field_list->getFields() as $field) {
             if ($field->shouldMarkup()) {
                 $field->setMarkupEngine($engine);
             }
         }
         $engine->process();
         $pull_box = id(new ReleephRequestView())->setUser($viewer)->setCustomFields($field_list)->setPullRequest($pull)->setIsListView(true);
         return id(new AphrontAjaxResponse())->setContent(array('markup' => hsprintf('%s', $pull_box)));
     }
     return id(new AphrontRedirectResponse())->setURI($origin_uri);
 }
 private function buildPropertyView(PhabricatorUser $user, PhabricatorActionListView $actions)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setObject($user)->setActionList($actions);
     $field_list = PhabricatorCustomField::getObjectFields($user, PhabricatorCustomField::ROLE_VIEW);
     $field_list->appendFieldsToPropertyList($user, $viewer, $view);
     return $view;
 }
 protected function buildAlmanacPropertiesTable(AlmanacPropertyInterface $object)
 {
     $viewer = $this->getViewer();
     $properties = $object->getAlmanacProperties();
     $this->requireResource('almanac-css');
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $object, PhabricatorPolicyCapability::CAN_EDIT);
     $field_list = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_DEFAULT);
     // Before reading values from the object, read defaults.
     $defaults = mpull($field_list->getFields(), 'getValueForStorage', 'getFieldKey');
     $field_list->setViewer($viewer)->readFieldsFromStorage($object);
     Javelin::initBehavior('phabricator-tooltips', array());
     $icon_builtin = id(new PHUIIconView())->setIcon('fa-circle')->addSigil('has-tooltip')->setMetadata(array('tip' => pht('Builtin Property'), 'align' => 'E'));
     $icon_custom = id(new PHUIIconView())->setIcon('fa-circle-o grey')->addSigil('has-tooltip')->setMetadata(array('tip' => pht('Custom Property'), 'align' => 'E'));
     $builtins = $object->getAlmanacPropertyFieldSpecifications();
     // Sort fields so builtin fields appear first, then fields are ordered
     // alphabetically.
     $fields = $field_list->getFields();
     $fields = msort($fields, 'getFieldKey');
     $head = array();
     $tail = array();
     foreach ($fields as $field) {
         $key = $field->getFieldKey();
         if (isset($builtins[$key])) {
             $head[$key] = $field;
         } else {
             $tail[$key] = $field;
         }
     }
     $fields = $head + $tail;
     $rows = array();
     foreach ($fields as $key => $field) {
         $value = $field->getValueForStorage();
         $is_builtin = isset($builtins[$key]);
         $delete_uri = $this->getApplicationURI('property/delete/');
         $delete_uri = id(new PhutilURI($delete_uri))->setQueryParams(array('objectPHID' => $object->getPHID(), 'key' => $key));
         $edit_uri = $this->getApplicationURI('property/edit/');
         $edit_uri = id(new PhutilURI($edit_uri))->setQueryParams(array('objectPHID' => $object->getPHID(), 'key' => $key));
         $delete = javelin_tag('a', array('class' => $can_edit ? 'button grey small' : 'button grey small disabled', 'sigil' => 'workflow', 'href' => $delete_uri), $is_builtin ? pht('Reset') : pht('Delete'));
         $default = idx($defaults, $key);
         $is_default = $default !== null && $default === $value;
         $display_value = PhabricatorConfigJSON::prettyPrintJSON($value);
         if ($is_default) {
             $display_value = phutil_tag('span', array('class' => 'almanac-default-property-value'), $display_value);
         }
         $display_key = $key;
         if ($can_edit) {
             $display_key = javelin_tag('a', array('href' => $edit_uri, 'sigil' => 'workflow'), $display_key);
         }
         $rows[] = array($is_builtin ? $icon_builtin : $icon_custom, $display_key, $display_value, $delete);
     }
     $table = id(new AphrontTableView($rows))->setNoDataString(pht('No properties.'))->setHeaders(array(null, pht('Name'), pht('Value'), null))->setColumnClasses(array(null, null, 'wide', 'action'));
     $phid = $object->getPHID();
     $add_uri = $this->getApplicationURI("property/edit/?objectPHID={$phid}");
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $object, PhabricatorPolicyCapability::CAN_EDIT);
     $add_button = id(new PHUIButtonView())->setTag('a')->setHref($add_uri)->setWorkflow(true)->setDisabled(!$can_edit)->setText(pht('Add Property'))->setIcon('fa-plus');
     $header = id(new PHUIHeaderView())->setHeader(pht('Properties'))->addActionLink($add_button);
     return id(new PHUIObjectBoxView())->setHeader($header)->setTable($table);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $object = id(new PhabricatorObjectQuery())->setViewer($viewer)->withPHIDs(array($request->getStr('objectPHID')))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$object) {
         return new Aphront404Response();
     }
     if (!$object instanceof AlmanacPropertyInterface) {
         return new Aphront404Response();
     }
     $key = $request->getStr('key');
     if (!strlen($key)) {
         return new Aphront404Response();
     }
     $cancel_uri = $object->getURI();
     $builtins = $object->getAlmanacPropertyFieldSpecifications();
     $is_builtin = isset($builtins[$key]);
     if ($is_builtin) {
         // This is a builtin property, so we're going to reset it to the
         // default value.
         $field_list = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_DEFAULT);
         // Note that we're NOT loading field values from the object: we just want
         // to get the field's default value so we can reset it.
         $fields = $field_list->getFields();
         $field = $fields[$key];
         $is_delete = false;
         $new_value = $field->getValueForStorage();
         // Now, load the field to get the old value.
         $field_list->setViewer($viewer)->readFieldsFromStorage($object);
         $old_value = $field->getValueForStorage();
         $title = pht('Reset Property');
         $body = pht('Reset this property to its default value?');
         $submit_text = pht('Reset');
     } else {
         // This is a custom property, so we're going to delete it outright.
         $is_delete = true;
         $old_value = $object->getAlmanacPropertyValue($key);
         $new_value = null;
         $title = pht('Delete Property');
         $body = pht('Delete this property? TODO: DOES NOT WORK YET');
         $submit_text = pht('Delete');
     }
     $validation_exception = null;
     if ($request->isFormPost()) {
         $xaction = $object->getApplicationTransactionTemplate()->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)->setMetadataValue('customfield:key', $key)->setOldValue($old_value)->setNewValue($new_value);
         // TODO: We aren't really deleting properties that we claim to delete
         // yet, but that needs to be specialized a little bit.
         $editor = $object->getApplicationTransactionEditor()->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true);
         try {
             $editor->applyTransactions($object, array($xaction));
             return id(new AphrontRedirectResponse())->setURI($cancel_uri);
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $validation_exception = $ex;
         }
     }
     return $this->newDialog()->setTitle($title)->setValidationException($validation_exception)->addHiddenInput('objectPHID', $object->getPHID())->addHiddenInput('key', $key)->appendParagraph($body)->addCancelButton($cancel_uri)->addSubmitButton($submit_text);
 }
 private function loadCustomFields()
 {
     if ($this->fields === null) {
         $field_list = PhabricatorCustomField::getObjectFields($this, PhabricatorCustomField::ROLE_VIEW);
         $field_list->readFieldsFromStorage($this);
         $this->fields = $field_list->getFields();
     }
     return $this->fields;
 }
 private function buildPropertyListView(PhabricatorProject $project)
 {
     $viewer = $this->getViewer();
     $view = id(new PHUIPropertyListView())->setUser($viewer);
     $view->addProperty(pht('Looks Like'), $viewer->renderHandle($project->getPHID())->setAsTag(true));
     $field_list = PhabricatorCustomField::getObjectFields($project, PhabricatorCustomField::ROLE_VIEW);
     $field_list->appendFieldsToPropertyList($project, $viewer, $view);
     return $view;
 }
 public function shouldEnableForRole($role)
 {
     switch ($role) {
         case self::ROLE_COMMITMESSAGE:
             return $this->shouldAppearInCommitMessage();
         case self::ROLE_COMMITMESSAGEEDIT:
             return $this->shouldAppearInCommitMessage() && $this->shouldAllowEditInCommitMessage();
     }
     return parent::shouldEnableForRole($role);
 }
 public function runTask(PhabricatorUser $actor, PhabricatorWorkerBulkJob $job, PhabricatorWorkerBulkTask $task)
 {
     $object = id(new ManiphestTaskQuery())->setViewer($actor)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withPHIDs(array($task->getObjectPHID()))->needProjectPHIDs(true)->needSubscriberPHIDs(true)->executeOne();
     if (!$object) {
         return;
     }
     $field_list = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_EDIT);
     $field_list->readFieldsFromStorage($object);
     $actions = $job->getParameter('actions');
     $xactions = $this->buildTransactions($actions, $object);
     $editor = id(new ManiphestTransactionEditor())->setActor($actor)->setContentSource($job->newContentSource())->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($object, $xactions);
 }
 private function buildPropertyView(PhabricatorUser $user)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setObject($user);
     $field_list = PhabricatorCustomField::getObjectFields($user, PhabricatorCustomField::ROLE_VIEW);
     $field_list->appendFieldsToPropertyList($user, $viewer, $view);
     if (!$view->hasAnyProperties()) {
         return null;
     }
     $view = id(new PHUIObjectBoxView())->appendChild($view)->addClass('project-view-properties');
     return $view;
 }
 public function processRequest()
 {
     $this->requireApplicationCapability(ManiphestBulkEditCapability::CAPABILITY);
     $request = $this->getRequest();
     $user = $request->getUser();
     $task_ids = $request->getArr('batch');
     $tasks = id(new ManiphestTaskQuery())->setViewer($user)->withIDs($task_ids)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     $actions = $request->getStr('actions');
     if ($actions) {
         $actions = json_decode($actions, true);
     }
     if ($request->isFormPost() && is_array($actions)) {
         foreach ($tasks as $task) {
             $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_EDIT);
             $field_list->readFieldsFromStorage($task);
             $xactions = $this->buildTransactions($actions, $task);
             if ($xactions) {
                 // TODO: Set content source to "batch edit".
                 $editor = id(new ManiphestTransactionEditor())->setActor($user)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($task, $xactions);
             }
         }
         $task_ids = implode(',', mpull($tasks, 'getID'));
         return id(new AphrontRedirectResponse())->setURI('/maniphest/?ids=' . $task_ids);
     }
     $handles = ManiphestTaskListView::loadTaskHandles($user, $tasks);
     $list = new ManiphestTaskListView();
     $list->setTasks($tasks);
     $list->setUser($user);
     $list->setHandles($handles);
     $template = new AphrontTokenizerTemplateView();
     $template = $template->render();
     $projects_source = new PhabricatorProjectDatasource();
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     $owner_source = new PhabricatorTypeaheadOwnerDatasource();
     require_celerity_resource('maniphest-batch-editor');
     Javelin::initBehavior('maniphest-batch-editor', array('root' => 'maniphest-batch-edit-form', 'tokenizerTemplate' => $template, 'sources' => array('project' => array('src' => $projects_source->getDatasourceURI(), 'placeholder' => $projects_source->getPlaceholderText()), 'owner' => array('src' => $owner_source->getDatasourceURI(), 'placeholder' => $owner_source->getPlaceholderText(), 'limit' => 1), 'cc' => array('src' => $mailable_source->getDatasourceURI(), 'placeholder' => $mailable_source->getPlaceholderText())), 'input' => 'batch-form-actions', 'priorityMap' => ManiphestTaskPriority::getTaskPriorityMap(), 'statusMap' => ManiphestTaskStatus::getTaskStatusMap()));
     $form = new AphrontFormView();
     $form->setUser($user);
     $form->setID('maniphest-batch-edit-form');
     foreach ($tasks as $task) {
         $form->appendChild(phutil_tag('input', array('type' => 'hidden', 'name' => 'batch[]', 'value' => $task->getID())));
     }
     $form->appendChild(phutil_tag('input', array('type' => 'hidden', 'name' => 'actions', 'id' => 'batch-form-actions')));
     $form->appendChild(phutil_tag('p', array(), pht('These tasks will be edited:')));
     $form->appendChild($list);
     $form->appendChild(id(new AphrontFormInsetView())->setTitle('Actions')->setRightButton(javelin_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'add-action', 'mustcapture' => true), pht('Add Another Action')))->setContent(javelin_tag('table', array('sigil' => 'maniphest-batch-actions', 'class' => 'maniphest-batch-actions-table'), '')))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Update Tasks'))->addCancelButton('/maniphest/'));
     $title = pht('Batch Editor');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Batch Edit Tasks'))->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => $title, 'device' => false));
 }
 public function getFieldValuesForConduit($object)
 {
     // TODO: This is currently very inefficient. We should bulk-load these
     // field values instead.
     $fields = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_CONDUIT);
     $fields->setViewer($this->getViewer())->readFieldsFromStorage($object);
     $map = array();
     foreach ($fields->getFields() as $field) {
         $key = $field->getModernFieldKey();
         $map[$key] = $field->getConduitDictionaryValue();
     }
     return $map;
 }
 private function buildPropertyListView(PhabricatorProject $project)
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setObject($project);
     $field_list = PhabricatorCustomField::getObjectFields($project, PhabricatorCustomField::ROLE_VIEW);
     $field_list->appendFieldsToPropertyList($project, $viewer, $view);
     if ($view->isEmpty()) {
         return null;
     }
     $view = id(new PHUIBoxView())->setColor(PHUIBoxView::GREY)->appendChild($view)->addClass('project-view-properties');
     return $view;
 }
 public function indexFulltextObject($object, PhabricatorSearchAbstractDocument $document)
 {
     // Rebuild the ApplicationSearch indexes. These are internal and not part
     // of the fulltext search, but putting them in this workflow allows users
     // to use the same tools to rebuild the indexes, which is easy to
     // understand.
     $field_list = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_DEFAULT);
     $field_list->setViewer($this->getViewer());
     $field_list->readFieldsFromStorage($object);
     // Rebuild ApplicationSearch indexes.
     $field_list->rebuildIndexes($object);
     // Rebuild global search indexes.
     $field_list->updateAbstractDocument($document);
 }
 /**
  * @phutil-external-symbol class PHPExcel
  * @phutil-external-symbol class PHPExcel_IOFactory
  * @phutil-external-symbol class PHPExcel_Style_NumberFormat
  * @phutil-external-symbol class PHPExcel_Cell_DataType
  */
 public function buildWorkbook(PHPExcel $workbook, array $tasks, array $handles, PhabricatorUser $user)
 {
     $sheet = $workbook->setActiveSheetIndex(0);
     $sheet->setTitle(pht('Tasks'));
     $widths = array(null, 15, null, 10, 15, 15, 60, 30, 20, 100);
     foreach ($widths as $col => $width) {
         if ($width !== null) {
             $sheet->getColumnDimension($this->col($col))->setWidth($width);
         }
     }
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     $pri_map = ManiphestTaskPriority::getTaskPriorityMap();
     $date_format = null;
     $rows = array();
     $rows[] = array(pht('ID'), pht('Owner'), pht('Status'), pht('Priority'), pht('Date Created'), pht('Date Updated'), pht('Deadline'), pht('Title'), pht('Projects'), pht('Description'));
     $is_date = array(false, false, false, false, true, true, true, false, false, false);
     $header_format = array('font' => array('bold' => true));
     foreach ($tasks as $task) {
         $task_owner = null;
         if ($task->getOwnerPHID()) {
             $task_owner = $handles[$task->getOwnerPHID()]->getName();
         }
         $projects = array();
         foreach ($task->getProjectPHIDs() as $phid) {
             $projects[] = $handles[$phid]->getName();
         }
         $projects = implode(', ', $projects);
         $custom_fields = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_VIEW);
         $custom_fields->setViewer($user)->readFieldsFromStorage($task);
         $fields = $custom_fields->getFields();
         $rows[] = array('T' . $task->getID(), $task_owner, idx($status_map, $task->getStatus(), '?'), idx($pri_map, $task->getPriority(), '?'), $this->computeExcelDate($task->getDateCreated()), $this->computeExcelDate($task->getDateModified()), $this->computeExcelDate($fields['std:maniphest:Deadline']->getValueForStorage()), $task->getTitle(), $projects, id(new PhutilUTF8StringTruncator())->setMaximumBytes(512)->truncateString($task->getDescription()));
     }
     foreach ($rows as $row => $cols) {
         foreach ($cols as $col => $spec) {
             $cell_name = $this->col($col) . ($row + 1);
             $cell = $sheet->setCellValue($cell_name, $spec, $return_cell = true);
             if ($row == 0) {
                 $sheet->getStyle($cell_name)->applyFromArray($header_format);
             }
             if ($is_date[$col]) {
                 $code = PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2;
                 $sheet->getStyle($cell_name)->getNumberFormat()->setFormatCode($code);
             } else {
                 $cell->setDataType(PHPExcel_Cell_DataType::TYPE_STRING);
             }
         }
     }
 }