diff --git a/resources/sql/autopatches/20140321.harbor.1.bxaction.sql b/resources/sql/autopatches/20140321.harbor.1.bxaction.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20140321.harbor.1.bxaction.sql @@ -0,0 +1,21 @@ +CREATE TABLE {$NAMESPACE}_harbormaster.harbormaster_buildsteptransaction ( + id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + phid VARCHAR(64) NOT NULL COLLATE utf8_bin, + authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, + objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, + viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, + editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, + commentPHID VARCHAR(64) COLLATE utf8_bin, + commentVersion INT UNSIGNED NOT NULL, + transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin, + oldValue LONGTEXT NOT NULL COLLATE utf8_bin, + newValue LONGTEXT NOT NULL COLLATE utf8_bin, + contentSource LONGTEXT NOT NULL COLLATE utf8_bin, + metadata LONGTEXT NOT NULL COLLATE utf8_bin, + dateCreated INT UNSIGNED NOT NULL, + dateModified INT UNSIGNED NOT NULL, + + UNIQUE KEY `key_phid` (phid), + KEY `key_object` (objectPHID) + +) ENGINE=InnoDB, COLLATE utf8_general_ci; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -712,7 +712,12 @@ 'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php', 'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php', 'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php', + 'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php', + 'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php', + 'HarbormasterBuildStepEditor' => 'applications/harbormaster/editor/HarbormasterBuildStepEditor.php', 'HarbormasterBuildStepQuery' => 'applications/harbormaster/query/HarbormasterBuildStepQuery.php', + 'HarbormasterBuildStepTransaction' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStepTransaction.php', + 'HarbormasterBuildStepTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildStepTransactionQuery.php', 'HarbormasterBuildTarget' => 'applications/harbormaster/storage/build/HarbormasterBuildTarget.php', 'HarbormasterBuildTargetQuery' => 'applications/harbormaster/query/HarbormasterBuildTargetQuery.php', 'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php', @@ -3310,8 +3315,18 @@ array( 0 => 'HarbormasterDAO', 1 => 'PhabricatorPolicyInterface', + 2 => 'PhabricatorCustomFieldInterface', + ), + 'HarbormasterBuildStepCoreCustomField' => + array( + 0 => 'HarbormasterBuildStepCustomField', + 1 => 'PhabricatorStandardCustomFieldInterface', ), + 'HarbormasterBuildStepCustomField' => 'PhabricatorCustomField', + 'HarbormasterBuildStepEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'HarbormasterBuildStepTransaction' => 'PhabricatorApplicationTransaction', + 'HarbormasterBuildStepTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildTarget' => array( 0 => 'HarbormasterDAO', diff --git a/src/applications/harbormaster/controller/HarbormasterStepEditController.php b/src/applications/harbormaster/controller/HarbormasterStepEditController.php --- a/src/applications/harbormaster/controller/HarbormasterStepEditController.php +++ b/src/applications/harbormaster/controller/HarbormasterStepEditController.php @@ -27,85 +27,39 @@ $plan = $step->getBuildPlan(); $implementation = $step->getStepImplementation(); - $implementation->validateSettingDefinitions(); - $settings = $implementation->getSettings(); + + $field_list = PhabricatorCustomField::getObjectFields( + $step, + PhabricatorCustomField::ROLE_EDIT); + $field_list + ->setViewer($viewer) + ->readFieldsFromStorage($step); $errors = array(); + $validation_exception = null; if ($request->isFormPost()) { - foreach ($implementation->getSettingDefinitions() as $name => $opt) { - $readable_name = $this->getReadableName($name, $opt); - $value = $this->getValueFromRequest($request, $name, $opt['type']); - - // TODO: This won't catch any validation issues unless the field - // is missing completely. How should we check if the user is - // required to enter an integer? - if ($value === null) { - $errors[] = $readable_name.' is not valid.'; - } else { - $step->setDetail($name, $value); - } - } + $xactions = $field_list->buildFieldTransactionsFromRequest( + new HarbormasterBuildStepTransaction(), + $request); - if (!$errors) { - $step->save(); + $editor = id(new HarbormasterBuildStepEditor()) + ->setActor($viewer) + ->setContinueOnNoEffect(true) + ->setContentSourceFromRequest($request); + + try { + $editor->applyTransactions($step, $xactions); return id(new AphrontRedirectResponse()) ->setURI($this->getApplicationURI('plan/'.$plan->getID().'/')); + } catch (PhabricatorApplicationTransactionValidationException $ex) { + $validation_exception = $ex; } } $form = id(new AphrontFormView()) ->setUser($viewer); - // We need to render out all of the fields for the settings that - // the implementation has. - foreach ($implementation->getSettingDefinitions() as $name => $opt) { - if ($request->isFormPost()) { - $value = $this->getValueFromRequest($request, $name, $opt['type']); - } else { - $value = $settings[$name]; - } - - switch ($opt['type']) { - case BuildStepImplementation::SETTING_TYPE_STRING: - case BuildStepImplementation::SETTING_TYPE_INTEGER: - $control = id(new AphrontFormTextControl()) - ->setLabel($this->getReadableName($name, $opt)) - ->setName($name) - ->setValue($value); - break; - case BuildStepImplementation::SETTING_TYPE_BOOLEAN: - $control = id(new AphrontFormCheckboxControl()) - ->setLabel($this->getReadableName($name, $opt)) - ->setName($name) - ->setValue($value); - break; - case BuildStepImplementation::SETTING_TYPE_ARTIFACT: - $filter = $opt['artifact_type']; - $available_artifacts = - BuildStepImplementation::loadAvailableArtifacts( - $plan, - $step, - $filter); - $options = array(); - foreach ($available_artifacts as $key => $type) { - $options[$key] = $key; - } - $control = id(new AphrontFormSelectControl()) - ->setLabel($this->getReadableName($name, $opt)) - ->setName($name) - ->setValue($value) - ->setOptions($options); - break; - default: - throw new Exception("Unable to render field with unknown type."); - } - - if (isset($opt['description'])) { - $control->setCaption($opt['description']); - } - - $form->appendChild($control); - } + $field_list->appendFieldsToForm($form); $form->appendChild( id(new AphrontFormSubmitControl()) @@ -115,7 +69,7 @@ $box = id(new PHUIObjectBoxView()) ->setHeaderText('Edit Step: '.$implementation->getName()) - ->setValidationException(null) + ->setValidationException($validation_exception) ->setForm($form); $crumbs = $this->buildApplicationCrumbs(); @@ -127,11 +81,23 @@ $variables = $this->renderBuildVariablesTable(); + $xactions = id(new HarbormasterBuildStepTransactionQuery()) + ->setViewer($viewer) + ->withObjectPHIDs(array($step->getPHID())) + ->execute(); + + $xaction_view = id(new PhabricatorApplicationTransactionView()) + ->setUser($viewer) + ->setObjectPHID($step->getPHID()) + ->setTransactions($xactions) + ->setShouldTerminate(true); + return $this->buildApplicationPage( array( $crumbs, $box, $variables, + $xaction_view, ), array( 'title' => $implementation->getName(), @@ -139,31 +105,6 @@ )); } - public function getReadableName($name, $opt) { - $readable_name = $name; - if (isset($opt['name'])) { - $readable_name = $opt['name']; - } - return $readable_name; - } - - public function getValueFromRequest(AphrontRequest $request, $name, $type) { - switch ($type) { - case BuildStepImplementation::SETTING_TYPE_STRING: - case BuildStepImplementation::SETTING_TYPE_ARTIFACT: - return $request->getStr($name); - break; - case BuildStepImplementation::SETTING_TYPE_INTEGER: - return $request->getInt($name); - break; - case BuildStepImplementation::SETTING_TYPE_BOOLEAN: - return $request->getBool($name); - break; - default: - throw new Exception("Unsupported setting type '".$type."'."); - } - } - private function renderBuildVariablesTable() { $viewer = $this->getRequest()->getUser(); diff --git a/src/applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php b/src/applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php @@ -0,0 +1,41 @@ +getStepImplementation()->getFieldSpecifications(); + return PhabricatorStandardCustomField::buildStandardFields($this, $specs); + } + + public function shouldUseStorage() { + return false; + } + + public function readValueFromObject(PhabricatorCustomFieldInterface $object) { + $key = $this->getProxy()->getRawStandardFieldKey(); + $this->setValueFromStorage($object->getDetail($key)); + } + + public function applyApplicationTransactionInternalEffects( + PhabricatorApplicationTransaction $xaction) { + $object = $this->getObject(); + $key = $this->getProxy()->getRawStandardFieldKey(); + + $this->setValueFromApplicationTransactions($xaction->getNewValue()); + $value = $this->getValueForStorage(); + + $object->setDetail($key, $value); + } + + public function applyApplicationTransactionExternalEffects( + PhabricatorApplicationTransaction $xaction) { + return; + } + +} diff --git a/src/applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php b/src/applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php @@ -0,0 +1,6 @@ +setAncestorClass("BuildStepImplementation") + ->setAncestorClass('BuildStepImplementation') ->setConcreteOnly(true) ->selectAndLoadSymbols(); return ipull($symbols, 'name'); @@ -33,7 +26,7 @@ * The description of the implementation, based on the current settings. */ public function getDescription() { - return ''; + return $this->getGenericDescription(); } /** @@ -55,43 +48,12 @@ } /** - * Validate the current settings of this build step. - */ - public function validateSettings() { - return true; - } - - /** * Loads the settings for this build step implementation from a build * step or target. */ public final function loadSettings($build_object) { - $this->settings = array(); - $this->validateSettingDefinitions(); - foreach ($this->getSettingDefinitions() as $name => $opt) { - $this->settings[$name] = $build_object->getDetail($name); - } - return $this->settings; - } - - /** - * Validates that the setting definitions for this implementation are valid. - */ - public final function validateSettingDefinitions() { - foreach ($this->getSettingDefinitions() as $name => $opt) { - if (!isset($opt['type'])) { - throw new Exception( - 'Setting definition \''.$name. - '\' is missing type requirement.'); - } - } - } - - /** - * Return an array of settings for this step implementation. - */ - public function getSettingDefinitions() { - return array(); + $this->settings = $build_object->getDetails(); + return $this; } /** @@ -197,4 +159,8 @@ return call_user_func($function, $pattern, $argv); } + public function getFieldSpecifications() { + return array(); + } + } diff --git a/src/applications/harbormaster/step/CommandBuildStepImplementation.php b/src/applications/harbormaster/step/CommandBuildStepImplementation.php --- a/src/applications/harbormaster/step/CommandBuildStepImplementation.php +++ b/src/applications/harbormaster/step/CommandBuildStepImplementation.php @@ -74,22 +74,6 @@ } } - public function validateSettings() { - $settings = $this->getSettings(); - - if ($settings['command'] === null || !is_string($settings['command'])) { - return false; - } - if ($settings['hostartifact'] === null || - !is_string($settings['hostartifact'])) { - return false; - } - - // TODO: Check if the host artifact is provided by previous build steps. - - return true; - } - public function getArtifactInputs() { return array( array( @@ -100,19 +84,19 @@ ); } - public function getSettingDefinitions() { + public function getFieldSpecifications() { return array( 'command' => array( - 'name' => 'Command', - 'description' => 'The command to execute on the remote machine.', - 'type' => BuildStepImplementation::SETTING_TYPE_STRING), + 'name' => pht('Command'), + 'type' => 'text', + 'required' => true, + ), 'hostartifact' => array( - 'name' => 'Host Artifact', - 'description' => - 'The host artifact that determines what machine the command '. - 'will run on.', - 'type' => BuildStepImplementation::SETTING_TYPE_ARTIFACT, - 'artifact_type' => HarbormasterBuildArtifact::TYPE_HOST)); + 'name' => pht('Host'), + 'type' => 'text', + 'required' => true, + ), + ); } } diff --git a/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php --- a/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php @@ -34,10 +34,7 @@ $log_body = $build->createLog($build_target, $uri, 'http-body'); $start = $log_body->start(); - $method = 'POST'; - if ($settings['method'] !== '') { - $method = $settings['method']; - } + $method = nonempty(idx($settings, 'method'), 'POST'); list($status, $body, $headers) = id(new HTTPSFuture($uri)) ->setMethod($method) @@ -52,42 +49,17 @@ } } - public function validateSettings() { - $settings = $this->getSettings(); - - if ($settings['uri'] === null || !is_string($settings['uri'])) { - return false; - } - - $methods = array( - 'GET' => true, - 'POST' => true, - 'DELETE' => true, - 'PUT' => true, - ); - - $method = idx($settings, 'method'); - if (strlen($method)) { - if (empty($methods[$method])) { - return false; - } - } - - return true; - } - - public function getSettingDefinitions() { + public function getFieldSpecifications() { return array( 'uri' => array( - 'name' => 'URI', - 'description' => pht('The URI to request.'), - 'type' => BuildStepImplementation::SETTING_TYPE_STRING, + 'name' => pht('URI'), + 'type' => 'text', + 'required' => true, ), 'method' => array( - 'name' => 'Method', - 'description' => - pht('Request type. Should be GET, POST, PUT, or DELETE.'), - 'type' => BuildStepImplementation::SETTING_TYPE_STRING, + 'name' => pht('HTTP Method'), + 'type' => 'select', + 'options' => array_fuse(array('POST', 'GET', 'PUT', 'DELETE')), ), ); } diff --git a/src/applications/harbormaster/step/LeaseHostBuildStepImplementation.php b/src/applications/harbormaster/step/LeaseHostBuildStepImplementation.php --- a/src/applications/harbormaster/step/LeaseHostBuildStepImplementation.php +++ b/src/applications/harbormaster/step/LeaseHostBuildStepImplementation.php @@ -51,19 +51,6 @@ $artifact->save(); } - public function validateSettings() { - $settings = $this->getSettings(); - - if ($settings['name'] === null || !is_string($settings['name'])) { - return false; - } - if ($settings['platform'] === null || !is_string($settings['platform'])) { - return false; - } - - return true; - } - public function getArtifactOutputs() { return array( array( @@ -74,17 +61,19 @@ ); } - public function getSettingDefinitions() { + public function getFieldSpecifications() { return array( 'name' => array( - 'name' => 'Artifact Name', - 'description' => - 'The name of the artifact to reference in future build steps.', - 'type' => BuildStepImplementation::SETTING_TYPE_STRING), + 'name' => pht('Artifact Name'), + 'type' => 'text', + 'required' => true, + ), 'platform' => array( - 'name' => 'Platform', - 'description' => 'The platform of the host.', - 'type' => BuildStepImplementation::SETTING_TYPE_STRING)); + 'name' => pht('Platform'), + 'type' => 'text', + 'required' => true, + ), + ); } } diff --git a/src/applications/harbormaster/step/PublishFragmentBuildStepImplementation.php b/src/applications/harbormaster/step/PublishFragmentBuildStepImplementation.php --- a/src/applications/harbormaster/step/PublishFragmentBuildStepImplementation.php +++ b/src/applications/harbormaster/step/PublishFragmentBuildStepImplementation.php @@ -57,22 +57,6 @@ } } - public function validateSettings() { - $settings = $this->getSettings(); - - if ($settings['path'] === null || !is_string($settings['path'])) { - return false; - } - if ($settings['artifact'] === null || - !is_string($settings['artifact'])) { - return false; - } - - // TODO: Check if the file artifact is provided by previous build steps. - - return true; - } - public function getArtifactInputs() { return array( array( @@ -83,19 +67,19 @@ ); } - public function getSettingDefinitions() { + public function getFieldSpecifications() { return array( 'path' => array( - 'name' => 'Path', - 'description' => - 'The path of the fragment that will be published.', - 'type' => BuildStepImplementation::SETTING_TYPE_STRING), + 'name' => pht('Path'), + 'type' => 'text', + 'required' => true, + ), 'artifact' => array( - 'name' => 'File Artifact', - 'description' => - 'The file artifact that will be published to Phragment.', - 'type' => BuildStepImplementation::SETTING_TYPE_ARTIFACT, - 'artifact_type' => HarbormasterBuildArtifact::TYPE_FILE)); + 'name' => pht('File Artifact'), + 'type' => 'text', + 'required' => true, + ), + ); } } diff --git a/src/applications/harbormaster/step/SleepBuildStepImplementation.php b/src/applications/harbormaster/step/SleepBuildStepImplementation.php --- a/src/applications/harbormaster/step/SleepBuildStepImplementation.php +++ b/src/applications/harbormaster/step/SleepBuildStepImplementation.php @@ -25,24 +25,15 @@ sleep($settings['seconds']); } - public function validateSettings() { - $settings = $this->getSettings(); - - if ($settings['seconds'] === null) { - return false; - } - if (!is_int($settings['seconds'])) { - return false; - } - return true; - } - - public function getSettingDefinitions() { + public function getFieldSpecifications() { return array( 'seconds' => array( - 'name' => 'Seconds', - 'description' => 'The number of seconds to sleep for.', - 'type' => BuildStepImplementation::SETTING_TYPE_INTEGER)); + 'name' => pht('Seconds'), + 'type' => 'int', + 'required' => true, + 'caption' => pht('The number of seconds to sleep for.'), + ), + ); } } diff --git a/src/applications/harbormaster/step/UploadArtifactBuildStepImplementation.php b/src/applications/harbormaster/step/UploadArtifactBuildStepImplementation.php --- a/src/applications/harbormaster/step/UploadArtifactBuildStepImplementation.php +++ b/src/applications/harbormaster/step/UploadArtifactBuildStepImplementation.php @@ -51,25 +51,6 @@ $artifact->save(); } - public function validateSettings() { - $settings = $this->getSettings(); - - if ($settings['path'] === null || !is_string($settings['path'])) { - return false; - } - if ($settings['name'] === null || !is_string($settings['name'])) { - return false; - } - if ($settings['hostartifact'] === null || - !is_string($settings['hostartifact'])) { - return false; - } - - // TODO: Check if the host artifact is provided by previous build steps. - - return true; - } - public function getArtifactInputs() { return array( array( @@ -90,28 +71,24 @@ ); } - public function getSettingDefinitions() { + public function getFieldSpecifications() { return array( 'path' => array( - 'name' => 'Path', - 'description' => - 'The path of the file that should be retrieved. Note that on '. - 'Windows machines running FreeSSHD, this path will be relative '. - 'to the SFTP root path (configured under the SFTP tab). You can '. - 'not specify an absolute path for Windows machines.', - 'type' => BuildStepImplementation::SETTING_TYPE_STRING), + 'name' => pht('Path'), + 'type' => 'text', + 'required' => true, + ), 'name' => array( - 'name' => 'Local Name', - 'description' => - 'The name for the file when it is stored in Phabricator.', - 'type' => BuildStepImplementation::SETTING_TYPE_STRING), + 'name' => pht('Local Name'), + 'type' => 'text', + 'required' => true, + ), 'hostartifact' => array( - 'name' => 'Host Artifact', - 'description' => - 'The host artifact that determines what machine the command '. - 'will run on.', - 'type' => BuildStepImplementation::SETTING_TYPE_ARTIFACT, - 'artifact_type' => HarbormasterBuildArtifact::TYPE_HOST)); + 'name' => pht('Host Artifact'), + 'type' => 'text', + 'required' => true, + ), + ); } } diff --git a/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php b/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php --- a/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php +++ b/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php @@ -1,7 +1,9 @@ assertAttached($this->customFields); + } + + public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) { + $this->customFields = $fields; + return $this; + } + + } diff --git a/src/applications/harbormaster/storage/configuration/HarbormasterBuildStepTransaction.php b/src/applications/harbormaster/storage/configuration/HarbormasterBuildStepTransaction.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/storage/configuration/HarbormasterBuildStepTransaction.php @@ -0,0 +1,14 @@ +getImplementation(); - if (!$implementation->validateSettings()) { - $target->setTargetStatus(HarbormasterBuildTarget::STATUS_FAILED); - $target->save(); - } else { - $implementation->execute($build, $target); - $target->setTargetStatus(HarbormasterBuildTarget::STATUS_PASSED); - $target->save(); - } + $implementation->execute($build, $target); + $target->setTargetStatus(HarbormasterBuildTarget::STATUS_PASSED); + $target->save(); } catch (Exception $ex) { phlog($ex); diff --git a/src/applications/maniphest/field/ManiphestConfiguredCustomField.php b/src/applications/maniphest/field/ManiphestConfiguredCustomField.php --- a/src/applications/maniphest/field/ManiphestConfiguredCustomField.php +++ b/src/applications/maniphest/field/ManiphestConfiguredCustomField.php @@ -8,7 +8,7 @@ return 'maniphest'; } - public function createFields() { + public function createFields($object) { $config = PhabricatorEnv::getEnvConfig( 'maniphest.custom-field-definitions', array()); diff --git a/src/applications/people/customfield/PhabricatorUserConfiguredCustomField.php b/src/applications/people/customfield/PhabricatorUserConfiguredCustomField.php --- a/src/applications/people/customfield/PhabricatorUserConfiguredCustomField.php +++ b/src/applications/people/customfield/PhabricatorUserConfiguredCustomField.php @@ -8,7 +8,7 @@ return 'user'; } - public function createFields() { + public function createFields($object) { return PhabricatorStandardCustomField::buildStandardFields( $this, PhabricatorEnv::getEnvConfig('user.custom-field-definitions', array())); diff --git a/src/applications/project/customfield/PhabricatorProjectConfiguredCustomField.php b/src/applications/project/customfield/PhabricatorProjectConfiguredCustomField.php --- a/src/applications/project/customfield/PhabricatorProjectConfiguredCustomField.php +++ b/src/applications/project/customfield/PhabricatorProjectConfiguredCustomField.php @@ -8,7 +8,7 @@ return 'project'; } - public function createFields() { + public function createFields($object) { return PhabricatorStandardCustomField::buildStandardFields( $this, PhabricatorEnv::getEnvConfig( diff --git a/src/applications/project/customfield/PhabricatorProjectDescriptionField.php b/src/applications/project/customfield/PhabricatorProjectDescriptionField.php --- a/src/applications/project/customfield/PhabricatorProjectDescriptionField.php +++ b/src/applications/project/customfield/PhabricatorProjectDescriptionField.php @@ -3,7 +3,7 @@ final class PhabricatorProjectDescriptionField extends PhabricatorProjectStandardCustomField { - public function createFields() { + public function createFields($object) { return PhabricatorStandardCustomField::buildStandardFields( $this, array( diff --git a/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php b/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php --- a/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php +++ b/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php @@ -43,9 +43,14 @@ foreach ($faux_spec as $key => $spec) { unset($faux_spec[$key]['disabled']); } + + // TODO: We might need to build a real object here eventually. + $faux_object = null; + $fields = PhabricatorCustomField::buildFieldList( $field_base_class, - $faux_spec); + $faux_spec, + $faux_object); $list_id = celerity_generate_unique_node_id(); $input_id = celerity_generate_unique_node_id(); diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php --- a/src/infrastructure/customfield/field/PhabricatorCustomField.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php @@ -60,7 +60,10 @@ "object of class '{$obj_class}'."); } - $fields = PhabricatorCustomField::buildFieldList($base_class, $spec); + $fields = PhabricatorCustomField::buildFieldList( + $base_class, + $spec, + $object); foreach ($fields as $key => $field) { if (!$field->shouldEnableForRole($role)) { @@ -97,7 +100,7 @@ /** * @task apps */ - public static function buildFieldList($base_class, array $spec) { + public static function buildFieldList($base_class, array $spec, $object) { $field_objects = id(new PhutilSymbolLoader()) ->setAncestorClass($base_class) ->loadObjects(); @@ -106,7 +109,7 @@ $from_map = array(); foreach ($field_objects as $field_object) { $current_class = get_class($field_object); - foreach ($field_object->createFields() as $field) { + foreach ($field_object->createFields($object) as $field) { $key = $field->getFieldKey(); if (isset($fields[$key])) { $original_class = $from_map[$key]; @@ -200,10 +203,11 @@ * For general implementations, the general field implementation can return * multiple field instances here. * + * @param object The object to create fields for. * @return list List of fields. * @task core */ - public function createFields() { + public function createFields($object) { return array($this); } @@ -239,9 +243,9 @@ * @task core */ public function shouldEnableForRole($role) { - if ($this->proxy) { - return $this->proxy->shouldEnableForRole($role); - } + + // NOTE: All of these calls proxy individually, so we don't need to + // proxy this call as a whole. switch ($role) { case self::ROLE_APPLICATIONTRANSACTIONS: diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -3,6 +3,7 @@ abstract class PhabricatorStandardCustomField extends PhabricatorCustomField { + private $rawKey; private $fieldKey; private $fieldName; private $fieldValue; @@ -40,6 +41,7 @@ $template = clone $template; $standard = id(clone $types[$type]) + ->setRawStandardFieldKey($key) ->setFieldKey($full_key) ->setFieldConfig($value) ->setApplicationField($template); @@ -142,6 +144,15 @@ return $this->required; } + public function setRawStandardFieldKey($raw_key) { + $this->rawKey = $raw_key; + return $this; + } + + public function getRawStandardFieldKey() { + return $this->rawKey; + } + /* -( PhabricatorCustomField )--------------------------------------------- */