From 001f76cbaae77bd7a19b8fc610e6c4b84beaa7bf Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Wed, 17 Jul 2013 16:43:37 -0700 Subject: [PATCH] Projects - tighten up a few things Summary: Fixes T2675, T2676. - when the last person leaves a project it is archived. - a script to archive all memberless projects - better feed stories for the various policy edits you can do - phriction pages are also moved as you rename projects Test Plan: edited some projects and noted reasonable feed stories. ran script against test data and it worked! left a last man standing project and it archived. renamed a project to "a" then "b" then "a" (etc) and it worked including phrictiondocument moves Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T2676, T2675 Differential Revision: https://secure.phabricator.com/D6478 --- .../20130716.archivememberlessprojects.php | 39 +++++++++++++++ .../story/PhabricatorFeedStoryProject.php | 15 ++++++ .../editor/PhabricatorProjectEditor.php | 49 +++++++++++++++++-- .../project/storage/PhabricatorProject.php | 5 ++ .../patch/PhabricatorBuiltinPatchList.php | 4 ++ 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 resources/sql/patches/20130716.archivememberlessprojects.php diff --git a/resources/sql/patches/20130716.archivememberlessprojects.php b/resources/sql/patches/20130716.archivememberlessprojects.php new file mode 100644 index 0000000000..aca6f51db7 --- /dev/null +++ b/resources/sql/patches/20130716.archivememberlessprojects.php @@ -0,0 +1,39 @@ +openTransaction(); + +foreach (new LiskMigrationIterator($table) as $project) { + + $members = PhabricatorEdgeQuery::loadDestinationPHIDs( + $project->getPHID(), + PhabricatorEdgeConfig::TYPE_PROJ_MEMBER); + + if (count($members)) { + echo sprintf( + 'Project "%s" has %d members; skipping.', + $project->getName(), + count($members)), "\n"; + continue; + } + + if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ARCHIVED) { + echo sprintf( + 'Project "%s" already archived; skipping.', + $project->getName()), "\n"; + continue; + } + + echo sprintf('Archiving project "%s"...', $project->getName()), "\n"; + queryfx( + $table->establishConnection('w'), + 'UPDATE %T SET status = %s WHERE id = %d', + $table->getTableName(), + PhabricatorProjectStatus::STATUS_ARCHIVED, + $project->getID()); +} + +$table->saveTransaction(); +echo "\nDone.\n"; diff --git a/src/applications/feed/story/PhabricatorFeedStoryProject.php b/src/applications/feed/story/PhabricatorFeedStoryProject.php index fba28197a9..e18ad7bdd5 100644 --- a/src/applications/feed/story/PhabricatorFeedStoryProject.php +++ b/src/applications/feed/story/PhabricatorFeedStoryProject.php @@ -86,6 +86,21 @@ final class PhabricatorFeedStoryProject extends PhabricatorFeedStory { $this->renderHandleList($rem)); } break; + case PhabricatorProjectTransactionType::TYPE_CAN_VIEW: + $action = hsprintf( + 'changed the visibility for %s.', + $this->linkTo($proj_phid)); + break; + case PhabricatorProjectTransactionType::TYPE_CAN_EDIT: + $action = hsprintf( + 'changed the edit policy for %s.', + $this->linkTo($proj_phid)); + break; + case PhabricatorProjectTransactionType::TYPE_CAN_JOIN: + $action = hsprintf( + 'changed the join policy for %s.', + $this->linkTo($proj_phid)); + break; default: $action = hsprintf('updated project %s.', $this->linkTo($proj_phid)); break; diff --git a/src/applications/project/editor/PhabricatorProjectEditor.php b/src/applications/project/editor/PhabricatorProjectEditor.php index 30817f9775..4a054364bc 100644 --- a/src/applications/project/editor/PhabricatorProjectEditor.php +++ b/src/applications/project/editor/PhabricatorProjectEditor.php @@ -8,6 +8,16 @@ final class PhabricatorProjectEditor extends PhabricatorEditor { private $addEdges = array(); private $remEdges = array(); + private $shouldArchive = false; + + private function setShouldArchive($should_archive) { + $this->shouldArchive = $should_archive; + return $this; + } + private function shouldArchive() { + return $this->shouldArchive; + } + public static function applyJoinProject( PhabricatorProject $project, PhabricatorUser $user) { @@ -120,6 +130,10 @@ final class PhabricatorProjectEditor extends PhabricatorEditor { try { $project->openTransaction(); + + if ($this->shouldArchive()) { + $project->setStatus(PhabricatorProjectStatus::STATUS_ARCHIVED); + } $project->save(); $edge_type = PhabricatorEdgeConfig::TYPE_PROJ_MEMBER; @@ -152,9 +166,6 @@ final class PhabricatorProjectEditor extends PhabricatorEditor { throw $ex; } - // TODO: If we rename a project, we should move its Phriction page. Do - // that once Phriction supports document moves. - return $this; } @@ -233,8 +244,37 @@ final class PhabricatorProjectEditor extends PhabricatorEditor { $type = $xaction->getTransactionType(); switch ($type) { case PhabricatorProjectTransactionType::TYPE_NAME: + $old_slug = $project->getFullPhrictionSlug(); $project->setName($xaction->getNewValue()); $project->setPhrictionSlug($xaction->getNewValue()); + + if ($xaction->getOldValue()) { + $old_document = id(new PhrictionDocument()) + ->loadOneWhere( + 'slug = %s', + $old_slug); + if ($old_document && $old_document->getStatus() == + PhrictionDocumentStatus::STATUS_EXISTS) { + $content = id(new PhrictionContent()) + ->load($old_document->getContentID()); + $from_editor = id(PhrictionDocumentEditor::newForSlug($old_slug)) + ->setActor($this->getActor()) + ->setTitle($content->getTitle()) + ->setContent($content->getContent()) + ->setDescription($content->getDescription()); + + $target_editor = id(PhrictionDocumentEditor::newForSlug( + $project->getFullPhrictionSlug())) + ->setActor($this->getActor()) + ->setTitle($content->getTitle()) + ->setContent($content->getContent()) + ->setDescription($content->getDescription()) + ->moveHere($old_document->getID(), $old_document->getPHID()); + + $target_document = $target_editor->getDocument(); + $from_editor->moveAway($target_document->getID()); + } + } $this->validateName($project); break; case PhabricatorProjectTransactionType::TYPE_STATUS: @@ -245,6 +285,9 @@ final class PhabricatorProjectEditor extends PhabricatorEditor { $new = array_fill_keys($xaction->getNewValue(), true); $this->addEdges = array_keys(array_diff_key($new, $old)); $this->remEdges = array_keys(array_diff_key($old, $new)); + if ($new === array()) { + $this->setShouldArchive(true); + } break; case PhabricatorProjectTransactionType::TYPE_CAN_VIEW: $project->setViewPolicy($xaction->getNewValue()); diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 3544cafa1a..78992f944b 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -128,4 +128,9 @@ final class PhabricatorProject extends PhabricatorProjectDAO return $this; } + public function getFullPhrictionSlug() { + $slug = $this->getPhrictionSlug(); + return 'projects/'.$slug; + } + } diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php index 3279846620..060c8657e9 100644 --- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php +++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php @@ -1466,6 +1466,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList { 'type' => 'sql', 'name' => $this->getPatchPath('20130711.pholioimageobsolete2.sql'), ), + '20130716.archivememberlessprojects.php' => array( + 'type' => 'php', + 'name' => $this->getPatchPath('20130716.archivememberlessprojects.php'), + ), ); } }