Unification of indents

This commit is contained in:
Mal 2020-08-23 12:37:39 +02:00
parent 37f220b561
commit 6b2abc1f89
31 changed files with 1171 additions and 1171 deletions

View File

@ -9,7 +9,7 @@ $session = new Session();
$router = new Router($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']); $router = new Router($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']);
if (isset($_SERVER['HTTP_CONTENT_TYPE'])) { if (isset($_SERVER['HTTP_CONTENT_TYPE'])) {
$router->setRequestBody($_SERVER['HTTP_CONTENT_TYPE'], file_get_contents('php://input')); $router->setRequestBody($_SERVER['HTTP_CONTENT_TYPE'], file_get_contents('php://input'));
} }
$router->route(); $router->route();

View File

@ -4,10 +4,10 @@ declare(strict_types=1);
class ApiBadRequestResponse extends ApiResponse class ApiBadRequestResponse extends ApiResponse
{ {
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->setParameter('success', false); $this->setParameter('success', false);
$this->setStatus(self::STATUS_BAD_REQUEST); $this->setStatus(self::STATUS_BAD_REQUEST);
} }
} }

View File

@ -4,24 +4,24 @@ declare(strict_types=1);
final class ApiJsonResponse extends ApiResponse final class ApiJsonResponse extends ApiResponse
{ {
protected string $mimeType = MimeType::JSON; protected string $mimeType = MimeType::JSON;
public function __construct(int $status = ServerStatus::OK) public function __construct(int $status = ServerStatus::OK)
{ {
parent::__construct($status); parent::__construct($status);
$this->setParameter('success', true); $this->setParameter('success', true);
} }
public function setResult(JsonSerializable $result): void public function setResult(JsonSerializable $result): void
{ {
$this->setParameter('result', $result->jsonSerialize()); $this->setParameter('result', $result->jsonSerialize());
} }
public function respond(): void public function respond(): void
{ {
parent::respond(); parent::respond();
echo json_encode($this->parameters); echo json_encode($this->parameters);
} }
} }

View File

@ -4,74 +4,74 @@ declare(strict_types=1);
class ApiResponse implements JsonSerializable class ApiResponse implements JsonSerializable
{ {
public const STATUS_OK = 200; public const STATUS_OK = 200;
public const STATUS_FORBIDDEN = 403; public const STATUS_FORBIDDEN = 403;
public const STATUS_UNAUTHORIZED = 401; public const STATUS_UNAUTHORIZED = 401;
public const STATUS_BAD_REQUEST = 400; public const STATUS_BAD_REQUEST = 400;
public const STATUS_NOT_FOUND = 404; public const STATUS_NOT_FOUND = 404;
public const STATUS_SERVER_ERROR = 500; public const STATUS_SERVER_ERROR = 500;
public const MIME_TYPE_PLAINTEXT = 'text/plain'; public const MIME_TYPE_PLAINTEXT = 'text/plain';
public const MIME_TYPE_JSON = 'application/json'; public const MIME_TYPE_JSON = 'application/json';
public const MIME_TYPE_SVG = 'image/svg+xml'; public const MIME_TYPE_SVG = 'image/svg+xml';
protected int $status = ServerStatus::OK; protected int $status = ServerStatus::OK;
protected string $mimeType = MimeType::PLAINTEXT; protected string $mimeType = MimeType::PLAINTEXT;
protected array $parameters = []; protected array $parameters = [];
public function __construct(int $status = ServerStatus::OK) public function __construct(int $status = ServerStatus::OK)
{ {
$this->setStatus($status); $this->setStatus($status);
} }
public function setParameter(string $key, $value): void public function setParameter(string $key, $value): void
{ {
$this->parameters[$key] = $value; $this->parameters[$key] = $value;
} }
public function setStatus(int $status): void public function setStatus(int $status): void
{ {
$this->status = $status; $this->status = $status;
} }
public function setMessage(string $message): void public function setMessage(string $message): void
{ {
$this->setParameter('message', $message); $this->setParameter('message', $message);
} }
public function setMimeType(string $mimeType): void public function setMimeType(string $mimeType): void
{ {
$this->mimeType = $mimeType; $this->mimeType = $mimeType;
} }
public function setBody(JsonSerializable $data): void public function setBody(JsonSerializable $data): void
{ {
$this->parameters = $data->jsonSerialize(); $this->parameters = $data->jsonSerialize();
} }
public function SetMessageIdNotFound(string $instanceName): void public function SetMessageIdNotFound(string $instanceName): void
{ {
$this->setMessage(sprintf('Die für %s angeforderte ID existiert nicht!', $instanceName)); $this->setMessage(sprintf('Die für %s angeforderte ID existiert nicht!', $instanceName));
} }
public function getStatus(): int public function getStatus(): int
{ {
return $this->status; return $this->status;
} }
public function getMimeType(): string public function getMimeType(): string
{ {
return $this->mimeType; return $this->mimeType;
} }
public function jsonSerialize() public function jsonSerialize()
{ {
return $this->parameters; return $this->parameters;
} }
public function respond(): void public function respond(): void
{ {
http_response_code($this->status); http_response_code($this->status);
header('Content-Type: ' . $this->mimeType); header('Content-Type: ' . $this->mimeType);
} }
} }

View File

@ -4,9 +4,9 @@ declare(strict_types=1);
class ApiSuccessResponse extends ApiResponse class ApiSuccessResponse extends ApiResponse
{ {
public function __construct(bool $success = true) public function __construct(bool $success = true)
{ {
parent::__construct(); parent::__construct();
$this->setParameter('success', $success); $this->setParameter('success', $success);
} }
} }

View File

@ -4,23 +4,23 @@ declare(strict_types=1);
final class ApiSvgResponse extends ApiResponse final class ApiSvgResponse extends ApiResponse
{ {
private string $content; private string $content;
protected string $mimeType = MimeType::SVG; protected string $mimeType = MimeType::SVG;
public function __construct(int $status = ServerStatus::OK) public function __construct(int $status = ServerStatus::OK)
{ {
parent::__construct($status); parent::__construct($status);
} }
public function setContent(string $content): void public function setContent(string $content): void
{ {
$this->content = $content; $this->content = $content;
} }
public function respond(): void public function respond(): void
{ {
parent::respond(); parent::respond();
header('Content-Length: ' . strlen($this->content)); header('Content-Length: ' . strlen($this->content));
echo $this->content; echo $this->content;
} }
} }

View File

@ -4,9 +4,9 @@ declare(strict_types=1);
class ApiUnauthorizedResponse extends ApiResponse class ApiUnauthorizedResponse extends ApiResponse
{ {
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->setStatus(self::STATUS_UNAUTHORIZED); $this->setStatus(self::STATUS_UNAUTHORIZED);
} }
} }

View File

@ -4,37 +4,37 @@ declare(strict_types=1);
final class FingerprintGetController extends AbstractController final class FingerprintGetController extends AbstractController
{ {
protected string $route = '/api/v1/fingerprint/{fingerprintId}'; protected string $route = '/api/v1/fingerprint/{fingerprintId}';
private int $fingerprintId; private int $fingerprintId;
public function __construct(string $url) public function __construct(string $url)
{ {
parent::__construct($url); parent::__construct($url);
$this->fingerprintId = (int)$this->getUrlParamInt('fingerprintId'); $this->fingerprintId = (int)$this->getUrlParamInt('fingerprintId');
} }
public function handle(): void public function handle(): void
{ {
try { try {
if (!$this->isUserLoggedIn()) { if (!$this->isUserLoggedIn()) {
return; return;
} }
$fingerprint = new Fingerprint($this->fingerprintId); $fingerprint = new Fingerprint($this->fingerprintId);
if (!$this->hasUserPermission($fingerprint->getUserId())) { if (!$this->hasUserPermission($fingerprint->getUserId())) {
return; return;
} }
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
$this->response->setResult($fingerprint); $this->response->setResult($fingerprint);
} catch (Throwable $e) { } catch (Throwable $e) {
$this->response = new ApiJsonResponse(ApiResponse::STATUS_NOT_FOUND); $this->response = new ApiJsonResponse(ApiResponse::STATUS_NOT_FOUND);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage(sprintf('No fingerprint with id %d found!', $this->fingerprintId)); $this->response->setMessage(sprintf('No fingerprint with id %d found!', $this->fingerprintId));
$this->response->setMimeType(ApiResponse::MIME_TYPE_JSON); $this->response->setMimeType(ApiResponse::MIME_TYPE_JSON);
} }
} }
} }

View File

@ -4,68 +4,68 @@ declare(strict_types=1);
final class FingerprintPostController extends AbstractController final class FingerprintPostController extends AbstractController
{ {
protected string $route = '/api/v1/fingerprint'; protected string $route = '/api/v1/fingerprint';
protected array $mandatoryAttributes = [ protected array $mandatoryAttributes = [
'fingerprint', 'fingerprint',
'userId', 'userId',
]; ];
public function handle(): void public function handle(): void
{ {
if (!$this->isUserLoggedIn()) { if (!$this->isUserLoggedIn()) {
return; return;
} }
parent::handle(); parent::handle();
$db = new MySqlDatabase(); $db = new MySqlDatabase();
$json = json_decode($this->requestBody); $json = json_decode($this->requestBody);
$fingerprint = new Fingerprint(null, $db); $fingerprint = new Fingerprint(null, $db);
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
try { try {
if (!$this->hasUserPermission((int)$json->userId)) { if (!$this->hasUserPermission((int)$json->userId)) {
return; return;
} }
$fingerprint->setFingerprint((string)$json->fingerprint); $fingerprint->setFingerprint((string)$json->fingerprint);
$fingerprint->setUserId((int)$json->userId); $fingerprint->setUserId((int)$json->userId);
if (!$db->hasTransaction()) { if (!$db->hasTransaction()) {
$db->startTransaction(); $db->startTransaction();
} }
$fingerprint->Save(); $fingerprint->Save();
$qrCode = new QrCode($fingerprint->getFingerprintId(), $fingerprint->getFingerprint()); $qrCode = new QrCode($fingerprint->getFingerprintId(), $fingerprint->getFingerprint());
$qrCode->generate(); $qrCode->generate();
$qrCode->save(); $qrCode->save();
$db->commit(); $db->commit();
$this->response->setParameter('fingerprintId', $fingerprint->getFingerprintId()); $this->response->setParameter('fingerprintId', $fingerprint->getFingerprintId());
} catch (QrCodeException $e) { } catch (QrCodeException $e) {
$this->response->setStatus(ServerStatus::INTERNAL_ERROR); $this->response->setStatus(ServerStatus::INTERNAL_ERROR);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage('An error occured during QR code creation!'); $this->response->setMessage('An error occured during QR code creation!');
} catch (Throwable $e) { } catch (Throwable $e) {
$this->catchDatabaseException($e->getMessage(), $json); $this->catchDatabaseException($e->getMessage(), $json);
} }
} }
private function catchDatabaseException(string $message, object $json): void private function catchDatabaseException(string $message, object $json): void
{ {
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
if (substr_count($message, 'foreign key constraint fails') > 0) { if (substr_count($message, 'foreign key constraint fails') > 0) {
$this->response->setMessage(sprintf('User with id %d doesn\'t exist!', $json->userId)); $this->response->setMessage(sprintf('User with id %d doesn\'t exist!', $json->userId));
$this->response->setStatus(ServerStatus::NOT_FOUND); $this->response->setStatus(ServerStatus::NOT_FOUND);
} elseif (substr_count($message, 'Duplicate entry') > 0) { } elseif (substr_count($message, 'Duplicate entry') > 0) {
$this->response->setMessage(sprintf('Fingerprint %s already exists!', $json->fingerprint)); $this->response->setMessage(sprintf('Fingerprint %s already exists!', $json->fingerprint));
$this->response->setStatus(ServerStatus::BAD_REQUEST); $this->response->setStatus(ServerStatus::BAD_REQUEST);
} else { } else {
$this->response->setMessage($message); $this->response->setMessage($message);
$this->response->setStatus(ServerStatus::INTERNAL_ERROR); $this->response->setStatus(ServerStatus::INTERNAL_ERROR);
} }
} }
} }

View File

@ -4,30 +4,30 @@ declare(strict_types=1);
final class QrCodeGetController extends AbstractController final class QrCodeGetController extends AbstractController
{ {
protected string $route = '/api/v1/fingerprint/{fingerprintId}/qr'; protected string $route = '/api/v1/fingerprint/{fingerprintId}/qr';
private int $fingerprintId; private int $fingerprintId;
public function __construct(string $url) public function __construct(string $url)
{ {
parent::__construct($url); parent::__construct($url);
$this->fingerprintId = (int)$this->getUrlParamInt('fingerprintId'); $this->fingerprintId = (int)$this->getUrlParamInt('fingerprintId');
} }
public function handle(): void public function handle(): void
{ {
$filename = Setting::PATH_QR_CODES . (string)$this->fingerprintId . '.svg'; $filename = Setting::PATH_QR_CODES . (string)$this->fingerprintId . '.svg';
if (!is_file($filename)) { if (!is_file($filename)) {
$this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage(sprintf('No QR code for fingerprint id %d found!', $this->fingerprintId)); $this->response->setMessage(sprintf('No QR code for fingerprint id %d found!', $this->fingerprintId));
return; return;
} }
try { try {
$this->response = new ApiSvgResponse(); $this->response = new ApiSvgResponse();
$file = @fopen($filename, 'r'); $file = @fopen($filename, 'r');
@ -38,5 +38,5 @@ final class QrCodeGetController extends AbstractController
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage($e->getMessage()); $this->response->setMessage($e->getMessage());
} }
} }
} }

View File

@ -4,19 +4,19 @@ declare(strict_types=1);
final class UserGetController extends AbstractController final class UserGetController extends AbstractController
{ {
protected string $route = '/api/v1/user/{userId}'; protected string $route = '/api/v1/user/{userId}';
private int $userId; private int $userId;
public function __construct(string $url) public function __construct(string $url)
{ {
parent::__construct($url); parent::__construct($url);
$this->userId = (int)$this->getUrlParamInt('userId'); $this->userId = (int)$this->getUrlParamInt('userId');
} }
public function handle(): void public function handle(): void
{ {
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
try { try {
@ -27,5 +27,5 @@ final class UserGetController extends AbstractController
$this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::INTERNAL_ERROR); $this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::INTERNAL_ERROR);
$this->response->setMessage($e->getMessage()); $this->response->setMessage($e->getMessage());
} }
} }
} }

View File

@ -4,51 +4,51 @@ declare(strict_types=1);
final class UserPostController extends AbstractController final class UserPostController extends AbstractController
{ {
protected string $route = '/api/v1/user'; protected string $route = '/api/v1/user';
protected array $mandatoryAttributes = [ protected array $mandatoryAttributes = [
'username', 'username',
'password', 'password',
'email', 'email',
'jabberAddress', 'jabberAddress',
]; ];
public function handle(): void public function handle(): void
{ {
parent::handle(); parent::handle();
if ($this->response->getStatus() !== ServerStatus::OK) { if ($this->response->getStatus() !== ServerStatus::OK) {
return; return;
} }
$json = json_decode($this->requestBody); $json = json_decode($this->requestBody);
try { try {
$user = new User(); $user = new User();
$user->setUsername($json->username); $user->setUsername($json->username);
$user->setPassword(Password::GetHash($json->password)); $user->setPassword(Password::GetHash($json->password));
$user->setEmail($json->email); $user->setEmail($json->email);
$user->setJabberAddress($json->jabberAddress); $user->setJabberAddress($json->jabberAddress);
$user->Save(); $user->Save();
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
$this->response->setParameter('userId', $user->getUserId()); $this->response->setParameter('userId', $user->getUserId());
} catch (DatabaseException $e) { } catch (DatabaseException $e) {
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage($e->getMessage()); $this->response->setMessage($e->getMessage());
switch ($e->getCode()) { switch ($e->getCode()) {
case DatabaseException::CONNECTION_FAILED: case DatabaseException::CONNECTION_FAILED:
$this->response->setStatus(ServerStatus::INTERNAL_ERROR); $this->response->setStatus(ServerStatus::INTERNAL_ERROR);
break; break;
default: default:
$this->response->setStatus(ServerStatus::INTERNAL_ERROR); $this->response->setStatus(ServerStatus::INTERNAL_ERROR);
} }
} catch (Throwable $e) { } catch (Throwable $e) {
$this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage($e->getMessage()); $this->response->setMessage($e->getMessage());
} }
} }
} }

View File

@ -4,25 +4,25 @@ declare(strict_types=1);
final class UserSessionDeleteController extends AbstractController final class UserSessionDeleteController extends AbstractController
{ {
protected string $route = '/api/v1/user/session'; protected string $route = '/api/v1/user/session';
public function handle(): void public function handle(): void
{ {
parent::handle(); parent::handle();
$session = new Session(); $session = new Session();
if (!$session->IsLoggedIn()) { if (!$session->IsLoggedIn()) {
$this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage('No session to delete!'); $this->response->setMessage('No session to delete!');
return; return;
} }
$session->Destroy(); $session->Destroy();
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
$this->response->setParameter('success', true); $this->response->setParameter('success', true);
} }
} }

View File

@ -4,41 +4,41 @@ declare(strict_types=1);
final class UserSessionPostController extends AbstractController final class UserSessionPostController extends AbstractController
{ {
protected string $route = '/api/v1/user/session'; protected string $route = '/api/v1/user/session';
protected array $mandatoryAttributes = [ protected array $mandatoryAttributes = [
'username', 'username',
'password', 'password',
]; ];
public function handle(): void public function handle(): void
{ {
parent::handle(); parent::handle();
if ($this->response->getStatus() !== ServerStatus::OK) { if ($this->response->getStatus() !== ServerStatus::OK) {
return; return;
} }
$json = json_decode($this->requestBody); $json = json_decode($this->requestBody);
$session = new Session(); $session = new Session();
if ($session->IsLoggedIn()) { if ($session->IsLoggedIn()) {
$this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage('You are already logged in!'); $this->response->setMessage('You are already logged in!');
return; return;
} }
if (!$session->Login($json->username, $json->password)) { if (!$session->Login($json->username, $json->password)) {
$this->response = new ApiJsonResponse(ServerStatus::UNAUTHORIZED); $this->response = new ApiJsonResponse(ServerStatus::UNAUTHORIZED);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage('Login failed!'); $this->response->setMessage('Login failed!');
return; return;
} }
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
$this->response->setParameter('userId', $session->getUserId()); $this->response->setParameter('userId', $session->getUserId());
} }
} }

View File

@ -4,61 +4,61 @@ declare(strict_types=1);
abstract class AbstractController abstract class AbstractController
{ {
protected string $route; protected string $route;
protected ApiResponse $response; protected ApiResponse $response;
protected Session $session; protected Session $session;
protected string $requestUrl; protected string $requestUrl;
protected ?string $requestBody = null; protected ?string $requestBody = null;
protected ?string $contentType = null; protected ?string $contentType = null;
protected array $mandatoryAttributes = []; protected array $mandatoryAttributes = [];
public function __construct(string $url) public function __construct(string $url)
{ {
$this->requestUrl = $url; $this->requestUrl = $url;
$this->response = new ApiResponse(); $this->response = new ApiResponse();
$this->session = new Session(); $this->session = new Session();
} }
public function setRequestBody(string $contentType, string $content): void public function setRequestBody(string $contentType, string $content): void
{ {
$this->requestBody = $content; $this->requestBody = $content;
$this->contentType = $contentType; $this->contentType = $contentType;
} }
public function getResponse(): ApiResponse public function getResponse(): ApiResponse
{ {
return $this->response; return $this->response;
} }
public function handle(): void public function handle(): void
{ {
if (!$this->validateJsonBody()) { if (!$this->validateJsonBody()) {
$this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST);
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setMessage('The request body has not the required json attributes!'); $this->response->setMessage('The request body has not the required json attributes!');
} }
} }
protected function getUrlParam(string $name): ?string protected function getUrlParam(string $name): ?string
{ {
foreach (explode('/', $this->route) as $index => $fragment) { foreach (explode('/', $this->route) as $index => $fragment) {
if ($fragment === '{' . $name . '}') { if ($fragment === '{' . $name . '}') {
return explode('/', $this->requestUrl)[$index]; return explode('/', $this->requestUrl)[$index];
} }
} }
return null; return null;
} }
protected function getUrlParamInt(string $name): ?int protected function getUrlParamInt(string $name): ?int
{ {
$param = $this->getUrlParam($name); $param = $this->getUrlParam($name);
return $param !== null ? (int)$param : null; return $param !== null ? (int)$param : null;
} }
public function isUserLoggedIn(): bool public function isUserLoggedIn(): bool
{ {
if (!$this->session->IsLoggedIn()) { if (!$this->session->IsLoggedIn()) {
$this->response = new ApiJsonResponse(ServerStatus::UNAUTHORIZED); $this->response = new ApiJsonResponse(ServerStatus::UNAUTHORIZED);
@ -72,7 +72,7 @@ abstract class AbstractController
return true; return true;
} }
public function hasUserPermission(int $userId): bool public function hasUserPermission(int $userId): bool
{ {
$this->response = new ApiJsonResponse(); $this->response = new ApiJsonResponse();
@ -87,28 +87,28 @@ abstract class AbstractController
return $hasPermission; return $hasPermission;
} }
protected function validateJsonBody(): bool protected function validateJsonBody(): bool
{ {
if (count($this->mandatoryAttributes) === 0) { if (count($this->mandatoryAttributes) === 0) {
return true; return true;
} }
if ($this->contentType === MimeType::JSON && $this->requestBody === null) { if ($this->contentType === MimeType::JSON && $this->requestBody === null) {
return false; return false;
} }
try { try {
$json = json_decode($this->requestBody); $json = json_decode($this->requestBody);
foreach ($this->mandatoryAttributes as $attribute) { foreach ($this->mandatoryAttributes as $attribute) {
if (!isset($json->{$attribute})) { if (!isset($json->{$attribute})) {
return false; return false;
} }
} }
return true; return true;
} catch (Throwable $e) { } catch (Throwable $e) {
return false; return false;
} }
} }
} }

View File

@ -4,243 +4,243 @@ declare(strict_types=1);
class Autoloader class Autoloader
{ {
private const PATH_CLASSES = 'backend/classes'; private const PATH_CLASSES = 'backend/classes';
private const PATH_CONTROLLERS = self::PATH_CLASSES . '/controller'; private const PATH_CONTROLLERS = self::PATH_CLASSES . '/controller';
private const PATH_CACHE = 'backend/cache/'; private const PATH_CACHE = 'backend/cache/';
public function __construct(string $cachePath = self::PATH_CACHE) public function __construct(string $cachePath = self::PATH_CACHE)
{ {
if ($cachePath !== self::PATH_CACHE) { if ($cachePath !== self::PATH_CACHE) {
$cachePath = substr($cachePath, -1) === '/' ? $cachePath : $cachePath . '/'; $cachePath = substr($cachePath, -1) === '/' ? $cachePath : $cachePath . '/';
} }
$routesFound = @include($cachePath . 'routes.php'); $routesFound = @include($cachePath . 'routes.php');
$classesFound = @include($cachePath . 'classes.php'); $classesFound = @include($cachePath . 'classes.php');
if (!$routesFound || !$classesFound) { if (!$routesFound || !$classesFound) {
throw new Exception( throw new Exception(
sprintf( sprintf(
'Autoloader cache not found! Please generate it with %s::BuildCache() at first!', 'Autoloader cache not found! Please generate it with %s::BuildCache() at first!',
self::class self::class
) )
); );
} }
spl_autoload_register( spl_autoload_register(
function (string $className) { function (string $className) {
if (!$this->loadClass($className)) { if (!$this->loadClass($className)) {
throw new Exception(sprintf('Class %s couldn\'t be loaded!', $className)); throw new Exception(sprintf('Class %s couldn\'t be loaded!', $className));
} }
} }
); );
} }
public static function BuildCache(): void public static function BuildCache(): void
{ {
self::BuildClassCache(); self::BuildClassCache();
self::BuildRouteCache(); self::BuildRouteCache();
} }
public static function BuildClassCache(): void public static function BuildClassCache(): void
{ {
$classesResult = self::scanForClasses(); $classesResult = self::scanForClasses();
$cacheContent = ''; $cacheContent = '';
foreach ($classesResult as $className => $path) { foreach ($classesResult as $className => $path) {
$cacheContent .= sprintf("\t\t'%s' => '%s',\n", $className, $path); $cacheContent .= sprintf("\t\t'%s' => '%s',\n", $className, $path);
} }
$cacheContent .= "\t]\n);"; $cacheContent .= "\t]\n);";
self::buildCacheFile($cacheContent, 'classes'); self::buildCacheFile($cacheContent, 'classes');
} }
private function loadClass(string $className): bool private function loadClass(string $className): bool
{ {
if (!isset(CLASSES[$className]) || !@include(CLASSES[$className])) { if (!isset(CLASSES[$className]) || !@include(CLASSES[$className])) {
return false; return false;
} }
return true; return true;
} }
public static function BuildRouteCache(): void public static function BuildRouteCache(): void
{ {
$controllersResult = self::scanForControllers(); $controllersResult = self::scanForControllers();
$controllerMethods = [ $controllerMethods = [
'GET' => [], 'GET' => [],
'POST' => [], 'POST' => [],
'PUT' => [], 'PUT' => [],
'DELETE' => [], 'DELETE' => [],
]; ];
foreach ($controllersResult as $className => $path) { foreach ($controllersResult as $className => $path) {
$file = fopen($path, 'r'); $file = fopen($path, 'r');
$content = fread($file, filesize($path)); $content = fread($file, filesize($path));
fclose($file); fclose($file);
preg_match_all('/(?<=private )\w+ \$\w+(?=;)/', $content, $matches); preg_match_all('/(?<=private )\w+ \$\w+(?=;)/', $content, $matches);
$params = []; $params = [];
foreach ($matches[0] as $match) { foreach ($matches[0] as $match) {
$parts = explode(' ', $match); $parts = explode(' ', $match);
$params[] = [ $params[] = [
'type' => $parts[0], 'type' => $parts[0],
'name' => $parts[1], 'name' => $parts[1],
]; ];
} }
preg_match('/(?<=protected string \$route = \').*(?=\';)/', $content, $matches); preg_match('/(?<=protected string \$route = \').*(?=\';)/', $content, $matches);
$route = $matches[0]; $route = $matches[0];
preg_match('/[A-Z][a-z]+(?=Controller)/', $className, $matches); preg_match('/[A-Z][a-z]+(?=Controller)/', $className, $matches);
$method = strtoupper($matches[0]); $method = strtoupper($matches[0]);
$controllerMethods[$method][$route] = [ $controllerMethods[$method][$route] = [
'name' => $className, 'name' => $className,
'params' => $params, 'params' => $params,
]; ];
} }
$cacheContent = ''; $cacheContent = '';
foreach ($controllerMethods as $method => $controllers) { foreach ($controllerMethods as $method => $controllers) {
$cacheContent .= self::createRoutesForMethod($method, $controllers); $cacheContent .= self::createRoutesForMethod($method, $controllers);
} }
$cacheContent .= "\t]\n);"; $cacheContent .= "\t]\n);";
self::buildCacheFile($cacheContent, 'routes'); self::buildCacheFile($cacheContent, 'routes');
} }
private static function createRoutesForMethod(string $method, array $routes): string private static function createRoutesForMethod(string $method, array $routes): string
{ {
krsort($routes); krsort($routes);
$stringRoutes = ''; $stringRoutes = '';
foreach ($routes as $route => $params) { foreach ($routes as $route => $params) {
$stringRoutes .= sprintf( $stringRoutes .= sprintf(
"'%s' => [ "'%s' => [
'controller' => %s::class, 'controller' => %s::class,
'params' => [ 'params' => [
%s %s
], ],
], ],
", ",
$route, $route,
$params['name'], $params['name'],
self::createRouteParams($params['params']) self::createRouteParams($params['params'])
); );
} }
return sprintf( return sprintf(
" "
'%s' => [ '%s' => [
%s %s
], ],
", ",
$method, $method,
$stringRoutes, $stringRoutes,
); );
} }
private static function createRouteParams(array $params): string private static function createRouteParams(array $params): string
{ {
$string = ''; $string = '';
foreach ($params as $param) { foreach ($params as $param) {
$string .= sprintf( $string .= sprintf(
" "
'%s' => [ '%s' => [
'type' => '%s', 'type' => '%s',
], ],
", ",
str_replace('$', '', $param['name']), str_replace('$', '', $param['name']),
$param['type'] $param['type']
); );
} }
return $string; return $string;
} }
private static function reformatCacheFileContent(string $content): string private static function reformatCacheFileContent(string $content): string
{ {
$depth = 0; $depth = 0;
$reformatted = ''; $reformatted = '';
$replace = ''; $replace = '';
// Removing indents // Removing indents
foreach (explode("\n", $content) as $line) { foreach (explode("\n", $content) as $line) {
$trim = trim($line); $trim = trim($line);
if ($trim !== '') { if ($trim !== '') {
$replace .= $trim . "\n"; $replace .= $trim . "\n";
} }
} }
for ($i = 0; $i < strlen($replace); $i++) { for ($i = 0; $i < strlen($replace); $i++) {
if (in_array($replace[$i], [')', ']'])) { if (in_array($replace[$i], [')', ']'])) {
$depth--; $depth--;
} }
if ($replace[$i - 1] === "\n") { if ($replace[$i - 1] === "\n") {
$reformatted .= str_repeat("\t", $depth); $reformatted .= str_repeat("\t", $depth);
} }
$reformatted .= $replace[$i]; $reformatted .= $replace[$i];
if (in_array($replace[$i], ['(', '['])) { if (in_array($replace[$i], ['(', '['])) {
$depth++; $depth++;
} }
} }
return $reformatted; return $reformatted;
} }
private static function buildCacheFile(string $content, string $cacheName): void private static function buildCacheFile(string $content, string $cacheName): void
{ {
$cacheContent = sprintf( $cacheContent = sprintf(
"<?php\n\n/*\n * This file was auto generated on %s\n */\n\ndefine(\n\t'%s',\n\t[\n", "<?php\n\n/*\n * This file was auto generated on %s\n */\n\ndefine(\n\t'%s',\n\t[\n",
(new DateTime())->format('Y-m-d H:i:s'), (new DateTime())->format('Y-m-d H:i:s'),
strtoupper($cacheName) strtoupper($cacheName)
); );
$cacheContent .= $content; $cacheContent .= $content;
$file = fopen(getcwd() . '/' . self::PATH_CACHE . $cacheName . '.php', 'w'); $file = fopen(getcwd() . '/' . self::PATH_CACHE . $cacheName . '.php', 'w');
fwrite($file, self::reformatCacheFileContent($cacheContent)); fwrite($file, self::reformatCacheFileContent($cacheContent));
fclose($file); fclose($file);
} }
private static function scanForFiles(string $folder): array private static function scanForFiles(string $folder): array
{ {
$folder = substr($folder, -1) === '/' ? substr($folder, 0, -1) : $folder; $folder = substr($folder, -1) === '/' ? substr($folder, 0, -1) : $folder;
$files = []; $files = [];
$handler = opendir($folder); $handler = opendir($folder);
while ($file = readdir($handler)) { while ($file = readdir($handler)) {
$path = $folder . '/' . $file; $path = $folder . '/' . $file;
if (is_dir($path) && $file !== '.' && $file !== '..') { if (is_dir($path) && $file !== '.' && $file !== '..') {
$files = array_merge($files, self::scanForFiles($path)); $files = array_merge($files, self::scanForFiles($path));
} elseif (is_file($path) && substr($path, -4) === '.php') { } elseif (is_file($path) && substr($path, -4) === '.php') {
$className = substr($file, 0, -4); $className = substr($file, 0, -4);
$files[$className] = $path; $files[$className] = $path;
} }
} }
return $files; return $files;
} }
private static function scanForClasses(): array private static function scanForClasses(): array
{ {
return self::scanForFiles(getcwd() . '/' . self::PATH_CLASSES); return self::scanForFiles(getcwd() . '/' . self::PATH_CLASSES);
} }
private static function scanForControllers(): array private static function scanForControllers(): array
{ {
return self::scanForFiles(getcwd() . '/' . self::PATH_CONTROLLERS); return self::scanForFiles(getcwd() . '/' . self::PATH_CONTROLLERS);
} }
} }

View File

@ -2,79 +2,79 @@
interface DatabaseInterface interface DatabaseInterface
{ {
public const ORDER_ASC = true; public const ORDER_ASC = true;
public const ORDER_DESC = false; public const ORDER_DESC = false;
/** /**
* Has to close the connection. * Has to close the connection.
*/ */
public function __destruct(); public function __destruct();
/** /**
* Sends an sql query to the database. * Sends an sql query to the database.
*/ */
public function Query(string $query, array $params = []): void; public function Query(string $query, array $params = []): void;
/** /**
* @return array * @return array
*/ */
public function getResult(): array; public function getResult(): array;
/** /**
* Selects backend from a table. * Selects backend from a table.
*/ */
public function Select( public function Select(
string $tableName, string $tableName,
array $fields = [], array $fields = [],
array $conditions = [], array $conditions = [],
int $limit = 0, int $limit = 0,
array $orderBy = [], array $orderBy = [],
bool $asc = true, bool $asc = true,
int $offset = 0 int $offset = 0
): array; ): array;
/** /**
* Deletes rows from a table. * Deletes rows from a table.
*/ */
public function Delete(string $table, array $conditions): void; public function Delete(string $table, array $conditions): void;
/** /**
* Inserts a new row into the table. * Inserts a new row into the table.
*/ */
public function Insert(string $table, array $fields): ?int; public function Insert(string $table, array $fields): ?int;
/** /**
* Edits backend inside a table. * Edits backend inside a table.
*/ */
public function Update(string $table, array $fields, array $conditions): void; public function Update(string $table, array $fields, array $conditions): void;
/** /**
* Returns the number of entries found. * Returns the number of entries found.
*/ */
public function Count(string $table, array $conditions = []): int; public function Count(string $table, array $conditions = []): int;
/* /*
* Returns if there's an open transaction. * Returns if there's an open transaction.
*/ */
public function hasTransaction(): bool; public function hasTransaction(): bool;
/* /*
* Starts a transaction that can later be committed or rolled back. * Starts a transaction that can later be committed or rolled back.
*/ */
public function startTransaction(): void; public function startTransaction(): void;
/* /*
* Quits a current transaction without saving. * Quits a current transaction without saving.
*/ */
public function rollback(): void; public function rollback(): void;
/* /*
* Saves and exits a current transaction. * Saves and exits a current transaction.
*/ */
public function commit(): void; public function commit(): void;
/** /**
* Returns the primary key from the last inserted row. * Returns the primary key from the last inserted row.
*/ */
public function GetLastInsertedId(): int; public function GetLastInsertedId(): int;
} }

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
final class MimeType final class MimeType
{ {
public const PLAINTEXT = 'text/plain'; public const PLAINTEXT = 'text/plain';
public const JSON = 'application/json'; public const JSON = 'application/json';
public const SVG = 'image/svg+xml'; public const SVG = 'image/svg+xml';
} }

View File

@ -8,22 +8,22 @@ final class MySqlDatabase implements DatabaseInterface
private ?PDO $connection; private ?PDO $connection;
private ?PDOStatement $cursor; private ?PDOStatement $cursor;
private bool $isTransactionOpen = false; private bool $isTransactionOpen = false;
public function __construct( public function __construct(
string $hostname = Setting::MYSQL_HOST, string $hostname = Setting::MYSQL_HOST,
string $user = Setting::MYSQL_USER, string $user = Setting::MYSQL_USER,
string $password = Setting::MYSQL_PASSWORD, string $password = Setting::MYSQL_PASSWORD,
string $database = Setting::MYSQL_DATABASE string $database = Setting::MYSQL_DATABASE
) { ) {
try { try {
$this->connection = new PDO("mysql:host=$hostname;dbname=$database", $user, $password); $this->connection = new PDO("mysql:host=$hostname;dbname=$database", $user, $password);
} catch (Throwable $e) { } catch (Throwable $e) {
throw new DatabaseException( throw new DatabaseException(
'Couldn\'t connect to the database!', 'Couldn\'t connect to the database!',
ServerStatus::INTERNAL_ERROR ServerStatus::INTERNAL_ERROR
); );
} }
} }
public function __destruct() public function __destruct()
@ -37,22 +37,22 @@ final class MySqlDatabase implements DatabaseInterface
if (!$this->cursor) { if (!$this->cursor) {
throw new DatabaseException( throw new DatabaseException(
'Initialization of database cursor failed', 'Initialization of database cursor failed',
DatabaseException::CONNECTION_FAILED DatabaseException::CONNECTION_FAILED
); );
} }
foreach ($params as $key => $param) { foreach ($params as $key => $param) {
if (is_bool($param)) { if (is_bool($param)) {
$param = (int)$param; $param = (int)$param;
} }
$this->cursor->bindValue(':' . $key, $param); $this->cursor->bindValue(':' . $key, $param);
} }
if (!$this->cursor->execute()) { if (!$this->cursor->execute()) {
throw new DatabaseException($this->cursor->errorInfo()[2], $this->cursor->errorInfo()[1]); throw new DatabaseException($this->cursor->errorInfo()[2], $this->cursor->errorInfo()[1]);
} }
} }
public function getResult(): array public function getResult(): array
@ -72,17 +72,17 @@ final class MySqlDatabase implements DatabaseInterface
return $result; return $result;
} }
/** /**
* Selects backend from a table. * Selects backend from a table.
*/ */
public function Select( public function Select(
string $tableName, string $tableName,
array $fields = [], array $fields = [],
array $conditions = [], array $conditions = [],
int $limit = 0, int $limit = 0,
array $orderBy = [], array $orderBy = [],
bool $asc = true, bool $asc = true,
int $offset = 0 int $offset = 0
): array { ): array {
if (!self::isValidTableName($tableName)) { if (!self::isValidTableName($tableName)) {
[]; [];
@ -125,8 +125,8 @@ final class MySqlDatabase implements DatabaseInterface
$offsetStatement = ''; $offsetStatement = '';
if ($offset > 0) { if ($offset > 0) {
$offsetStatement = 'OFFSET ' . $offset; $offsetStatement = 'OFFSET ' . $offset;
} }
$query = sprintf( $query = sprintf(
'SELECT %s FROM %s %s %s %s %s', 'SELECT %s FROM %s %s %s %s %s',
@ -135,139 +135,139 @@ final class MySqlDatabase implements DatabaseInterface
$conditionsExpression, $conditionsExpression,
$orderStatement, $orderStatement,
$limitStatement, $limitStatement,
$offsetStatement $offsetStatement
); );
try { try {
$this->Query($query, $conditions); $this->Query($query, $conditions);
} catch (Throwable $e) { } catch (Throwable $e) {
throw new DatabaseException( throw new DatabaseException(
$e->getMessage(), $e->getMessage(),
ServerStatus::INTERNAL_ERROR ServerStatus::INTERNAL_ERROR
); );
} }
return $this->getResult(); return $this->getResult();
} }
/** /**
* Deletes rows from a table. * Deletes rows from a table.
*/ */
public function Delete(string $table, array $conditions): void public function Delete(string $table, array $conditions): void
{ {
if (count($conditions) === 0) { if (count($conditions) === 0) {
$conditionsStatement = '1'; $conditionsStatement = '1';
} else { } else {
$conditionPairs = []; $conditionPairs = [];
foreach ($conditions as $field => $value) { foreach ($conditions as $field => $value) {
$conditionPairs[] = sprintf('%s=:Condition%s', $field, $field); $conditionPairs[] = sprintf('%s=:Condition%s', $field, $field);
$conditions['Condition' . $field] = $value; $conditions['Condition' . $field] = $value;
unset($conditions[$field]); unset($conditions[$field]);
} }
$conditionsStatement = implode(' AND ', $conditionPairs); $conditionsStatement = implode(' AND ', $conditionPairs);
} }
$query = sprintf('DELETE FROM %s WHERE %s', $table, $conditionsStatement); $query = sprintf('DELETE FROM %s WHERE %s', $table, $conditionsStatement);
$this->Query($query, $conditions); $this->Query($query, $conditions);
} }
public function Insert(string $table, array $fields): ?int public function Insert(string $table, array $fields): ?int
{ {
if (count($fields) === 0) { if (count($fields) === 0) {
throw new DatabaseException('Row to insert is empty!'); throw new DatabaseException('Row to insert is empty!');
} }
$fieldNames = implode(',', array_keys($fields)); $fieldNames = implode(',', array_keys($fields));
$fieldPlaceholder = []; $fieldPlaceholder = [];
foreach ($fields as $name => $value) { foreach ($fields as $name => $value) {
$fieldPlaceholder[] = ':' . $name; $fieldPlaceholder[] = ':' . $name;
} }
$query = sprintf( $query = sprintf(
'INSERT INTO %s (%s) VALUES (%s)', $table, $fieldNames, implode(',', $fieldPlaceholder) 'INSERT INTO %s (%s) VALUES (%s)', $table, $fieldNames, implode(',', $fieldPlaceholder)
); );
$this->Query($query, $fields); $this->Query($query, $fields);
$lastInsertedId = $this->GetLastInsertedId(); $lastInsertedId = $this->GetLastInsertedId();
if ((int)$lastInsertedId === 0) { if ((int)$lastInsertedId === 0) {
return null; return null;
} }
return $lastInsertedId; return $lastInsertedId;
} }
public function Update(string $table, array $fields, array $conditions): void public function Update(string $table, array $fields, array $conditions): void
{ {
$conditionPairs = []; $conditionPairs = [];
foreach ($conditions as $field => $value) { foreach ($conditions as $field => $value) {
$conditionPairs[] = sprintf('%s=:Condition%s', $field, $field); $conditionPairs[] = sprintf('%s=:Condition%s', $field, $field);
$conditions['Condition' . $field] = $value; $conditions['Condition' . $field] = $value;
unset($conditions[$field]); unset($conditions[$field]);
} }
$conditionsStatement = implode(' AND ', $conditionPairs); $conditionsStatement = implode(' AND ', $conditionPairs);
$fieldPairs = []; $fieldPairs = [];
foreach ($fields as $field => $value) { foreach ($fields as $field => $value) {
$fieldPairs[] = sprintf('%s=:%s', $field, $field); $fieldPairs[] = sprintf('%s=:%s', $field, $field);
} }
$fieldsStatement = implode(',', $fieldPairs); $fieldsStatement = implode(',', $fieldPairs);
$query = sprintf('UPDATE %s SET %s WHERE %s', $table, $fieldsStatement, $conditionsStatement); $query = sprintf('UPDATE %s SET %s WHERE %s', $table, $fieldsStatement, $conditionsStatement);
$this->Query($query, array_merge($fields, $conditions)); $this->Query($query, array_merge($fields, $conditions));
} }
public function Count(string $table, array $conditions = []): int public function Count(string $table, array $conditions = []): int
{ {
$result = $this->Select($table, ['count(*)'], $conditions); $result = $this->Select($table, ['count(*)'], $conditions);
return (int)$result[0]['count(*)']; return (int)$result[0]['count(*)'];
} }
public function hasTransaction(): bool public function hasTransaction(): bool
{ {
return $this->isTransactionOpen; return $this->isTransactionOpen;
} }
public function startTransaction(): void public function startTransaction(): void
{ {
$this->connection->beginTransaction(); $this->connection->beginTransaction();
$this->isTransactionOpen = true; $this->isTransactionOpen = true;
} }
public function rollback(): void public function rollback(): void
{ {
$this->connection->rollBack(); $this->connection->rollBack();
$this->isTransactionOpen = false; $this->isTransactionOpen = false;
} }
public function commit(): void public function commit(): void
{ {
$this->connection->commit(); $this->connection->commit();
$this->isTransactionOpen = false; $this->isTransactionOpen = false;
} }
public function GetLastInsertedId(): int public function GetLastInsertedId(): int
{ {
$this->Query('SELECT LAST_INSERT_ID() as ID'); $this->Query('SELECT LAST_INSERT_ID() as ID');
return (int)$this->getResult()[0]['ID']; return (int)$this->getResult()[0]['ID'];
} }
/** /**
* Does a check if the given table name contains forbidden chars. * Does a check if the given table name contains forbidden chars.
*/ */
private static function isValidTableName(string $tableName): bool private static function isValidTableName(string $tableName): bool
{ {
foreach (str_split($tableName) as $char) { foreach (str_split($tableName) as $char) {

View File

@ -2,17 +2,17 @@
class MySqlTable extends Table class MySqlTable extends Table
{ {
public function __construct(string $tableName, $id = null, DatabaseInterface &$database = null) public function __construct(string $tableName, $id = null, DatabaseInterface &$database = null)
{ {
self::EnsureConnection($database); self::EnsureConnection($database);
parent::__construct($tableName, $id, $database); parent::__construct($tableName, $id, $database);
} }
public static function EnsureConnection(?DatabaseInterface & $database): void public static function EnsureConnection(?DatabaseInterface & $database): void
{ {
if (!($database instanceof MySqlDatabase)) { if (!($database instanceof MySqlDatabase)) {
$database = new MySqlDatabase(); $database = new MySqlDatabase();
} }
} }
} }

View File

@ -4,12 +4,12 @@ declare(strict_types=1);
class Password class Password
{ {
public static function IsValid(string $password, string $hash): bool public static function IsValid(string $password, string $hash): bool
{ {
return password_verify($password, $hash); return password_verify($password, $hash);
} }
public static function GetHash(string $password): string public static function GetHash(string $password): string
{ {
return password_hash($password, PASSWORD_BCRYPT); return password_hash($password, PASSWORD_BCRYPT);
} }

View File

@ -4,41 +4,41 @@ declare(strict_types=1);
final class QrCode final class QrCode
{ {
private int $fingerprintId; private int $fingerprintId;
private string $fingerprint; private string $fingerprint;
private string $temporaryFilename; private string $temporaryFilename;
public function __construct(int $fingerprintId, string $fingerprint) public function __construct(int $fingerprintId, string $fingerprint)
{ {
$this->fingerprintId = $fingerprintId; $this->fingerprintId = $fingerprintId;
$this->fingerprint = $fingerprint; $this->fingerprint = $fingerprint;
} }
public function save(): void public function save(): void
{ {
if (!is_file($this->temporaryFilename)) { if (!is_file($this->temporaryFilename)) {
throw new QrCodeException( throw new QrCodeException(
sprintf('Temporary QR file %s couldn\'t be found!', $this->temporaryFilename) sprintf('Temporary QR file %s couldn\'t be found!', $this->temporaryFilename)
); );
} }
$returnCode = 0; $returnCode = 0;
$filename = $this->getFilePath(); $filename = $this->getFilePath();
passthru( passthru(
sprintf('mv %s %s', $this->temporaryFilename, $filename), sprintf('mv %s %s', $this->temporaryFilename, $filename),
$returnCode $returnCode
); );
if ($returnCode !== 0 || !is_file($filename)) { if ($returnCode !== 0 || !is_file($filename)) {
throw new QrCodeException( throw new QrCodeException(
sprintf('QR code for fingerprint %d couldn\'t be created!', $this->fingerprintId) sprintf('QR code for fingerprint %d couldn\'t be created!', $this->fingerprintId)
); );
} }
} }
public function delete(): void public function delete(): void
{ {
$filepath = $this->getFilePath(); $filepath = $this->getFilePath();
@ -51,35 +51,35 @@ final class QrCode
} }
} }
public function generate(): bool public function generate(): bool
{ {
$returnCode = 0; $returnCode = 0;
$path = substr(Setting::PATH_TMP, -1) === '/' ? Setting::PATH_TMP : Setting::PATH_TMP . '/'; $path = substr(Setting::PATH_TMP, -1) === '/' ? Setting::PATH_TMP : Setting::PATH_TMP . '/';
$this->temporaryFilename = $path . $this->generateTemporaryFilename() . '.svg'; $this->temporaryFilename = $path . $this->generateTemporaryFilename() . '.svg';
passthru( passthru(
sprintf('qrencode -o %s -t SVG "%s"', $this->temporaryFilename, $this->fingerprint), sprintf('qrencode -o %s -t SVG "%s"', $this->temporaryFilename, $this->fingerprint),
$returnCode $returnCode
); );
return !(bool)$returnCode; return !(bool)$returnCode;
} }
public function hasFile(): bool public function hasFile(): bool
{ {
return is_file($this->getFilePath()); return is_file($this->getFilePath());
} }
private function generateTemporaryFilename(): string private function generateTemporaryFilename(): string
{ {
$hash = hash('md5', (new DateTime())->format('U') . $this->fingerprint); $hash = hash('md5', (new DateTime())->format('U') . $this->fingerprint);
return sprintf('%s.svg', $hash); return sprintf('%s.svg', $hash);
} }
private function getFilePath(): string private function getFilePath(): string
{ {
$path = substr(Setting::PATH_QR_CODES, -1) === '/' $path = substr(Setting::PATH_QR_CODES, -1) === '/'
? Setting::PATH_QR_CODES ? Setting::PATH_QR_CODES

View File

@ -4,55 +4,55 @@ declare(strict_types=1);
final class Router final class Router
{ {
private string $route; private string $route;
private string $method; private string $method;
private ?string $requestBody = null; private ?string $requestBody = null;
private ?string $contentType = null; private ?string $contentType = null;
public function __construct(string $route, string $method) public function __construct(string $route, string $method)
{ {
$this->route = $route; $this->route = $route;
$this->method = $method; $this->method = $method;
} }
public function setRequestBody(string $contentType, string $content): void public function setRequestBody(string $contentType, string $content): void
{ {
$this->contentType = $contentType; $this->contentType = $contentType;
$this->requestBody = $content; $this->requestBody = $content;
} }
public function route(): void public function route(): void
{ {
foreach (ROUTES[$this->method] as $route => $params) { foreach (ROUTES[$this->method] as $route => $params) {
preg_match_all($this->createRegex($route, $params['params']), $this->route, $matches); preg_match_all($this->createRegex($route, $params['params']), $this->route, $matches);
if (count($matches[0]) > 0) { if (count($matches[0]) > 0) {
$class = new ReflectionClass($params['controller']); $class = new ReflectionClass($params['controller']);
/** @var AbstractController $controller */ /** @var AbstractController $controller */
$controller = $class->newInstance($matches[0][0]); $controller = $class->newInstance($matches[0][0]);
if ($this->requestBody !== null && $this->contentType !== null) { if ($this->requestBody !== null && $this->contentType !== null) {
$controller->setRequestBody($this->contentType, $this->requestBody); $controller->setRequestBody($this->contentType, $this->requestBody);
} }
$controller->handle(); $controller->handle();
$controller->getResponse()->respond(); $controller->getResponse()->respond();
return; return;
} }
} }
} }
private function createRegex(string $route, array $params): string private function createRegex(string $route, array $params): string
{ {
foreach ($params as $param => $values) { foreach ($params as $param => $values) {
switch ($values['type']) { switch ($values['type']) {
case 'int': case 'int':
$route = str_replace('{' . $param . '}', '[0-9]+', $route); $route = str_replace('{' . $param . '}', '[0-9]+', $route);
} }
} }
return '/' . str_replace('/', '\\/', $route) . '/'; return '/' . str_replace('/', '\\/', $route) . '/';
} }
} }

View File

@ -4,10 +4,10 @@ declare(strict_types=1);
class ServerStatus class ServerStatus
{ {
public const OK = 200; public const OK = 200;
public const FORBIDDEN = 403; public const FORBIDDEN = 403;
public const UNAUTHORIZED = 401; public const UNAUTHORIZED = 401;
public const BAD_REQUEST = 400; public const BAD_REQUEST = 400;
public const NOT_FOUND = 404; public const NOT_FOUND = 404;
public const INTERNAL_ERROR = 500; public const INTERNAL_ERROR = 500;
} }

View File

@ -4,92 +4,92 @@ declare(strict_types=1);
final class Session final class Session
{ {
public const TYPE_INT = 1; public const TYPE_INT = 1;
public const TYPE_STRING = 2; public const TYPE_STRING = 2;
public const TYPE_BOOL = 3; public const TYPE_BOOL = 3;
private const IS_LOGGED_IN = 'is_logged_in'; private const IS_LOGGED_IN = 'is_logged_in';
private const USER_ID = 'account_id'; private const USER_ID = 'account_id';
private const USERNAME = 'username'; private const USERNAME = 'username';
private const IS_ADMIN = 'admin'; private const IS_ADMIN = 'admin';
private const EMAIL = 'email'; private const EMAIL = 'email';
private const JABBER_ADDRESS = 'jabber'; private const JABBER_ADDRESS = 'jabber';
public function __construct() public function __construct()
{ {
@session_start(); @session_start();
if (!$this->HasValue(self::IS_LOGGED_IN)) { if (!$this->HasValue(self::IS_LOGGED_IN)) {
$this->SetBool(self::IS_LOGGED_IN, false); $this->SetBool(self::IS_LOGGED_IN, false);
} }
} }
public function Destroy(): bool public function Destroy(): bool
{ {
return session_unset() && session_destroy(); return session_unset() && session_destroy();
} }
public function Login(string $usernameOrEmail, string $password): bool public function Login(string $usernameOrEmail, string $password): bool
{ {
try { try {
$user = User::getFromUsername($usernameOrEmail); $user = User::getFromUsername($usernameOrEmail);
} catch (Throwable $e) { } catch (Throwable $e) {
$user = User::getFromEmail($usernameOrEmail); $user = User::getFromEmail($usernameOrEmail);
} }
if ($user === null || !Password::IsValid($password, $user->getPassword())) { if ($user === null || !Password::IsValid($password, $user->getPassword())) {
return false; return false;
} }
$this->SetBool(self::IS_LOGGED_IN, true); $this->SetBool(self::IS_LOGGED_IN, true);
$this->SetInt(self::USER_ID, $user->getUserId()); $this->SetInt(self::USER_ID, $user->getUserId());
$this->SetString(self::USERNAME, $user->getUsername()); $this->SetString(self::USERNAME, $user->getUsername());
$this->SetString(self::EMAIL, $user->getEmail()); $this->SetString(self::EMAIL, $user->getEmail());
$this->SetString(self::JABBER_ADDRESS, $user->getJabberAddress()); $this->SetString(self::JABBER_ADDRESS, $user->getJabberAddress());
$this->SetBool(self::IS_ADMIN, $user->isAdmin()); $this->SetBool(self::IS_ADMIN, $user->isAdmin());
return true; return true;
} }
public function HasValue(string $key): bool public function HasValue(string $key): bool
{ {
return self::HasSession() && isset($_SESSION[$key]); return self::HasSession() && isset($_SESSION[$key]);
} }
public function SetBool(string $key, bool $value): void public function SetBool(string $key, bool $value): void
{ {
$_SESSION[$key] = $value; $_SESSION[$key] = $value;
} }
public function SetString(string $key, string $value): void public function SetString(string $key, string $value): void
{ {
$_SESSION[$key] = $value; $_SESSION[$key] = $value;
} }
public function SetInt(string $key, int $value): void public function SetInt(string $key, int $value): void
{ {
$_SESSION[$key] = $value; $_SESSION[$key] = $value;
} }
public function IsLoggedIn(): bool public function IsLoggedIn(): bool
{ {
return self::HasSession() && $this->GetBool(self::IS_LOGGED_IN); return self::HasSession() && $this->GetBool(self::IS_LOGGED_IN);
} }
public function GetInt(string $key): ?int public function GetInt(string $key): ?int
{ {
return $this->HasValue($key) ? (int)$_SESSION[$key] : null; return $this->HasValue($key) ? (int)$_SESSION[$key] : null;
} }
public function GetString(string $key): ?string public function GetString(string $key): ?string
{ {
return $this->HasValue($key) ? (string)$_SESSION[$key] : null; return $this->HasValue($key) ? (string)$_SESSION[$key] : null;
} }
public function GetBool(string $key): ?bool public function GetBool(string $key): ?bool
{ {
return $this->HasValue($key) ? (bool)$_SESSION[$key] : null; return $this->HasValue($key) ? (bool)$_SESSION[$key] : null;
} }
public function getUserId(): ?int public function getUserId(): ?int
{ {
@ -101,8 +101,8 @@ final class Session
return $this->GetBool(self::IS_ADMIN); return $this->GetBool(self::IS_ADMIN);
} }
public static function HasSession(): bool public static function HasSession(): bool
{ {
return isset($_SESSION); return isset($_SESSION);
} }
} }

View File

@ -18,25 +18,25 @@ abstract class Table
protected string $tableName; protected string $tableName;
protected array $fields; protected array $fields;
protected string $primaryKey; protected string $primaryKey;
protected bool $isPrimKeyManual = false; protected bool $isPrimKeyManual = false;
public function __construct(string $tableName, $id, ?DatabaseInterface & $database) public function __construct(string $tableName, $id, ?DatabaseInterface & $database)
{ {
$this->tableName = $tableName; $this->tableName = $tableName;
$this->fields = []; $this->fields = [];
$this->database = $database; $this->database = $database;
$this->database->Query(sprintf('DESCRIBE %s', $tableName)); $this->database->Query(sprintf('DESCRIBE %s', $tableName));
$result = $this->database->getResult(); $result = $this->database->getResult();
foreach ($result as $field) { foreach ($result as $field) {
$sqlType = substr_count( $sqlType = substr_count(
$field['Type'], '(') === 0 ? $field['Type'] : strstr($field['Type'], $field['Type'], '(') === 0 ? $field['Type'] : strstr($field['Type'],
'(', '(',
true true
); );
switch ($sqlType) { switch ($sqlType) {
case 'varchar': case 'varchar':
@ -60,12 +60,12 @@ abstract class Table
$type = self::TYPE_FLOAT; $type = self::TYPE_FLOAT;
break; break;
case 'datetime': case 'datetime':
case 'date': case 'date':
$type = self::TYPE_DATETIME; $type = self::TYPE_DATETIME;
break; break;
case 'tinyint': case 'tinyint':
$type = self::TYPE_BOOL; $type = self::TYPE_BOOL;
break; break;
default: default:
throw new DatabaseException( throw new DatabaseException(
sprintf('Type %s of field %s couldn\'t be handled', $sqlType, $field['Field']), sprintf('Type %s of field %s couldn\'t be handled', $sqlType, $field['Field']),
@ -73,40 +73,40 @@ abstract class Table
); );
} }
$this->addField($field['Field'], $type); $this->addField($field['Field'], $type);
if ($field['Key'] === 'PRI') { if ($field['Key'] === 'PRI') {
$this->primaryKey = $field['Field']; $this->primaryKey = $field['Field'];
} }
} }
if (!$this->isPrimKeyManual && $id !== null) { if (!$this->isPrimKeyManual && $id !== null) {
$this->loadById($id); $this->loadById($id);
} }
} }
public function getPrimaryKey() public function getPrimaryKey()
{ {
if ($this->primaryKey === null) { if ($this->primaryKey === null) {
return null; return null;
} }
return $this->getField($this->primaryKey); return $this->getField($this->primaryKey);
} }
protected function addField(string $name, int $type): void protected function addField(string $name, int $type): void
{ {
if (!self::IsValidType($type)) { if (!self::IsValidType($type)) {
throw new DatabaseException( throw new DatabaseException(
sprintf('Field %s has invalid type of %s!', $name, $type), sprintf('Field %s has invalid type of %s!', $name, $type),
ServerStatus::INTERNAL_ERROR ServerStatus::INTERNAL_ERROR
); );
} }
$this->fields[$name] = [self::VALUE => null, self::TYPE => $type]; $this->fields[$name] = [self::VALUE => null, self::TYPE => $type];
} }
protected function loadById($id): void protected function loadById($id): void
{ {
$this->database->Query( $this->database->Query(
sprintf('SELECT * FROM %s WHERE %s = :id', $this->tableName, $this->primaryKey), sprintf('SELECT * FROM %s WHERE %s = :id', $this->tableName, $this->primaryKey),
@ -128,18 +128,18 @@ abstract class Table
} }
public function Flush(): void public function Flush(): void
{ {
$this->database->Delete($this->tableName, []); $this->database->Delete($this->tableName, []);
} }
public function Delete(): void public function Delete(): void
{ {
$this->database->Delete($this->tableName, [$this->primaryKey => $this->getPrimaryKey()]); $this->database->Delete($this->tableName, [$this->primaryKey => $this->getPrimaryKey()]);
foreach ($this->GetAllFieldNames() as $field) { foreach ($this->GetAllFieldNames() as $field) {
$this->fields[$field][self::VALUE] = null; $this->fields[$field][self::VALUE] = null;
} }
} }
protected function getField(string $name) protected function getField(string $name)
{ {
@ -150,9 +150,9 @@ abstract class Table
return $this->fields[$name][self::VALUE]; return $this->fields[$name][self::VALUE];
} }
/** /**
* Sets the value for the given field inside the database. * Sets the value for the given field inside the database.
*/ */
protected function setField(string $name, $value): void protected function setField(string $name, $value): void
{ {
if (!$this->HasField($name)) { if (!$this->HasField($name)) {
@ -179,51 +179,51 @@ abstract class Table
return; return;
case self::TYPE_DATETIME: case self::TYPE_DATETIME:
try { try {
$this->fields[$name][self::VALUE] = new DateTime((string)$value); $this->fields[$name][self::VALUE] = new DateTime((string)$value);
} catch (Throwable $e) { } catch (Throwable $e) {
throw new DatabaseException( throw new DatabaseException(
$e->getMessage(), $e->getMessage(),
ServerStatus::INTERNAL_ERROR ServerStatus::INTERNAL_ERROR
); );
} }
return; return;
case self::TYPE_BOOL: case self::TYPE_BOOL:
$this->fields[$name][self::VALUE] = (bool)$value; $this->fields[$name][self::VALUE] = (bool)$value;
} }
} }
/** /**
* Checks if the table has the given column. * Checks if the table has the given column.
*/ */
public function HasField(string $name): bool public function HasField(string $name): bool
{ {
return array_key_exists($name, $this->fields); return array_key_exists($name, $this->fields);
} }
/** /**
* Saves the whole object into the database. * Saves the whole object into the database.
*/ */
public function Save(): void public function Save(): void
{ {
$fields = []; $fields = [];
foreach ($this->GetAllFieldNames() as $fieldName) { foreach ($this->GetAllFieldNames() as $fieldName) {
$field = $this->getField($fieldName); $field = $this->getField($fieldName);
if ($field instanceof DateTime) { if ($field instanceof DateTime) {
$fields[$fieldName] = $field->format('Y-m-d H:i:s'); $fields[$fieldName] = $field->format('Y-m-d H:i:s');
} else if (is_bool($field)) { } else if (is_bool($field)) {
$fields[$fieldName] = (int)$field; $fields[$fieldName] = (int)$field;
} else { } else {
$fields[$fieldName] = $field; $fields[$fieldName] = $field;
} }
} }
if ($this->isPrimKeyManual) { if ($this->isPrimKeyManual) {
$this->saveWithManualId($fields); $this->saveWithManualId($fields);
} else { } else {
$this->saveWithPrimaryKey($fields); $this->saveWithPrimaryKey($fields);
} }
} }
/** /**
@ -240,9 +240,9 @@ abstract class Table
return $fieldNames; return $fieldNames;
} }
/** /**
* Checks if the index is a valid backend type. * Checks if the index is a valid backend type.
*/ */
public static function IsValidType(int $type): bool public static function IsValidType(int $type): bool
{ {
$validTypes = [ $validTypes = [
@ -250,43 +250,43 @@ abstract class Table
self::TYPE_INTEGER, self::TYPE_INTEGER,
self::TYPE_FLOAT, self::TYPE_FLOAT,
self::TYPE_DATETIME, self::TYPE_DATETIME,
self::TYPE_BOOL, self::TYPE_BOOL,
]; ];
return in_array($type, $validTypes); return in_array($type, $validTypes);
} }
protected function saveWithManualId(array $fields): void protected function saveWithManualId(array $fields): void
{ {
if ($this->getField($this->primaryKey) === null) { if ($this->getField($this->primaryKey) === null) {
throw new DatabaseException( throw new DatabaseException(
'Manual primary key must not be null!', 'Manual primary key must not be null!',
ServerStatus::INTERNAL_ERROR ServerStatus::INTERNAL_ERROR
); );
} }
$hasKey = (bool)$this->database->Count( $hasKey = (bool)$this->database->Count(
$this->tableName, $this->tableName,
[$this->primaryKey => $this->getField($this->primaryKey)] [$this->primaryKey => $this->getField($this->primaryKey)]
); );
if ($hasKey) { if ($hasKey) {
$this->database->Update( $this->database->Update(
$this->tableName, $fields, [$this->primaryKey => $this->getField($this->primaryKey)] $this->tableName, $fields, [$this->primaryKey => $this->getField($this->primaryKey)]
); );
} else { } else {
$this->database->Insert($this->tableName, $fields); $this->database->Insert($this->tableName, $fields);
} }
} }
protected function saveWithPrimaryKey(array $fields): void protected function saveWithPrimaryKey(array $fields): void
{ {
if ($this->getField($this->primaryKey) !== null) { if ($this->getField($this->primaryKey) !== null) {
$this->database->Update( $this->database->Update(
$this->tableName, $fields, [$this->primaryKey => $this->getField($this->primaryKey)] $this->tableName, $fields, [$this->primaryKey => $this->getField($this->primaryKey)]
); );
} else { } else {
$this->setField($this->primaryKey, $this->database->Insert($this->tableName, $fields)); $this->setField($this->primaryKey, $this->database->Insert($this->tableName, $fields));
} }
} }
} }

View File

@ -4,50 +4,50 @@ declare(strict_types=1);
final class Fingerprint extends MySqlTable implements JsonSerializable final class Fingerprint extends MySqlTable implements JsonSerializable
{ {
public const FIELD_ID = 'FingerprintId'; public const FIELD_ID = 'FingerprintId';
public const FIELD_FINGERPRINT = 'Fingerprint'; public const FIELD_FINGERPRINT = 'Fingerprint';
public const FIELD_USER = 'UserId'; public const FIELD_USER = 'UserId';
public function __construct($id = null, DatabaseInterface &$database = null) public function __construct($id = null, DatabaseInterface &$database = null)
{ {
parent::__construct(self::class, $id, $database); parent::__construct(self::class, $id, $database);
} }
public function getFingerprintId(): ?int public function getFingerprintId(): ?int
{ {
if ($this->getPrimaryKey() === null) { if ($this->getPrimaryKey() === null) {
return null; return null;
} }
return (int)$this->getPrimaryKey(); return (int)$this->getPrimaryKey();
} }
public function getFingerprint(): string public function getFingerprint(): string
{ {
return $this->getField(self::FIELD_FINGERPRINT); return $this->getField(self::FIELD_FINGERPRINT);
} }
public function getUserId(): int public function getUserId(): int
{ {
return $this->getField(self::FIELD_USER); return $this->getField(self::FIELD_USER);
} }
public function setFingerprint(string $fingerprint): void public function setFingerprint(string $fingerprint): void
{ {
$this->setField(self::FIELD_FINGERPRINT, $fingerprint); $this->setField(self::FIELD_FINGERPRINT, $fingerprint);
} }
public function setUserId(int $userId): void public function setUserId(int $userId): void
{ {
$this->setField(self::FIELD_USER, $userId); $this->setField(self::FIELD_USER, $userId);
} }
public function jsonSerialize(): array public function jsonSerialize(): array
{ {
return [ return [
'fingerprintId' => $this->getFingerprintId(), 'fingerprintId' => $this->getFingerprintId(),
'fingerprint' => $this->getFingerprint(), 'fingerprint' => $this->getFingerprint(),
'userId' => $this->getUserId() 'userId' => $this->getUserId()
]; ];
} }
} }

View File

@ -4,42 +4,42 @@ declare(strict_types=1);
final class Sharing extends MySqlTable implements JsonSerializable final class Sharing extends MySqlTable implements JsonSerializable
{ {
public const FIELD_USER = 'User'; public const FIELD_USER = 'User';
public const FIELD_USER_SHARED = 'UserShared'; public const FIELD_USER_SHARED = 'UserShared';
public function __construct($id = null, DatabaseInterface &$database = null) public function __construct($id = null, DatabaseInterface &$database = null)
{ {
parent::__construct(self::class, $id, $database); parent::__construct(self::class, $id, $database);
} }
public function getSharingId(): ?int public function getSharingId(): ?int
{ {
if ($this->getPrimaryKey() === null) { if ($this->getPrimaryKey() === null) {
return null; return null;
} }
return (int)$this->getPrimaryKey(); return (int)$this->getPrimaryKey();
} }
public function getUserId(): int public function getUserId(): int
{ {
return $this->getField(self::FIELD_USER); return $this->getField(self::FIELD_USER);
} }
public function getUserShared(): int public function getUserShared(): int
{ {
return $this->getField(self::FIELD_USER_SHARED); return $this->getField(self::FIELD_USER_SHARED);
} }
public function setUserId(int $userId): void public function setUserId(int $userId): void
{ {
$this->setField(self::FIELD_USER, $userId); $this->setField(self::FIELD_USER, $userId);
} }
public function setUserShared(int $userShared): void public function setUserShared(int $userShared): void
{ {
$this->setField(self::FIELD_USER_SHARED, $userShared); $this->setField(self::FIELD_USER_SHARED, $userShared);
} }
public function jsonSerialize() public function jsonSerialize()
{ {

View File

@ -4,141 +4,141 @@ declare(strict_types=1);
final class User extends MySqlTable implements JsonSerializable final class User extends MySqlTable implements JsonSerializable
{ {
public const FIELD_ID = 'UserId'; public const FIELD_ID = 'UserId';
public const FIELD_USERNAME = 'Username'; public const FIELD_USERNAME = 'Username';
public const FIELD_PASSWORD = 'Password'; public const FIELD_PASSWORD = 'Password';
public const FIELD_EMAIL = 'Email'; public const FIELD_EMAIL = 'Email';
public const FIELD_JABBER_ADDRESS = 'JabberAddress'; public const FIELD_JABBER_ADDRESS = 'JabberAddress';
public const FIELD_ADMIN = 'IsAdmin'; public const FIELD_ADMIN = 'IsAdmin';
public function __construct($id = null, DatabaseInterface &$database = null) public function __construct($id = null, DatabaseInterface &$database = null)
{ {
parent::__construct(self::class, $id, $database); parent::__construct(self::class, $id, $database);
} }
public function getUserId(): ?int public function getUserId(): ?int
{ {
if ($this->getPrimaryKey() === null) { if ($this->getPrimaryKey() === null) {
return null; return null;
} }
return (int)$this->getPrimaryKey(); return (int)$this->getPrimaryKey();
} }
public function getUsername(): string public function getUsername(): string
{ {
return $this->getField(self::FIELD_USERNAME); return $this->getField(self::FIELD_USERNAME);
} }
public function getPassword(): string public function getPassword(): string
{ {
return $this->getField(self::FIELD_PASSWORD); return $this->getField(self::FIELD_PASSWORD);
} }
public function getEmail(): string public function getEmail(): string
{ {
return $this->getField(self::FIELD_EMAIL); return $this->getField(self::FIELD_EMAIL);
} }
public function getJabberAddress(): string public function getJabberAddress(): string
{ {
return $this->getField(self::FIELD_JABBER_ADDRESS); return $this->getField(self::FIELD_JABBER_ADDRESS);
} }
public function isAdmin(): bool public function isAdmin(): bool
{ {
return $this->getField(self::FIELD_ADMIN); return $this->getField(self::FIELD_ADMIN);
} }
public function setUsername(string $username): void public function setUsername(string $username): void
{ {
$this->setField(self::FIELD_USERNAME, $username); $this->setField(self::FIELD_USERNAME, $username);
} }
public function setPassword(string $password): void public function setPassword(string $password): void
{ {
$this->setField(self::FIELD_PASSWORD, $password); $this->setField(self::FIELD_PASSWORD, $password);
} }
public function setEmail(string $email): void public function setEmail(string $email): void
{ {
$this->setField(self::FIELD_EMAIL, $email); $this->setField(self::FIELD_EMAIL, $email);
} }
public function setJabberAddress(string $jabberAddress): void public function setJabberAddress(string $jabberAddress): void
{ {
$this->setField(self::FIELD_JABBER_ADDRESS, $jabberAddress); $this->setField(self::FIELD_JABBER_ADDRESS, $jabberAddress);
} }
public function setAdmin(bool $isAdmin): void public function setAdmin(bool $isAdmin): void
{ {
$this->setField(self::FIELD_ADMIN, $isAdmin); $this->setField(self::FIELD_ADMIN, $isAdmin);
} }
public static function getFromUsername(string $username, DatabaseInterface &$database = null): self public static function getFromUsername(string $username, DatabaseInterface &$database = null): self
{ {
$databaseGiven = true; $databaseGiven = true;
if ($database === null) { if ($database === null) {
$database = new MySqlDatabase(); $database = new MySqlDatabase();
$databaseGiven = false; $databaseGiven = false;
} }
if ($database->Count(self::class, [self::FIELD_USERNAME => $username]) === 0) { if ($database->Count(self::class, [self::FIELD_USERNAME => $username]) === 0) {
throw new UserException(sprintf('No user with name %s found!', $username)); throw new UserException(sprintf('No user with name %s found!', $username));
} }
$id = $database->Select(self::class, [self::FIELD_ID], [self::FIELD_USERNAME => $username])[0][self::FIELD_ID]; $id = $database->Select(self::class, [self::FIELD_ID], [self::FIELD_USERNAME => $username])[0][self::FIELD_ID];
$user = $databaseGiven ? new User((int)$id, $database) : new User((int)$id); $user = $databaseGiven ? new User((int)$id, $database) : new User((int)$id);
return $user; return $user;
} }
public static function getFromEmail(string $email, DatabaseInterface &$database = null): self public static function getFromEmail(string $email, DatabaseInterface &$database = null): self
{ {
$databaseGiven = true; $databaseGiven = true;
if ($database === null) { if ($database === null) {
$database = new MySqlDatabase(); $database = new MySqlDatabase();
$databaseGiven = false; $databaseGiven = false;
} }
if ($database->Count(self::class) === 0) { if ($database->Count(self::class) === 0) {
throw new UserException(sprintf('No user with email %s found!', $email)); throw new UserException(sprintf('No user with email %s found!', $email));
} }
$id = $database->Select(self::class, [self::FIELD_ID], [self::FIELD_EMAIL => $email])[0][self::FIELD_ID]; $id = $database->Select(self::class, [self::FIELD_ID], [self::FIELD_EMAIL => $email])[0][self::FIELD_ID];
$user = $databaseGiven ? new User((int)$id, $database) : new User((int)$id); $user = $databaseGiven ? new User((int)$id, $database) : new User((int)$id);
return $user; return $user;
} }
public function getFingerprintIds(): array public function getFingerprintIds(): array
{ {
$result = $this->database->Select( $result = $this->database->Select(
Fingerprint::class, Fingerprint::class,
[Fingerprint::FIELD_ID], [Fingerprint::FIELD_ID],
[Fingerprint::FIELD_USER => $this->getUserId()] [Fingerprint::FIELD_USER => $this->getUserId()]
); );
$ids = []; $ids = [];
foreach ($result as $record) { foreach ($result as $record) {
$ids[] = (int)$record[Fingerprint::FIELD_ID]; $ids[] = (int)$record[Fingerprint::FIELD_ID];
} }
return $ids; return $ids;
} }
public function jsonSerialize() public function jsonSerialize()
{ {
return [ return [
'userId' => $this->getUserId(), 'userId' => $this->getUserId(),
'username' => $this->getUsername(), 'username' => $this->getUsername(),
'jabberAddress' => $this->getJabberAddress(), 'jabberAddress' => $this->getJabberAddress(),
'fingerprintIds' => $this->getFingerprintIds() 'fingerprintIds' => $this->getFingerprintIds()
]; ];
} }
} }

View File

@ -4,5 +4,5 @@ declare(strict_types=1);
final class DatabaseException extends Exception final class DatabaseException extends Exception
{ {
public const CONNECTION_FAILED = 1; public const CONNECTION_FAILED = 1;
} }

View File

@ -17,14 +17,14 @@ declare(strict_types=1);
final class Setting final class Setting
{ {
public const MYSQL_HOST = \':HOST\'; public const MYSQL_HOST = \':HOST\';
public const MYSQL_USER = \':USER\'; public const MYSQL_USER = \':USER\';
public const MYSQL_PASSWORD = \':PASSWORD\'; public const MYSQL_PASSWORD = \':PASSWORD\';
public const MYSQL_DATABASE = \':DATABASE\'; public const MYSQL_DATABASE = \':DATABASE\';
public const PATH_ROOT = \':ROOT_PATH/\'; public const PATH_ROOT = \':ROOT_PATH/\';
public const PATH_QR_CODES = self::PATH_ROOT . \'backend/qr/\'; public const PATH_QR_CODES = self::PATH_ROOT . \'backend/qr/\';
public const PATH_TMP = self::PATH_ROOT . \'backend/tmp/\'; public const PATH_TMP = self::PATH_ROOT . \'backend/tmp/\';
} }
'; ';