Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F3281943
D25772.1742698281.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
9 KB
Referenced Files
None
Subscribers
None
D25772.1742698281.diff
View Options
diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php
--- a/src/applications/project/storage/PhabricatorProject.php
+++ b/src/applications/project/storage/PhabricatorProject.php
@@ -748,9 +748,75 @@
$slug->delete();
}
+ // Destroy my milestones because they cannot live without me.
+ // Do not use PhabricatorProjectQuery to avoid a circular dependency,
+ // and, to do not have a load silent fail, since these milestones do not
+ // have their parent anymore.
+ $milestones = id(new self())
+ ->loadAllWhere('parentProjectPHID = %s AND milestoneNumber IS NOT NULL',
+ $this->getPHID());
+ foreach ($milestones as $milestone) {
+ $milestone->attachParentProject($this);
+ $engine->destroyObject($milestone);
+ }
+
+ // Update my children to eventually fix holes in the tree.
+ $this->onDestroyTouchChildren(true);
+
+ // After the tree is fixed, update my parent hasSubProjects field.
+ if ($this->getParentProject()) {
+ id(new PhabricatorProjectsMembershipIndexEngineExtension())
+ ->rematerialize($this->getParentProject());
+ }
+
$this->saveTransaction();
}
+ /**
+ * On destroy, eventually bubble up my direct children, to take my place.
+ * Refresh all remaining children, to consolidate depth, path key, etc.
+ */
+ private function onDestroyTouchChildren($close_my_hole) {
+ // Micro-optimization.
+ if (!$this->supportsSubprojects() && !$this->supportsMilestones()) {
+ return;
+ }
+
+ // Get direct sub-projects and milestones and their new desired parent.
+ // We must skip my direct milestones since they are under removal.
+ // Do not use PhabricatorProjectQuery to avoid a circular dependency.
+ $query_children = new self();
+ if ($close_my_hole) {
+ $desired_parent = $this->getParentProject();
+ $children = $query_children->loadAllWhere(
+ 'parentProjectPHID = %s AND milestoneNumber IS NULL',
+ $this->getPHID());
+ } else {
+ $desired_parent = $this;
+ $children = $query_children->loadAllWhere(
+ 'parentProjectPHID = %s',
+ $this->getPHID());
+ }
+
+ // The desired parent PHID for my children may become NULL,
+ // when we are closing my hole but my parent it's a root-project.
+ $desired_parent_phid = null;
+ if ($desired_parent) {
+ $desired_parent_phid = $desired_parent->getPHID();
+ }
+
+ // Eventually bubble up my direct children. Update the others.
+ foreach ($children as $child) {
+ $child->attachParentProject($desired_parent);
+ $child->setParentProjectPHID($desired_parent_phid);
+ $child->setProjectPathKey(null); // Force a new path key and depth.
+ $child->save();
+
+ // Descend the tree.
+ $child->onDestroyTouchChildren(false);
+ }
+ }
+
/* -( PhabricatorFulltextInterface )--------------------------------------- */
diff --git a/src/docs/user/userguide/projects.diviner b/src/docs/user/userguide/projects.diviner
--- a/src/docs/user/userguide/projects.diviner
+++ b/src/docs/user/userguide/projects.diviner
@@ -337,3 +337,126 @@
Form customization also provides a powerful tool for making many policy
management tasks easier (see @{article:User Guide: Customizing Forms}).
+
+Archiving
+=========
+
+Phorge supports the destroy (unsafe) and the archive (safe) of projects.
+
+Archiving a project (or archiving a milestone - since milestones are projects)
+is very recommended: you are encouraged in archiving a project when it stopped
+being useful, when the project reached its deadline, or when its investor was
+a scam. You might be surprised how useful it is to know which colleagues have
+worked on a certain very old archived project, which fortunately somebody
+decided to archive rather than violently destroy.
+Archiving still has sense when your boss created a nonsense project about
+how-to integrate Phorge with Doom, but now would like to hide all traces...
+still, please desist from looking for destruction, and evaluate archiving it,
+and not only for the glory of the internal documentation in your organization.
+
+The {nav icon=ban,name=Archive} action is visible to all people who
+can {nav icon=pencil,name=Edit} a project. As usual in Phorge,
+there is a confirmation dialog.
+
+After you confirm to archive a project, these things will happen:
+
+- in general, the archived project will avoid to distract people,
+ still preserving its past glory.
+- whatever mentions the tag or its hashtag, the related badge is generously
+ de-colorized or struck-through.
+- the archived project is unlisted from the active list at
+ [ /project/query/active/ ]( /project/query/active/ )
+- the archived project is de-prioritized from most search results and selectors,
+ including the top search bar, the tag pickers, etc.
+- the archived project is muted, and do not cause "watch" notifications.
+- who triggered this action is logged in the recent actions.
+
+All these consequences are reversible. You can bring a project back
+to life anytime using the {nav icon=check,name=Activate project} action.
+
+After archiving a project, all tagged objects, tagged tasks, etc. will be
+intentionally kept as-is. In particular, on tagged objects is not
+enforced any special read-only policy. This has sense if you have paid
+attention to "Policies In Depth". In short, an object can have so many tags,
+and if a specific team group closed its operations does not mean that others
+should stop working on all their tagged stuff, etc.
+
+After you presented "how amazing is Phorge about archiving projects" and
+after you distributed stickers about `#JustArchive` to all coworkers,
+it's a classic that somebody still want to "just remove the project" or
+"make it go away" or "run obliviate", etc.
+In these cases where "more censorship" is needed, you can evaluate an
+additional change in the visibility settings of that project. For example,
+the very limited visibility "show only to me" makes the project effectively
+invisible to others. Mastering the visibility policies helps a lot in making
+sure your cleanup requests are managed professionally and in a secure way,
+still allowing future auditing, when needed.
+
+At this point, if you still haven't convinced everyone to archive a specific
+project, explore the next scary and unsafe section about permanently destroying.
+
+Permanently Destroying
+======================
+
+Phorge is designed as a safe collaborative platform that rarely
+requires @{article:Permanently Destroying Data}.
+
+If you have read that article, and if you have done a backup, and if
+you have access the command line, and if you still want to permanently
+destroy a project (or a milestone), these will be the consequences:
+
+- the project is destroyed permanently from the database, forever
+ (unless you have a good backup and sufficient recover skills)
+- all objects, including tasks, repositories, wiki documents, calendars,
+ secrets, other projects, etc. to which you set visibility restrictions
+ involving that project (example: "visible to project members"),
+ these objects will be broken, and everyone will be locked out of them.
+ It means these objects will become completely invisible from the web
+ interface and API results.
+ You still have margin to recover from these particular policy problems,
+ reading the @{article:User Guide: Unlocking Objects}.
+- tagged items are generally preserved, including tasks, commits,
+ wiki documents, calendar events, repositories, etc. and these objects
+ will simply not be associated anymore with that project tag
+ (but will remain associated with other tags, of course).
+- users that are members or watchers of the destroyed project will be
+ kept in your Phorge but unassigned from that project.
+ Watchers might go crazy until they find something else to watch.
+- comments and texts wrote by users will be preserved even if they were
+ mentioning your `#project` but that hashtag will not render a link.
+ You will still be able to add that hashtag in another project,
+ to revive these links.
+- if the project has a workboard, that workboard is destroyed as well
+ (tasks in that workboard will always be kept and will remain associated
+ with other workboards, in case).
+- if the project has direct milestones, these milestones are destroyed as well
+ (note that milestones are technically projects, so, read this list
+ again aloud to understand what will happen to these milestones, and to items
+ associated to these milestones, etc.)
+- if the project has a parent project, and if that parent has no other child
+ projects anymore, that parent can be promoted to root-project again.
+ This means the members of the parent project will be editable again.
+- if the project has sub-projects, all sub-projects and all their descendant
+ sub-projects will climb the tree depth by one level, to fill the hole
+ you caused. Grandchildren become children, sons become parents,
+ etc. - a real mess for family photos.
+- you increase the risk of something completely unexpected happening,
+ such as the destruction of your entire datacenter by our
+ Slugma Pokemons out of recursion control.
+
+To permanently destroy a project, you will need to execute a command like this,
+from the root directory of the Phorge repository on your server:
+
+```
+./bin/remove destroy PHID-PROJ-abcdef123456
+```
+
+The command needs the "PHID" code of the project.
+Every project has a PHID and it can be easily retrieved in multiple ways,
+including the {nav icon=cog,name=Manage} menu of that project, hovering
+the cursor on the {nav icon=flag,name=Flag For Later} feature.
+
+This command requires a manual confirmation. Before proceeding,
+take the disclaimer seriously and read again the previous section about
+archiving projects (safe), instead of permanently destroying them (unsafe),
+to eventually change your mind.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 23, 02:51 (11 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1192616
Default Alt Text
D25772.1742698281.diff (9 KB)
Attached To
Mode
D25772: Projects: improve quality of destroy workflow
Attached
Detach File
Event Timeline
Log In to Comment