Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2980229
D25772.1739883786.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
7 KB
Referenced Files
None
Subscribers
None
D25772.1739883786.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,90 @@
Form customization also provides a powerful tool for making many policy
management tasks easier (see @{article:User Guide: Customizing Forms}).
+
+Archiving
+=========
+
+Like most things in real life, sometimes project tags or milestones
+stop being useful, perhaps because they reached their deadline,
+perhaps because their investor was a scam, perhaps because your
+boss created a nonsense project by mistake with a faulty mouse, etc.
+
+In general, we recommend archiving projects instead of destroying them.
+Firstly, Phorge discourages killing. Secondly, keeping track of which
+colleagues worked on legacy projects is generally useful. Thirdly,
+the alternative is destroying projects (from the command line), but
+destroying things is generally very scary, very unsafe, and not
+recommended. In the other hand, archiving is generally very stable,
+well-tested, safe, encouraged, reversible, and full of satisfaction.
+Some Phorge instances also start smelling of peach fragrances,
+after you archive your first project.
+
+People who can {nav icon=pencil,name=Edit} a project can also
+use the {nav icon=ban,name=Archive} action.
+
+Archived projects will generally avoid to distract you, but they will preserve
+their past glory. For example:
+
+- archived projects are unlisted from the active list at /project/query/active/
+- archived projects are de-prioritized from most search selections,
+ including the top search bar, including tag pickers, etc.
+- archived projects are kept where they were placed (e.g. kept in tasks),
+ but are generously de-colorized from their tag badges, or struck-through.
+- archived projects are muted, and do not cause "watch" notifications
+
+All these consequences are reversible. You can bring a project back
+to life anytime using the {nav icon=check,name=Activate project} action.
+
+If somebody ask you to delete a project and make it go away, you can still
+just archive the project, and also change its project visibility.
+Valid examples are "show only to me", or "show only to these coworkers",
+etc. This is also a safe and easily reversible operation.
+
+If at this point we still haven't convinced you to archive your projects,
+enjoy the next scary section.
+
+Permanently Destroying
+======================
+
+Phorge is designed as a safe collaborative platform that rarely
+requires permanently destroying things.
+
+There are still uncommon circumstances were you may want to afford
+all the risks in the wild and not recommended world of
+@{article:Permanently Destroying Data}.
+
+What happens when you permanently destroy a project (or a milestone)
+using the command line:
+
+- the project is destroyed permanently, forever (unless you have a good backup)
+- all objects (such as tasks, repositories, etc.) to which you set visibility
+ restrictions like "visible to: members of THAT TAG" will immediately become
+ completely invisible from the web interface and API results
+- tagged items are generally preserved, including tasks, commits,
+ wiki documents, 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 of the destroyed project are preserved but
+ they are unassigned from that project
+- watchers of the destroyed project are preserved but they may need to find
+ something else to look at
+- if the project has a workboard, that workboard is destroyed as well
+ (tasks in that workboard will be kept and will remain associated
+ with other workboards, of course)
+- 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 can be edited directly.
+- if the project has sub-projects, all sub-projects and all their descendant
+ sub-projects will climb the tree depth by one level, to still have sense
+ and remain preserved. 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 a rebel fleet
+ of Slugma Pokemons out of recursion control.
+
+So, please consider just simply archiving projects, instead of destroying them.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 18, 13:03 (3 d, 14 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1174874
Default Alt Text
D25772.1739883786.diff (7 KB)
Attached To
Mode
D25772: Projects: improve quality of destroy workflow
Attached
Detach File
Event Timeline
Log In to Comment