@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add a Before-Destruction Engine

Summary:
Allow extensions to run hooks *before* an object is destroyed.

This would easily allow to do things like:

- Before you actually destroy a profile picture, find its active usages
and set the builtin profile image.
This is our core need to be able to fix T16074.
- Before you actually destroy something at midnight, allow extensions
to throw violently and effectively impede destruction saying
for example "please go to sleep first" in the exception message, visible
from command line.
This specific thing is not currently required but theoretically works.
- Before you actually destroy a generic object, you can still query
its dependent items, before the destruction of the object.
This is particularly useful if you want to use Query methods,
which often require a fully functioning parent object.
This last specific thing is not currently required but theoretically works.
- Before you actually destroy a generic object, you can still
destroy something else using the PhabricatorDestructionEngine.
This last specific thing is not currently required but theoretically works.

This new engine is to be considered unstable.
If you implement this class please contact Phorge at T16079 even if the task is closed.

Closes T16079

Ref T16074

Test Plan: Try to destroy something (./bin/remove destroy). Absolutely no regressions.

Reviewers: O1 Blessed Committers, aklapper

Reviewed By: O1 Blessed Committers, aklapper

Subscribers: aklapper, mainframe98, tobiaswiese, Matthew, Cigaryno

Maniphest Tasks: T16079, T16074

Differential Revision: https://we.phorge.it/D26026

+96
+2
src/__phutil_library_map__.php
··· 2613 2613 'PhabricatorBarePageView' => 'view/page/PhabricatorBarePageView.php', 2614 2614 'PhabricatorBaseURISetupCheck' => 'applications/config/check/PhabricatorBaseURISetupCheck.php', 2615 2615 'PhabricatorBcryptPasswordHasher' => 'infrastructure/util/password/PhabricatorBcryptPasswordHasher.php', 2616 + 'PhabricatorBeforeDestructionEngineExtension' => 'applications/system/engine/PhabricatorBeforeDestructionEngineExtension.php', 2616 2617 'PhabricatorBinariesSetupCheck' => 'applications/config/check/PhabricatorBinariesSetupCheck.php', 2617 2618 'PhabricatorBitbucketAuthProvider' => 'applications/auth/provider/PhabricatorBitbucketAuthProvider.php', 2618 2619 'PhabricatorBoardColumnsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorBoardColumnsSearchEngineAttachment.php', ··· 8976 8977 'PhabricatorBarePageView' => 'AphrontPageView', 8977 8978 'PhabricatorBaseURISetupCheck' => 'PhabricatorSetupCheck', 8978 8979 'PhabricatorBcryptPasswordHasher' => 'PhabricatorPasswordHasher', 8980 + 'PhabricatorBeforeDestructionEngineExtension' => 'Phobject', 8979 8981 'PhabricatorBinariesSetupCheck' => 'PhabricatorSetupCheck', 8980 8982 'PhabricatorBitbucketAuthProvider' => 'PhabricatorOAuth1AuthProvider', 8981 8983 'PhabricatorBoardColumnsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
+83
src/applications/system/engine/PhabricatorBeforeDestructionEngineExtension.php
··· 1 + <?php 2 + 3 + /** 4 + * Abstract "Before Destruction Engine", 5 + * to fire a hook before something is permamently destroyed. 6 + * 7 + * This class is to be considered unstable and may receive variations 8 + * over time. If you want to use this engine or extend its features, please 9 + * share your use-case here, even if the task is closed: 10 + * https://we.phorge.it/T16079 11 + */ 12 + abstract class PhabricatorBeforeDestructionEngineExtension extends Phobject { 13 + 14 + /** 15 + * Get the extension internal key. 16 + * 17 + * @return string 18 + */ 19 + final public function getExtensionKey(): string { 20 + return $this->getPhobjectClassConstant('EXTENSIONKEY'); 21 + } 22 + 23 + /** 24 + * Get the extension human name. 25 + * 26 + * @return string 27 + */ 28 + abstract public function getExtensionName(): string; 29 + 30 + /** 31 + * Check if this extension supports a "Before Destruction" hook 32 + * on the specified object. 33 + * 34 + * The object is guaranteed to have a PHID and still exist but 35 + * will be destroyed later. 36 + * This method should not contain write operations. 37 + * This method exposes a PhabricatorDestructionEngine since it can give 38 + * useful info, but here you should not use it to destroy objects. 39 + * When this method returns true, the method beforeDestroyObject() 40 + * will be fired. 41 + * 42 + * @param PhabricatorDestructionEngine $destruction_engine 43 + * Available destruction engine 44 + * @param object $object 45 + * Object that will be destroyed 46 + * @return bool If true, beforeDestroyObject() 47 + * will be fired. 48 + */ 49 + public function canBeforeDestroyObject( 50 + PhabricatorDestructionEngine $destruction_engine, 51 + $object): bool { 52 + return true; 53 + } 54 + 55 + /** 56 + * Call your "Before Destruction" hook on the specified object. 57 + * The object is guaranteed to have a PHID and still exist but 58 + * will be destroyed later. 59 + * This method is not called if canBeforeDestroyObject() returns false. 60 + * 61 + * @param PhabricatorDestructionEngine $destruction_engine 62 + * Available destruction engine 63 + * @param object $object 64 + * Object that will be destroyed 65 + */ 66 + abstract public function beforeDestroyObject( 67 + PhabricatorDestructionEngine $destruction_engine, 68 + $object): void; 69 + 70 + /** 71 + * Get all "Before Destruction Engine" extensions. 72 + * 73 + * @return list<PhabricatorDestructionEngineExtension> 74 + */ 75 + final public static function getAllExtensions(): array { 76 + $map = new PhutilClassMapQuery(); 77 + return $map 78 + ->setAncestorClass(__CLASS__) 79 + ->setUniqueMethod('getExtensionKey') 80 + ->execute(); 81 + } 82 + 83 + }
+11
src/applications/system/engine/PhabricatorDestructionEngine.php
··· 73 73 } 74 74 } 75 75 76 + if ($object_phid) { 77 + // Allow extension to do something before the destruction. 78 + $before_extensions = 79 + PhabricatorBeforeDestructionEngineExtension::getAllExtensions(); 80 + foreach ($before_extensions as $key => $before_extension) { 81 + if ($before_extension->canBeforeDestroyObject($this, $object)) { 82 + $before_extension->beforeDestroyObject($this, $object); 83 + } 84 + } 85 + } 86 + 76 87 $object->destroyObjectPermanently($this); 77 88 78 89 if ($object_phid) {