Page MenuHomePhorge

Drag & Drop Task Cover Image: also attach

Authored by valerio.bozzolan on Nov 20 2023, 09:06.
Referenced Files
F2198740: D25475.1716392819.diff
Tue, May 21, 15:46
F2198681: D25475.1716383860.diff
Tue, May 21, 13:17
Unknown Object (File)
Mon, May 20, 11:47
Unknown Object (File)
Mon, May 20, 10:43
Unknown Object (File)
Mon, May 20, 10:21
Unknown Object (File)
Mon, May 20, 09:01
Unknown Object (File)
Mon, May 20, 05:52
Unknown Object (File)
Mon, May 20, 05:51
"Mountain of Wealth" token, awarded by 20after4.



After this change, the cover image is finally always visible to others (to people who can see the Task)
instead of being visible only to yourself.

Example conversation before this change:

  • Anna: (uploads a nice Cover Image on the Task, using drag & drop from the Workboard)
  • Bob: Thanks! But I cannot see that image. Please change visibility.
  • Anna: Ouch! How?
  • Bob: I don't know. Try Files > your File > Edit > Set Visibility > Something that includes "Bob".
  • Anna: Done. Do you see my image now? (Spoiler: it's a green pepper)
  • Bob: Yes and no. I mean, I can see the original file, but not from the Workboard.
  • Anna: Uh? Have you tried refreshing your cache?
  • Bob: Yes. Still invisible from Workboard.
  • Anna: Maybe you have to change Defaults Permissions of the "Files" Application, to have "All Users"
  • Bob: That is a bit invasive. Let's try. I changed the Files policy globally. Try re-uploading your image again.
  • Anna: Done. Do you see it now?
  • Bob: Yes! I can finally see it now, also from the Workboard.

Example conversation after this change:

  • Anna: (uploads a nice Cover Image on the Task, using drag & drop from the Workboard)

Done! So, after this change, everything works as expected. Every task participant can see that image,
and nobody starts a nonsense conversation, and nobody needs to do random experiments with
default application policies.

So, after this change:

  • the original file is attached to the Task
  • the cover image is not orphan anymore, but mentioned in the "Transforms" of the original file
  • the cover image so now inherits the original file policies

So, Task participants can finally see that cover image (transform), since it comes from a file,
and that file is attached to the Task, and since they can see that Task.

For a micro-optimization, this change refactors a bit PhabricatorFile.

You can still work in object-oriented:


But now you can also work directly with PHIDs, if necessary:

PhabricatorFile::attachFileToObject($file_phid, $task_phid)

This patch somehow improves T15768.

Closes T15163
Closes T15703

Test Plan

Visit a Workboard with a Column and a Task. Then:

  1. Drag & Drop GNU.png from your computer to that Task
  2. Drag & Drop GNU.png again there
  3. Drag & Drop Linux.png to that Task
  4. Drag & Drop Linux.png again
  5. No nuclear implosion.
  6. In all cases Task participants can see your Cover Image.

Diff Detail

rP Phorge
Lint Not Applicable
Tests Not Applicable

Event Timeline

valerio.bozzolan planned changes to this revision.EditedNov 22 2023, 12:10

This partially fixes the problem:

  • the file is now visible to Task participants, but
  • the file file transform is still not visible as Cover Image for some interesting reasons

Probably, this could also be done inside an expandTransaction method in ManiphestTransactionEditor. But I'm not bold enough to generalize this. Thanks for tips.


🔶 I think that this connection should be executed as default by PhabricatorTransformedFile executeTransform() as default. But I'm not sure, and I also don't know how to do that in that way. Thanks for any counter-idea.

ready for review, flagged the thing as side-effect


Looking at PhabricatorFileTestCase it seems normal to do this kind of things manually.

valerio.bozzolan edited the summary of this revision. (Show Details)

beautified even more - all logic inside the Transaction itself

The change looks reasonable though I’m not familiar at this level of the database schema design

All of this should maybe go under "applyExternalEffects()", but I can't find any doc that explains what should go there. Looks like external runs after all the internal and the object being saved, and before final. 🤷‍♂️

All of this should maybe go under "applyExternalEffects()"

Uhm. Let's process split this in two considerations:

  1. About the line new PhabricatorTransformedFile(): since that transform needs to be created as internal effect, it's probably OK to make it non-orphan as internal effect
  2. About the line $file->attachToObject($object->getPHID()): this may sound a good candidate for the applyExternalEffects() since it really changes something unrelated from the Task - maybe I can play with $object->getProperty('cover.filePHID')

I don't know because maybe then we should execute the same File query to check if the user has enough permissions to see that file 🤔 to just attach it to the file. (edited: or maybe not?)

Unrelated random overview:

  • PhabricatorProjectColumnStatusTransaction::applyExternalEffects() - updates a Trigger
  • PhabricatorUserApproveTransaction::applyExternalEffects() - sends email
  • PhabricatorUserUsernameTransaction::applyExternalEffects() - resets a cache
  • HarbormasterBuildMessageAbortTransaction::applyExternalEffects() - release artifacts
  • PhabricatorCalendarImportDeleteTransaction::applyExternalEffects() - destroy child objects
  • PhabricatorProjectColumnTriggerTransaction::applyExternalEffects() - index things

But look at PhabricatorFileDeleteTransaction that has applyInternalEffects() that creates an external Task runner 🤔

Anyway I'll try - thanks

introduce a nice applyExternalEffect() to change external things (the orginal file)

For performance reasons, created a static method that does not require a File object just to receive its phid... maybe nice :D

add minor comment - ready again - tested

Thanks again avivey. I liked the idea of using applyExternalEffects(). I have not found a way to do it efficiently, without introducing another static method.

Thanks for any honest comment and tip.

Pending that small inline, lgtm.


For extra safety, let's add a check for phid_get_type($file_phid) === PHID_TYPE_FILE here.

This revision is now accepted and ready to land.Sat, Apr 27, 07:00
  • add hardening suggested by dear avivey
  • add unit test for the new low-level function and its crash