From 249ee9f1048ad78a295752be01dc3d14daebbd3a Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 2 Jun 2015 15:10:55 -0700 Subject: [PATCH] Migrate mailing lists to mailing list users Summary: Ref T8387. This migrates lists in the database to users, and replaces all subscriptions. This won't update Herald rules or saved search queries, but they're presumably rare and infeasibly complex to migrate. Test Plan: This migration is relatively re-runnable, so I ran it a bunch of times with different setups using `bin/storage adjust --apply`. It successfully migrated lists into users and replaced them in all the places they were subscribed. Reviewers: btrahan Reviewed By: btrahan Subscribers: eadler, epriestley Maniphest Tasks: T8387 Differential Revision: https://secure.phabricator.com/D13128 --- .../sql/autopatches/20150602.mlist.2.php | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 resources/sql/autopatches/20150602.mlist.2.php diff --git a/resources/sql/autopatches/20150602.mlist.2.php b/resources/sql/autopatches/20150602.mlist.2.php new file mode 100644 index 0000000000..a8f2a090ba --- /dev/null +++ b/resources/sql/autopatches/20150602.mlist.2.php @@ -0,0 +1,145 @@ +establishConnection('w'); +$lists = new LiskRawMigrationIterator($conn_w, 'metamta_mailinglist'); + +echo pht('Migrating mailing lists...')."\n"; + +foreach ($lists as $list) { + $name = $list['name']; + $email = $list['email']; + $uri = $list['uri']; + $old_phid = $list['phid']; + + $username = preg_replace('/[^a-zA-Z0-9_-]+/', '-', $name); + $username = preg_replace('/-{2,}/', '-', $username); + $username = trim($username, '-'); + if (!strlen($username)) { + $username = 'mailinglist'; + } + $username .= '-list'; + + $username_okay = false; + for ($suffix = 1; $suffix <= 9; $suffix++) { + if ($suffix == 1) { + $effective_username = $username; + } else { + $effective_username = $username.$suffix; + } + + $collision = id(new PhabricatorPeopleQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withUsernames(array($effective_username)) + ->executeOne(); + if (!$collision) { + $username_okay = true; + break; + } + } + + if (!$username_okay) { + echo pht( + 'Failed to migrate mailing list "%s": unable to generate a unique '. + 'username for it.')."\n"; + continue; + } + + $username = $effective_username; + if (!PhabricatorUser::validateUsername($username)) { + echo pht( + 'Failed to migrate mailing list "%s": unable to generate a valid '. + 'username for it.', + $name)."\n"; + continue; + } + + $address = id(new PhabricatorUserEmail())->loadOneWhere( + 'address = %s', + $email); + if ($address) { + echo pht( + 'Failed to migrate mailing list "%s": an existing user already '. + 'has the email address "%s".', + $name, + $email)."\n"; + continue; + } + + $user = id(new PhabricatorUser()) + ->setUsername($username) + ->setRealName(pht('Mailing List "%s"', $name)) + ->setIsApproved(1) + ->setIsMailingList(1); + + $email_object = id(new PhabricatorUserEmail()) + ->setAddress($email) + ->setIsVerified(1); + + try { + id(new PhabricatorUserEditor()) + ->setActor($user) + ->createNewUser($user, $email_object); + } catch (Exception $ex) { + echo pht( + 'Failed to migrate mailing list "%s": %s.', + $name, + $ex->getMessage())."\n"; + continue; + } + + $new_phid = $user->getPHID(); + + // NOTE: After the PHID type is removed we can't use any Edge code to + // modify edges. + + $edge_type = PhabricatorSubscribedToObjectEdgeType::EDGECONST; + $edge_inverse = PhabricatorObjectHasSubscriberEdgeType::EDGECONST; + + $map = PhabricatorPHIDType::getAllTypes(); + foreach ($map as $type => $spec) { + try { + $object = $spec->newObject(); + if (!$object) { + continue; + } + $object_conn_w = $object->establishConnection('w'); + queryfx( + $object_conn_w, + 'UPDATE %T SET dst = %s WHERE dst = %s AND type = %s', + PhabricatorEdgeConfig::TABLE_NAME_EDGE, + $new_phid, + $old_phid, + $edge_inverse); + } catch (Exception $ex) { + // Just ignore these; they're mostly tables not existing. + continue; + } + } + + try { + $dst_phids = queryfx_all( + $conn_w, + 'SELECT dst FROM %T WHERE src = %s AND type = %s', + PhabricatorEdgeConfig::TABLE_NAME_EDGE, + $old_phid, + $edge_type); + if ($dst_phids) { + $editor = new PhabricatorEdgeEditor(); + foreach ($dst_phids as $dst_phid) { + $editor->addEdge($new_phid, $edge_type, $dst_phid['dst']); + } + $editor->save(); + } + } catch (Exception $ex) { + echo pht( + 'Unable to migrate some inverse edges for mailing list "%s": %s.', + $name, + $ex->getMessage())."\n"; + continue; + } + + echo pht( + 'Migrated mailing list "%s" to mailing list user "%s".', + $name, + $user->getUsername())."\n"; +}