<?php
namespace Tlf\User;
trait Activations {
/**
* Check that an activation code is valid. If a code has more than 1 entry in the DB, all entries using that code are deleted. If a code has no valid user attached to it, it will be deleted.
*
*
* @param string $code an activation code generated by sentinel
* @return bool true if activation code is valid. False otherwise
*/
public function checkActivationCode($code){
//@TODO Guarantee uniqueness of activation codes. Sentinel does NOT do this, but I do check for duplication in this script. There's issues with my current approach, as it could potentially delete somebody else's activation code, thus requiring them to reset their password
$core = $this;
$pdo = $core->getPdo();
$stmt = $pdo->prepare("SELECT user_id, completed, UNIX_TIMESTAMP(created_at) AS created_at, UNIX_TIMESTAMP(CURRENT_TIMESTAMP()) AS now FROM activations WHERE `code` LIKE :code");
$stmt->execute([':code'=>$code]);
$rows = $stmt->fetchAll();
$numRows = count($rows);
$deleteActivation = function() use ($code, $pdo){
$del = $pdo->prepare("DELETE FROM activations WHERE `code` LIKE :code");
$del->execute([':code'=>$code]);
};
// I might combine >1 & ==0 into a single message that says "There was a problem with your activation code. Reset password"
if ($numRows>=2||$numRows==0){
if ($numRows>=2)$deleteActivation();
return false;
}
$row = $rows[0];
$userId = $row['user_id'];
$didComplete = (bool)$row['completed'];
$createdAt = (int)$row['created_at'];
// $expiration = $createdAt + 60*60*1; //60 secs * 60 mins * 1 hour = 1 hour
// $expiration = $createdAt + 15;
$now = (int)$row['now'];
//@TODO Implement proper expiration checking. Sentinel seems to be creating activation codes in the future, so expiration checks cannot be counted on at this time.
$expiration = $now + 100;
if ($didComplete||$now>$expiration){
return false;
}
$user = $this->backend->userById($userId);
if ($user==null){
$deleteActivation();
return false;
}
return true;
}
public function newActivationCode($user){
$model = $user->model();
if ($model==null)return null;//@TODO should I throw an exception here?
$code = $this->backend->newActivationCode($model);
return $code;
}
public function completeActivation($user, $code){
return $this->backend->completeActivation($user->model(), $code);
}
/**
*
* @param unknown $code
* @return boolean|NULL|array `false` if there are multiple entries for the activation code. `null` if no entries. an array of the row if found.
*/
public function activationDetails($code){
$pdo = $this->getPdo();
$stmt = $pdo->prepare("SELECT * FROM activations WHERE `code` LIKE :code");
$stmt->execute([':code'=>$code]);
$rows = $stmt->fetchAll();
if (count($rows)>1){
//@TODO log the error? Or maybe delete the duplicates? cause now we have an issue
return false;
// throw new \Exception("There are multiple entries for the same activation code.");
} else if (count($rows)==0){
return null;
}
return $rows[0];
}
}