Getting custom field list of another task when saving ManiphestTask

#1

Hello all,

i observed a strange (maybe a wanted) behaviour when using PhabricatorCustomField::getObjectFields() in applyApplicationTransactionInternalEffects in a custom field class.

Let’s assume the following:

  • myextension.blockedBy and myextension.blocks are both custom fields extending the ManiphestCustomField and setting a proxy of type PhabricatorStandardCustomFieldTokenizer storing PHIDs of tasks
  • When myextension.blockedBy is changed for Task A all relating tasks (identified by their PHID) shall have the PHID of Task A as the value of myextension.blocks

I added some code to the applyApplicationTransactionInternalEffects method inside the myextension.blockedBy custom field class, looking like this (some parts which are not necessary for this question are taken out):

public function applyApplicationTransactionInternalEffects(
        PhabricatorApplicationTransaction $xaction)
    {
        if ($this->getProxy()) {
            /* Check for needed blocks assignment */
        $blocks_tasks_phids = json_decode($xaction->getNewValue());
        if (!empty($blocks_tasks_phids)) {
/* Walk and get tasks */
            foreach ($blocks_tasks_phids as $blocks_task_phid) {
                $blocks_task = id(new ManiphestTaskQuery())
                    ->setViewer($this->getViewer())
                    ->needProjectPHIDs(true)
                    ->withPHIDs(array($blocks_task_phid))
                    ->executeOne();

$blocked_field_list = PhabricatorCustomField::getObjectFields(
                            $blocks_task,
                            PhabricatorCustomField::ROLE_EDIT
                        );

$blocked_field_list->setViewer($this->getViewer())
                        ->readFieldsFromStorage($blocked_task);
}

            /* Do transaction */
            return $this->getProxy()->applyApplicationTransactionInternalEffects($xaction);
        }

        return;
    }

Everything works fine, the $blocks_task get the right task, the $blocked_field_list is filled correctly etc. But somehow as soon as i do this block of code

$blocked_field_list = PhabricatorCustomField::getObjectFields(
                            $blocks_task,
                            PhabricatorCustomField::ROLE_EDIT
                        );

the transaction to Task A for the field myextension.blockedBy is not saved into database. I get an email saying that Task A was edited and it has the right “newValue” inside it etc. but the actual transaction is NOT taken out.

As an example: let’s assume that Task A has Task B and Task C set as myextension.blockedBy. When i know edit Task A and delete Task C from the myextension.blockedBy field and hit the “Save changes” button everythign wents fine regarding the WebUI but Task A still have Task B AND Task C as myextension.blockedBy value. As soon as i take out the PhabricatorCustomField::getObjectFields() part from the applyApplicationTransactionInternalEffects function everything works fine again.

Is this a known behaviour, is it wanted, am i doing anything wrong?

Thanks and take care
Florian