validate(); Database::transaction(function() use ($token) { self::forgeId($token); $bindings = [ 'user_id' => $token->getUserId(), 'token' => $token->getText(), 'used' => $token->isUsed(), 'expires' => $token->getExpirationDate(), ]; $stmt = new Sql\UpdateStatement(); $stmt->setTable('user_token'); $stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($token->getId()))); foreach ($bindings as $key => $val) $stmt->setColumn($key, new Sql\Binding($val)); Database::exec($stmt); }); return $token; } public static function findByToken($key, $throw = true) { if (empty($key)) throw new SimpleNotFoundException('Invalid security token'); $stmt = new Sql\SelectStatement(); $stmt->setTable('user_token'); $stmt->setColumn('*'); $stmt->setCriterion(new Sql\EqualsFunctor('token', new Sql\Binding($key))); $row = Database::fetchOne($stmt); if ($row) return self::convertRow($row); if ($throw) throw new SimpleNotFoundException('No user with such security token'); return null; } public static function checkValidity($token) { if (empty($token)) throw new SimpleException('Invalid security token'); if ($token->isUsed()) throw new SimpleException('This token was already used'); if ($token->getExpirationDate() !== null and time() > $token->getExpirationDate()) throw new SimpleException('This token has expired'); } public static function forgeUnusedToken() { $tokenText = ''; while (true) { $tokenText = md5(mt_rand() . uniqid()); $token = self::findByToken($tokenText, false); if (!$token) return $tokenText; } } }