Example #1
0
 /**
  * Merge second user into first one and returns it
  * @param User $userByEmail user to be kept
  * @param User $userByIdentity user to be deleted
  * @param Identity $identity identity to be moved from the deleted user to kept user
  * @return User
  */
 private function mergeUser(User $userByEmail, User $userByIdentity, Identity $identity)
 {
     // Gather all references to the user that we are going to delete
     $rsm = new \Doctrine\ORM\Query\ResultSetMapping();
     $rsm->addScalarResult('TABLE_NAME', 'TABLE_NAME');
     $rsm->addScalarResult('COLUMN_NAME', 'COLUMN_NAME');
     $qb = $this->getEntityManager()->createNativeQuery("\n            SELECT TABLE_NAME, COLUMN_NAME\n            FROM `information_schema`.`KEY_COLUMN_USAGE`\n            WHERE\n            REFERENCED_TABLE_SCHEMA = :database\n            AND REFERENCED_TABLE_NAME = 'user'\n            AND REFERENCED_COLUMN_NAME = 'id'", $rsm);
     $database = $this->getEntityManager()->getConnection()->getDatabase();
     $qb->setParameters(['database' => $database]);
     $records = $qb->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
     // Update all references from the old user to the user we're going to keep
     foreach ($records as $r) {
         $table = $r['TABLE_NAME'];
         $field = $r['COLUMN_NAME'];
         $query = "UPDATE `{$table}` SET `{$field}` = :newUser WHERE `{$field}` = :oldUser";
         $this->getEntityManager()->getConnection()->executeUpdate($query, ['newUser' => $userByEmail->getId(), 'oldUser' => $userByIdentity->getId()]);
     }
     // This is not strictly necessary since the DB just has been update a
     // few lines before, but just to keep the model in memory up to date we do it "again"
     $identity->setUser($userByEmail);
     // Delete the duplicated user
     $this->getEntityManager()->remove($userByIdentity);
     return $userByEmail;
 }
Example #2
0
 /**
  * Create or update a user according to its social identity (coming from Facebook, Google, etc.)
  * @param string $provider
  * @param \Hybridauth\User\Profile $profile
  * @return User
  */
 public function createOrUpdate($provider, Profile $profile)
 {
     // First, look for pre-existing identity
     $identityRepository = $this->getEntityManager()->getRepository(\Application\Model\Identity::class);
     $identity = $identityRepository->findOneBy(['provider' => $provider, 'providerId' => $profile->identifier]);
     $userByIdentity = $identity ? $identity->getUser() : null;
     $userByEmail = $profile->email ? $this->findOneByEmail($profile->email) : null;
     if ($userByIdentity && $userByEmail && $userByEmail !== $userByIdentity) {
         $user = $this->mergeUser($userByEmail, $userByIdentity, $identity);
     } elseif ($userByIdentity) {
         $user = $userByIdentity;
     } else {
         $user = $userByEmail;
     }
     // If we still couldn't find a user yet, create a brand new one
     if (!$user) {
         $user = new User();
         $this->getEntityManager()->persist($user);
         $country = $this->getEntityManager()->getRepository(\Application\Model\Country::class)->findOneByCode($profile->country);
         $user->fromProfile($profile, $country);
     }
     // Also create an identity if we couldn't find one at the beginning
     if (!$identity) {
         $identity = new \Application\Model\Identity();
         $identity->setUser($user);
         $identity->setProvider($provider);
         $identity->setProviderId($profile->identifier);
         $this->getEntityManager()->persist($identity);
     }
     // Mark as logged in
     $user->setLastLogin(new \DateTimeImmutable());
     if (!$user->getFirstLogin()) {
         $user->setFirstLogin(new \DateTimeImmutable());
     }
     return $user;
 }