1
0
Fork 0
mirror of https://codeberg.org/demostf/api.git synced 2026-06-03 18:04:08 +02:00

Add php-cs-fixer

This commit is contained in:
Robin Appelman 2017-07-30 14:51:54 +02:00
commit 309ae17036
54 changed files with 4900 additions and 4106 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
.env .env
vendor vendor
node_modules node_modules
.php_cs.cache

13
.php_cs.dist Normal file
View file

@ -0,0 +1,13 @@
<?php
$finder = PhpCsFixer\Finder::create()
->exclude('vendor')
->in(__DIR__);
return PhpCsFixer\Config::create()
->setRules([
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'braces' => ['position_after_functions_and_oop_constructs' => 'same'],
])
->setFinder($finder);

View file

@ -20,3 +20,7 @@ phpunit:
.PHONY: test .PHONY: test
tests: phpunit mocha tests: phpunit mocha
.PHONY: lint
lint:
vendor/bin/php-cs-fixer fix

View file

@ -19,6 +19,7 @@
} }
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.0" "phpunit/phpunit": "^6.0",
"friendsofphp/php-cs-fixer": "^2.4"
} }
} }

2207
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -20,111 +20,111 @@ use Doctrine\DBAL\Connection;
use RandomLib\Generator; use RandomLib\Generator;
class Container { class Container {
private $connection; private $connection;
private $generator; private $generator;
private $baseUrl; private $baseUrl;
private $parserUrl; private $parserUrl;
private $storeRoot; private $storeRoot;
private $storeUrl; private $storeUrl;
private $apiRoot; private $apiRoot;
private $editKey; private $editKey;
public function __construct( public function __construct(
Connection $connection, Connection $connection,
Generator $generator, Generator $generator,
string $baseUrl, string $baseUrl,
string $parserUrl, string $parserUrl,
string $storeRoot, string $storeRoot,
string $storeUrl, string $storeUrl,
string $apiRoot, string $apiRoot,
string $editKey string $editKey
) { ) {
$this->connection = $connection; $this->connection = $connection;
$this->generator = $generator; $this->generator = $generator;
$this->baseUrl = $baseUrl; $this->baseUrl = $baseUrl;
$this->parserUrl = $parserUrl; $this->parserUrl = $parserUrl;
$this->storeRoot = $storeRoot; $this->storeRoot = $storeRoot;
$this->storeUrl = $storeUrl; $this->storeUrl = $storeUrl;
$this->apiRoot = $apiRoot; $this->apiRoot = $apiRoot;
$this->editKey = $editKey; $this->editKey = $editKey;
} }
public function getAuthProvider(): AuthProvider { public function getAuthProvider(): AuthProvider {
return new AuthProvider($this->connection, $this->generator); return new AuthProvider($this->connection, $this->generator);
} }
public function getChatProvider(): ChatProvider { public function getChatProvider(): ChatProvider {
return new ChatProvider($this->connection); return new ChatProvider($this->connection);
} }
public function getDemoListProvider(): DemoListProvider { public function getDemoListProvider(): DemoListProvider {
return new DemoListProvider($this->connection); return new DemoListProvider($this->connection);
} }
public function getDemoProvider(): DemoProvider { public function getDemoProvider(): DemoProvider {
return new DemoProvider($this->connection); return new DemoProvider($this->connection);
} }
public function getInfoProvider(): InfoProvider { public function getInfoProvider(): InfoProvider {
return new InfoProvider($this->connection); return new InfoProvider($this->connection);
} }
public function getKillProvider(): KillProvider { public function getKillProvider(): KillProvider {
return new KillProvider($this->connection); return new KillProvider($this->connection);
} }
public function getPlayerProvider(): PlayerProvider { public function getPlayerProvider(): PlayerProvider {
return new PlayerProvider($this->connection); return new PlayerProvider($this->connection);
} }
public function getUploadProvider(): UploadProvider { public function getUploadProvider(): UploadProvider {
return new UploadProvider( return new UploadProvider(
$this->connection, $this->connection,
$this->baseUrl, $this->baseUrl,
new HeaderParser(), new HeaderParser(),
new Parser(new RawParser($this->parserUrl)), new Parser(new RawParser($this->parserUrl)),
new DemoStore($this->storeRoot, $this->storeUrl), new DemoStore($this->storeRoot, $this->storeUrl),
$this->getUserProvider(), $this->getUserProvider(),
$this->getDemoProvider(), $this->getDemoProvider(),
new DemoSaver( new DemoSaver(
$this->getKillProvider(), $this->getKillProvider(),
$this->getPlayerProvider(), $this->getPlayerProvider(),
$this->getChatProvider(), $this->getChatProvider(),
$this->getUserProvider(), $this->getUserProvider(),
$this->getDemoProvider() $this->getDemoProvider()
) )
); );
} }
public function getUserProvider(): UserProvider { public function getUserProvider(): UserProvider {
return new UserProvider($this->connection, $this->generator); return new UserProvider($this->connection, $this->generator);
} }
public function getBaseUrl(): string { public function getBaseUrl(): string {
return $this->baseUrl; return $this->baseUrl;
} }
public function getParserUrl(): string { public function getParserUrl(): string {
return $this->parserUrl; return $this->parserUrl;
} }
public function getStoreRoot(): string { public function getStoreRoot(): string {
return $this->storeRoot; return $this->storeRoot;
} }
public function getStoreUrl(): string { public function getStoreUrl(): string {
return $this->storeUrl; return $this->storeUrl;
} }
public function getApiRoot(): string { public function getApiRoot(): string {
return $this->apiRoot; return $this->apiRoot;
} }
public function getEditKey(): string { public function getEditKey(): string {
return $this->editKey; return $this->editKey;
} }
public function getConnection(): Connection { public function getConnection(): Connection {
return $this->connection; return $this->connection;
} }
} }

View file

@ -6,69 +6,69 @@ use Demostf\API\Providers\UserProvider;
use flight\Engine; use flight\Engine;
class AuthController extends BaseController { class AuthController extends BaseController {
/** /**
* @var UserProvider * @var UserProvider
*/ */
private $userProvider; private $userProvider;
/** /**
* @var AuthProvider * @var AuthProvider
*/ */
private $authProvider; private $authProvider;
/** @var string */ /** @var string */
private $host; private $host;
private $apiRoot; private $apiRoot;
public function __construct(UserProvider $userProvider, AuthProvider $authProvider, string $host, string $apiRoot) { public function __construct(UserProvider $userProvider, AuthProvider $authProvider, string $host, string $apiRoot) {
$this->userProvider = $userProvider; $this->userProvider = $userProvider;
$this->authProvider = $authProvider; $this->authProvider = $authProvider;
$this->host = $host; $this->host = $host;
$this->apiRoot = $apiRoot; $this->apiRoot = $apiRoot;
} }
public function token() { public function token() {
echo $this->authProvider->generateToken(); echo $this->authProvider->generateToken();
} }
public function get($token) { public function get($token) {
$userData = $this->authProvider->getUser($token); $userData = $this->authProvider->getUser($token);
\Flight::json([ \Flight::json([
'token' => $token, 'token' => $token,
'steamid' => $userData['steamid'], 'steamid' => $userData['steamid'],
'name' => $userData['name'], 'name' => $userData['name'],
'key' => $userData['key'] 'key' => $userData['key']
]); ]);
} }
public function login($token) { public function login($token) {
$_SESSION['return'] = $this->query('return', 'https://' . $this->host); $_SESSION['return'] = $this->query('return', 'https://' . $this->host);
$steam = new SteamLogin(); $steam = new SteamLogin();
$url = $steam->url($this->apiRoot . '/auth/handle/' . urlencode($token), $this->apiRoot); $url = $steam->url($this->apiRoot . '/auth/handle/' . urlencode($token), $this->apiRoot);
\Flight::redirect(str_replace('&amp;', '&', $url)); // headers make no sense \Flight::redirect(str_replace('&amp;', '&', $url)); // headers make no sense
} }
public function logout($token) { public function logout($token) {
$this->authProvider->logout($token); $this->authProvider->logout($token);
\Flight::json([ \Flight::json([
'token' => $token, 'token' => $token,
'steamid' => null, 'steamid' => null,
'name' => null, 'name' => null,
'key' => null 'key' => null
]); ]);
} }
public function handle($token) { public function handle($token) {
$return = $_SESSION['return'] ?? 'https://' . $this->host; $return = $_SESSION['return'] ?? 'https://' . $this->host;
unset($_SESSION['return']); unset($_SESSION['return']);
$steam = new SteamLogin(); $steam = new SteamLogin();
$steamId = $steam->validate(); $steamId = $steam->validate();
if ($steamId) { if ($steamId) {
$steamIdObject = new \SteamId($steamId); $steamIdObject = new \SteamId($steamId);
$key = $this->userProvider->store($steamIdObject); $key = $this->userProvider->store($steamIdObject);
$this->authProvider->setUser($token, $steamIdObject, $key); $this->authProvider->setUser($token, $steamIdObject, $key);
} }
\Flight::redirect($return); \Flight::redirect($return);
} }
} }

View file

@ -1,20 +1,18 @@
<?php namespace Demostf\API\Controllers; <?php namespace Demostf\API\Controllers;
class BaseController { class BaseController {
protected function query($name, $default) {
$request = \Flight::request();
return isset($request->query[$name]) ? $request->query[$name] : $default;
}
protected function query($name, $default) { protected function file($name) {
$request = \Flight::request(); $request = \Flight::request();
return isset($request->query[$name]) ? $request->query[$name] : $default; return $request->files[$name];
} }
protected function file($name) { protected function post($name, $default = null) {
$request = \Flight::request(); $request = \Flight::request();
return $request->files[$name]; return isset($request->data[$name]) ? $request->data[$name] : $default;
} }
protected function post($name, $default = null) {
$request = \Flight::request();
return isset($request->data[$name]) ? $request->data[$name] : $default;
}
} }

View file

@ -6,97 +6,97 @@ use Demostf\API\Providers\DemoProvider;
use flight\Engine; use flight\Engine;
class DemoController extends BaseController { class DemoController extends BaseController {
/** @var DemoProvider */ /** @var DemoProvider */
private $demoProvider; private $demoProvider;
/** @var ChatProvider */ /** @var ChatProvider */
private $chatProvider; private $chatProvider;
private $demoListProvider; private $demoListProvider;
private $editKey; private $editKey;
public function __construct(DemoProvider $demoProvider, ChatProvider $chatProvider, DemoListProvider $demoListProvider, string $editKey) { public function __construct(DemoProvider $demoProvider, ChatProvider $chatProvider, DemoListProvider $demoListProvider, string $editKey) {
$this->demoProvider = $demoProvider; $this->demoProvider = $demoProvider;
$this->chatProvider = $chatProvider; $this->chatProvider = $chatProvider;
$this->demoListProvider = $demoListProvider; $this->demoListProvider = $demoListProvider;
$this->editKey = $editKey; $this->editKey = $editKey;
} }
/** /**
* @param string $id * @param string $id
*/ */
public function get($id) { public function get($id) {
\Flight::json($this->demoProvider->get($id)); \Flight::json($this->demoProvider->get($id));
} }
protected function getFilter() { protected function getFilter() {
$map = $this->query('map', ''); $map = $this->query('map', '');
$players = $this->query('players', ''); $players = $this->query('players', '');
$type = $this->query('type', ''); $type = $this->query('type', '');
$filter = []; $filter = [];
if ($map) { if ($map) {
$filter['map'] = $map; $filter['map'] = $map;
} }
if ($players) { if ($players) {
if (!is_array($players)) { if (!is_array($players)) {
$players = explode(',', $players); $players = explode(',', $players);
} }
$players = array_filter($players); $players = array_filter($players);
$filter['players'] = $players; $filter['players'] = $players;
} }
switch ($type) { switch ($type) {
case 'hl': case 'hl':
$filter['playerCount'] = [17, 18, 19]; $filter['playerCount'] = [17, 18, 19];
break; break;
case '6v6': case '6v6':
$filter['playerCount'] = [11, 12, 13]; $filter['playerCount'] = [11, 12, 13];
break; break;
case '4v4': case '4v4':
$filter['playerCount'] = [7, 8, 9]; $filter['playerCount'] = [7, 8, 9];
break; break;
} }
return $filter; return $filter;
} }
public function listDemos() { public function listDemos() {
$page = $this->query('page', 1); $page = $this->query('page', 1);
$order = $this->query('order', 'DESC') === 'ASC' ? 'ASC' : 'DESC'; $order = $this->query('order', 'DESC') === 'ASC' ? 'ASC' : 'DESC';
\Flight::json($this->demoListProvider->listDemos($page, $this->getFilter(), $order)); \Flight::json($this->demoListProvider->listDemos($page, $this->getFilter(), $order));
} }
public function listProfile($steamid) { public function listProfile($steamid) {
$page = $this->query('page', 1); $page = $this->query('page', 1);
$where = $this->getFilter(); $where = $this->getFilter();
$where['players'][] = $steamid; $where['players'][] = $steamid;
\Flight::json($this->demoListProvider->listProfile($page, $where)); \Flight::json($this->demoListProvider->listProfile($page, $where));
} }
public function listUploads($steamid) { public function listUploads($steamid) {
$page = $this->query('page', 1); $page = $this->query('page', 1);
\Flight::json($this->demoListProvider->listUploads($steamid, $page, $this->getFilter())); \Flight::json($this->demoListProvider->listUploads($steamid, $page, $this->getFilter()));
} }
public function chat($demoId) { public function chat($demoId) {
\Flight::json($this->chatProvider->getChat($demoId)); \Flight::json($this->chatProvider->getChat($demoId));
} }
public function setDemoUrl($id) { public function setDemoUrl($id) {
$hash = $this->post('hash', ''); $hash = $this->post('hash', '');
$backend = $this->post('backend', ''); $backend = $this->post('backend', '');
$path = $this->post('path', ''); $path = $this->post('path', '');
$url = $this->post('url', ''); $url = $this->post('url', '');
$editKey = $this->post('key', ''); $editKey = $this->post('key', '');
if ($editKey !== $this->editKey || $editKey === '') { if ($editKey !== $this->editKey || $editKey === '') {
throw new \InvalidArgumentException('Invalid key'); throw new \InvalidArgumentException('Invalid key');
} }
$demo = $this->demoProvider->get((int)$id); $demo = $this->demoProvider->get((int)$id);
$existingHash = $demo->getHash(); $existingHash = $demo->getHash();
if ($existingHash === '' || $existingHash === $hash) { if ($existingHash === '' || $existingHash === $hash) {
$this->demoProvider->setDemoUrl((int)$id, $backend, $url, $path); $this->demoProvider->setDemoUrl((int)$id, $backend, $url, $path);
} else { } else {
throw new \InvalidArgumentException('Invalid demo hash'); throw new \InvalidArgumentException('Invalid demo hash');
} }
} }
} }

View file

@ -4,18 +4,18 @@ use Demostf\API\Providers\InfoProvider;
use flight\Engine; use flight\Engine;
class InfoController extends BaseController { class InfoController extends BaseController {
/** @var InfoProvider */ /** @var InfoProvider */
private $infoProvider; private $infoProvider;
public function __construct(InfoProvider $infoProvider) { public function __construct(InfoProvider $infoProvider) {
$this->infoProvider = $infoProvider; $this->infoProvider = $infoProvider;
} }
public function listMaps() { public function listMaps() {
\Flight::json($this->infoProvider->listMaps()); \Flight::json($this->infoProvider->listMaps());
} }
public function stats() { public function stats() {
\Flight::json($this->infoProvider->getStats()); \Flight::json($this->infoProvider->getStats());
} }
} }

View file

@ -4,36 +4,36 @@ use Demostf\API\Providers\UploadProvider;
use flight\Engine; use flight\Engine;
class UploadController extends BaseController { class UploadController extends BaseController {
private $uploadProvider; private $uploadProvider;
public function __construct(UploadProvider $uploadProvider) { public function __construct(UploadProvider $uploadProvider) {
$this->uploadProvider = $uploadProvider; $this->uploadProvider = $uploadProvider;
} }
public function upload() { public function upload() {
$key = $this->post('key', ''); $key = $this->post('key', '');
$red = $this->post('red', 'RED'); $red = $this->post('red', 'RED');
$blu = $this->post('blu', 'BLU'); $blu = $this->post('blu', 'BLU');
$name = $this->post('name', 'Unnamed'); $name = $this->post('name', 'Unnamed');
$demo = $this->file('demo'); $demo = $this->file('demo');
if (is_null($demo)) { if (is_null($demo)) {
echo 'No demo uploaded'; echo 'No demo uploaded';
return; return;
} }
$demoFile = $demo['tmp_name']; $demoFile = $demo['tmp_name'];
try { try {
$result = $this->uploadProvider->upload($key, $red, $blu, $name, $demoFile); $result = $this->uploadProvider->upload($key, $red, $blu, $name, $demoFile);
if ($result === 'Invalid key') { if ($result === 'Invalid key') {
\Flight::response()->status(401)->write($result)->send(); \Flight::response()->status(401)->write($result)->send();
} else { } else {
echo $result; echo $result;
} }
} catch (\Exception $e) { } catch (\Exception $e) {
\Flight::response() \Flight::response()
->status(500) ->status(500)
->write($e->getMessage()) ->write($e->getMessage())
->send(); ->send();
} }
} }
} }

View file

@ -6,21 +6,21 @@ use Demostf\API\Providers\UserProvider;
use flight\Engine; use flight\Engine;
class UserController extends BaseController { class UserController extends BaseController {
/** /**
* @var UserProvider * @var UserProvider
*/ */
private $userProvider; private $userProvider;
public function __construct(UserProvider $userProvider) { public function __construct(UserProvider $userProvider) {
$this->userProvider = $userProvider; $this->userProvider = $userProvider;
} }
public function get($steamid) { public function get($steamid) {
\Flight::json($this->userProvider->get($steamid)); \Flight::json($this->userProvider->get($steamid));
} }
public function search() { public function search() {
$query = $this->query('query', ''); $query = $this->query('query', '');
\Flight::json($this->userProvider->search($query)); \Flight::json($this->userProvider->search($query));
} }
} }

View file

@ -3,107 +3,107 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class DemoPlayer implements \JsonSerializable { class DemoPlayer implements \JsonSerializable {
/** @var int */ /** @var int */
private $id; private $id;
/** @var int */ /** @var int */
private $userId; private $userId;
/** @var string */ /** @var string */
private $name; private $name;
/** @var string */ /** @var string */
private $team; private $team;
/** @var string */ /** @var string */
private $class; private $class;
/** @var string */ /** @var string */
private $steamId; private $steamId;
/** @var string */ /** @var string */
private $avatar; private $avatar;
/** @var int */ /** @var int */
private $kills; private $kills;
/** @var int */ /** @var int */
private $assists; private $assists;
/** @var int */ /** @var int */
private $deaths; private $deaths;
public function __construct(int $id, int $userId, string $name, string $team, string $class, string $steamId, string $avatar, int $kills, int $assists, int $deaths) { public function __construct(int $id, int $userId, string $name, string $team, string $class, string $steamId, string $avatar, int $kills, int $assists, int $deaths) {
$this->id = $id; $this->id = $id;
$this->userId = $userId; $this->userId = $userId;
$this->name = $name; $this->name = $name;
$this->team = $team; $this->team = $team;
$this->class = $class; $this->class = $class;
$this->steamId = $steamId; $this->steamId = $steamId;
$this->avatar = $avatar; $this->avatar = $avatar;
$this->kills = $kills; $this->kills = $kills;
$this->assists = $assists; $this->assists = $assists;
$this->deaths = $deaths; $this->deaths = $deaths;
} }
public function getId(): int { public function getId(): int {
return $this->id; return $this->id;
} }
public function getUserId(): int { public function getUserId(): int {
return $this->userId; return $this->userId;
} }
public function getName(): string { public function getName(): string {
return $this->name; return $this->name;
} }
public function getTeam(): string { public function getTeam(): string {
return $this->team; return $this->team;
} }
public function getClass(): string { public function getClass(): string {
return $this->class; return $this->class;
} }
public function getSteamId(): string { public function getSteamId(): string {
return $this->steamId; return $this->steamId;
} }
public function getAvatar(): string { public function getAvatar(): string {
return $this->avatar; return $this->avatar;
} }
public function getKills(): int { public function getKills(): int {
return $this->kills; return $this->kills;
} }
public function getAssists(): int { public function getAssists(): int {
return $this->assists; return $this->assists;
} }
public function getDeaths(): int { public function getDeaths(): int {
return $this->deaths; return $this->deaths;
} }
public static function fromRow($row): DemoPlayer { public static function fromRow($row): DemoPlayer {
return new DemoPlayer( return new DemoPlayer(
$row['id'], $row['id'],
$row['user_id'], $row['user_id'],
$row['name'], $row['name'],
$row['team'], $row['team'],
$row['class'], $row['class'],
$row['steamid'], $row['steamid'],
$row['avatar'], $row['avatar'],
$row['kills'], $row['kills'],
$row['assists'], $row['assists'],
$row['deaths'] $row['deaths']
); );
} }
public function jsonSerialize() { public function jsonSerialize() {
return [ return [
'id' => $this->getId(), 'id' => $this->getId(),
'user_id' => $this->getUserId(), 'user_id' => $this->getUserId(),
'name' => $this->getName(), 'name' => $this->getName(),
'team' => $this->getTeam(), 'team' => $this->getTeam(),
'class' => $this->getClass(), 'class' => $this->getClass(),
'steamid' => $this->getSteamId(), 'steamid' => $this->getSteamId(),
'avatar' => $this->getAvatar(), 'avatar' => $this->getAvatar(),
'kills' => $this->getKills(), 'kills' => $this->getKills(),
'assists' => $this->getAssists(), 'assists' => $this->getAssists(),
'deaths' => $this->getDeaths() 'deaths' => $this->getDeaths()
]; ];
} }
} }

View file

@ -3,48 +3,48 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class Kill { class Kill {
private $id; private $id;
private $demoId; private $demoId;
private $attackerId; private $attackerId;
private $assisterId; private $assisterId;
private $victimId; private $victimId;
private $weapon; private $weapon;
public function __construct(int $id, int $demoId, int $attackerId, int $assisterId, int $victimId, string $weapon) { public function __construct(int $id, int $demoId, int $attackerId, int $assisterId, int $victimId, string $weapon) {
$this->id = $id; $this->id = $id;
$this->demoId = $demoId; $this->demoId = $demoId;
$this->attackerId = $attackerId; $this->attackerId = $attackerId;
$this->assisterId = $assisterId; $this->assisterId = $assisterId;
$this->victimId = $victimId; $this->victimId = $victimId;
$this->weapon = $weapon; $this->weapon = $weapon;
} }
public function getId(): int { public function getId(): int {
return $this->id; return $this->id;
} }
public function getDemoId(): int { public function getDemoId(): int {
return $this->demoId; return $this->demoId;
} }
public function getAttackerId(): int { public function getAttackerId(): int {
return $this->attackerId; return $this->attackerId;
} }
public function getAssisterId(): int { public function getAssisterId(): int {
return $this->assisterId; return $this->assisterId;
} }
public function getVictimId(): int { public function getVictimId(): int {
return $this->victimId; return $this->victimId;
} }
public function getWeapon(): string { public function getWeapon(): string {
return $this->weapon; return $this->weapon;
} }
} }

View file

@ -5,60 +5,60 @@ namespace Demostf\API\Data;
use Demostf\API\Demo\ChatMessage; use Demostf\API\Demo\ChatMessage;
class ParsedDemo { class ParsedDemo {
/** @var int */ /** @var int */
private $redScore; private $redScore;
/** @var int */ /** @var int */
private $blueScore; private $blueScore;
/** @var ChatMessage[] */ /** @var ChatMessage[] */
private $chat; private $chat;
/** @var ParsedPlayer[] */ /** @var ParsedPlayer[] */
private $players; private $players;
/** @var ParsedKill[] */ /** @var ParsedKill[] */
private $kills; private $kills;
/** /**
* ParsedDemo constructor. * ParsedDemo constructor.
* *
* @param int $redScore * @param int $redScore
* @param int $blueScore * @param int $blueScore
* @param ChatMessage[] $chat * @param ChatMessage[] $chat
* @param ParsedPlayer[] $players * @param ParsedPlayer[] $players
* @param ParsedKill[] $kills * @param ParsedKill[] $kills
*/ */
public function __construct(int $redScore, int $blueScore, array $chat, array $players, array $kills) { public function __construct(int $redScore, int $blueScore, array $chat, array $players, array $kills) {
$this->redScore = $redScore; $this->redScore = $redScore;
$this->blueScore = $blueScore; $this->blueScore = $blueScore;
$this->chat = $chat; $this->chat = $chat;
$this->players = $players; $this->players = $players;
$this->kills = $kills; $this->kills = $kills;
} }
public function getRedScore(): int { public function getRedScore(): int {
return $this->redScore; return $this->redScore;
} }
public function getBlueScore(): int { public function getBlueScore(): int {
return $this->blueScore; return $this->blueScore;
} }
/** /**
* @return ChatMessage[] * @return ChatMessage[]
*/ */
public function getChat(): array { public function getChat(): array {
return $this->chat; return $this->chat;
} }
/** /**
* @return ParsedPlayer[] * @return ParsedPlayer[]
*/ */
public function getPlayers(): array { public function getPlayers(): array {
return $this->players; return $this->players;
} }
/** /**
* @return ParsedKill[] * @return ParsedKill[]
*/ */
public function getKills(): array { public function getKills(): array {
return $this->kills; return $this->kills;
} }
} }

View file

@ -3,34 +3,34 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class ParsedKill { class ParsedKill {
private $attackerDemoId; private $attackerDemoId;
private $assisterDemoId; private $assisterDemoId;
private $victimDemoId; private $victimDemoId;
private $weapon; private $weapon;
public function __construct(int $attackerDemoId, int $assisterDemoId, int $victimDemoId, string $weapon) { public function __construct(int $attackerDemoId, int $assisterDemoId, int $victimDemoId, string $weapon) {
$this->attackerDemoId = $attackerDemoId; $this->attackerDemoId = $attackerDemoId;
$this->assisterDemoId = $assisterDemoId; $this->assisterDemoId = $assisterDemoId;
$this->victimDemoId = $victimDemoId; $this->victimDemoId = $victimDemoId;
$this->weapon = $weapon; $this->weapon = $weapon;
} }
public function getAttackerDemoId(): int { public function getAttackerDemoId(): int {
return $this->attackerDemoId; return $this->attackerDemoId;
} }
public function getAssisterDemoId(): int { public function getAssisterDemoId(): int {
return $this->assisterDemoId; return $this->assisterDemoId;
} }
public function getVictimDemoId(): int { public function getVictimDemoId(): int {
return $this->victimDemoId; return $this->victimDemoId;
} }
public function getWeapon(): string { public function getWeapon(): string {
return $this->weapon; return $this->weapon;
} }
} }

View file

@ -3,42 +3,42 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class ParsedPlayer { class ParsedPlayer {
/** @var string */ /** @var string */
private $name; private $name;
/** @var int */ /** @var int */
private $demoUserId; private $demoUserId;
/** @var string */ /** @var string */
private $steamId; private $steamId;
/** @var string */ /** @var string */
private $team; private $team;
/** @var string` */ /** @var string` */
private $class; private $class;
public function __construct(string $name, int $demoUserId, string $steamId, string $team, string $class) { public function __construct(string $name, int $demoUserId, string $steamId, string $team, string $class) {
$this->name = $name; $this->name = $name;
$this->demoUserId = $demoUserId; $this->demoUserId = $demoUserId;
$this->steamId = $steamId; $this->steamId = $steamId;
$this->team = $team; $this->team = $team;
$this->class = $class; $this->class = $class;
} }
public function getName(): string { public function getName(): string {
return $this->name; return $this->name;
} }
public function getDemoUserId(): int { public function getDemoUserId(): int {
return $this->demoUserId; return $this->demoUserId;
} }
public function getSteamId(): string { public function getSteamId(): string {
return $this->steamId; return $this->steamId;
} }
public function getTeam(): string { public function getTeam(): string {
return $this->team; return $this->team;
} }
public function getClass(): string { public function getClass(): string {
return $this->class; return $this->class;
} }
} }

View file

@ -3,62 +3,62 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class Player { class Player {
/** @var int */ /** @var int */
private $id; private $id;
/** @var int */ /** @var int */
private $demoId; private $demoId;
/** @var int */ /** @var int */
private $demoUserId; private $demoUserId;
/** @var int */ /** @var int */
private $userId; private $userId;
/** @var string */ /** @var string */
private $name; private $name;
/** @var string */ /** @var string */
private $team; private $team;
/** @var string */ /** @var string */
private $class; private $class;
public function __construct(int $id, int $demoId, int $demoUserId, int $userId, string $name, string $team, string $class) { public function __construct(int $id, int $demoId, int $demoUserId, int $userId, string $name, string $team, string $class) {
$this->id = $id; $this->id = $id;
$this->demoId = $demoId; $this->demoId = $demoId;
$this->demoUserId = $demoUserId; $this->demoUserId = $demoUserId;
$this->userId = $userId; $this->userId = $userId;
$this->name = $name; $this->name = $name;
$this->team = $team; $this->team = $team;
$this->class = $class; $this->class = $class;
} }
public function getId(): int { public function getId(): int {
return $this->id; return $this->id;
} }
public function getDemoId(): int { public function getDemoId(): int {
return $this->demoId; return $this->demoId;
} }
public function getDemoUserId(): int { public function getDemoUserId(): int {
return $this->demoUserId; return $this->demoUserId;
} }
public function getUserId(): int { public function getUserId(): int {
return $this->userId; return $this->userId;
} }
public function getName(): string { public function getName(): string {
return $this->name; return $this->name;
} }
public function getTeam(): string { public function getTeam(): string {
return $this->team; return $this->team;
} }
public function getClass(): string { public function getClass(): string {
return $this->class; return $this->class;
} }
} }

View file

@ -3,28 +3,28 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class StoredDemo { class StoredDemo {
/** @var string */ /** @var string */
private $url; private $url;
/** @var string */ /** @var string */
private $backend; private $backend;
/** @var string */ /** @var string */
private $path; private $path;
public function __construct(string $url, string $backend, string $path) { public function __construct(string $url, string $backend, string $path) {
$this->url = $url; $this->url = $url;
$this->backend = $backend; $this->backend = $backend;
$this->path = $path; $this->path = $path;
} }
public function getUrl(): string { public function getUrl(): string {
return $this->url; return $this->url;
} }
public function getBackend(): string { public function getBackend(): string {
return $this->backend; return $this->backend;
} }
public function getPath(): string { public function getPath(): string {
return $this->path; return $this->path;
} }
} }

View file

@ -3,42 +3,42 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class Upload { class Upload {
/** @var string */ /** @var string */
private $name; private $name;
/** @var string */ /** @var string */
private $red; private $red;
/** @var string */ /** @var string */
private $blue; private $blue;
/** @var int */ /** @var int */
private $uploaderId; private $uploaderId;
/** @var string */ /** @var string */
private $hash; private $hash;
public function __construct(string $name, string $red, string $blue, int $uploaderId, string $hash) { public function __construct(string $name, string $red, string $blue, int $uploaderId, string $hash) {
$this->name = $name; $this->name = $name;
$this->red = $red; $this->red = $red;
$this->blue = $blue; $this->blue = $blue;
$this->uploaderId = $uploaderId; $this->uploaderId = $uploaderId;
$this->hash = $hash; $this->hash = $hash;
} }
public function getName(): string { public function getName(): string {
return $this->name; return $this->name;
} }
public function getRed(): string { public function getRed(): string {
return $this->red; return $this->red;
} }
public function getBlue(): string { public function getBlue(): string {
return $this->blue; return $this->blue;
} }
public function getUploaderId(): int { public function getUploaderId(): int {
return $this->uploaderId; return $this->uploaderId;
} }
public function getHash(): string { public function getHash(): string {
return $this->hash; return $this->hash;
} }
} }

View file

@ -3,61 +3,61 @@
namespace Demostf\API\Data; namespace Demostf\API\Data;
class User implements \JsonSerializable { class User implements \JsonSerializable {
/** @var int */ /** @var int */
private $id; private $id;
/** @var string */ /** @var string */
private $steamId; private $steamId;
/** @var string */ /** @var string */
private $name; private $name;
/** @var string */ /** @var string */
private $avatar; private $avatar;
/** @var string */ /** @var string */
private $token; private $token;
public function __construct(int $id, string $steamId, string $name, string $avatar, string $token) { public function __construct(int $id, string $steamId, string $name, string $avatar, string $token) {
$this->id = $id; $this->id = $id;
$this->steamId = $steamId; $this->steamId = $steamId;
$this->name = $name; $this->name = $name;
$this->avatar = $avatar; $this->avatar = $avatar;
$this->token = $token; $this->token = $token;
} }
public function getId(): int { public function getId(): int {
return $this->id; return $this->id;
} }
public function getSteamId(): string { public function getSteamId(): string {
return $this->steamId; return $this->steamId;
} }
public function getName(): string { public function getName(): string {
return $this->name; return $this->name;
} }
public function getAvatar(): string { public function getAvatar(): string {
return $this->avatar; return $this->avatar;
} }
public function getToken(): string { public function getToken(): string {
return $this->token; return $this->token;
} }
public function jsonSerialize() { public function jsonSerialize() {
return [ return [
'id' => $this->getId(), 'id' => $this->getId(),
'steamid' => $this->getSteamId(), 'steamid' => $this->getSteamId(),
'name' => $this->getName(), 'name' => $this->getName(),
'avatar' => $this->getAvatar() 'avatar' => $this->getAvatar()
]; ];
} }
public static function fromRow(array $row): User { public static function fromRow(array $row): User {
return new User( return new User(
(int)$row['id'], (int)$row['id'],
$row['steamid'], $row['steamid'],
$row['name'], $row['name'],
$row['avatar'], $row['avatar'],
$row['token'] ?? '' $row['token'] ?? ''
); );
} }
} }

View file

@ -1,46 +1,46 @@
<?php namespace Demostf\API\Demo; <?php namespace Demostf\API\Demo;
class ChatMessage { class ChatMessage {
/** @var string */ /** @var string */
private $user; private $user;
/** @var integer */ /** @var integer */
private $time; private $time;
/** @var string */ /** @var string */
private $message; private $message;
/** /**
* ChatMessage constructor. * ChatMessage constructor.
* *
* @param string $user * @param string $user
* @param int $time * @param int $time
* @param string $message * @param string $message
*/ */
public function __construct(string $user, int $time, string $message) { public function __construct(string $user, int $time, string $message) {
$this->user = $user; $this->user = $user;
$this->time = $time; $this->time = $time;
$this->message = $message; $this->message = $message;
} }
/** /**
* @return string * @return string
*/ */
public function getUser(): string { public function getUser(): string {
return $this->user; return $this->user;
} }
/** /**
* @return int * @return int
*/ */
public function getTime(): int { public function getTime(): int {
return $this->time; return $this->time;
} }
/** /**
* @return string * @return string
*/ */
public function getMessage(): string { public function getMessage(): string {
return $this->message; return $this->message;
} }
} }

View file

@ -4,215 +4,215 @@ use Demostf\API\Data\DemoPlayer;
use Demostf\API\Data\User; use Demostf\API\Data\User;
class Demo implements \JsonSerializable { class Demo implements \JsonSerializable {
/** @var int */ /** @var int */
private $id; private $id;
/** @var string */ /** @var string */
private $url; private $url;
/** @var string */ /** @var string */
private $name; private $name;
/** @var string */ /** @var string */
private $server; private $server;
/** @var float */ /** @var float */
private $duration; private $duration;
/** @var string */ /** @var string */
private $nick; private $nick;
/** @var string */ /** @var string */
private $map; private $map;
/** @var \DateTime */ /** @var \DateTime */
private $time; private $time;
/** @var string */ /** @var string */
private $red; private $red;
/** @var string */ /** @var string */
private $blue; private $blue;
/** @var int */ /** @var int */
private $redScore; private $redScore;
/** @var int */ /** @var int */
private $blueScore; private $blueScore;
/** @var int */ /** @var int */
private $playerCount; private $playerCount;
/** @var int */ /** @var int */
private $uploader; private $uploader;
/** @var User|null */ /** @var User|null */
private $uploaderUser; private $uploaderUser;
/** @var DemoPlayer[] */ /** @var DemoPlayer[] */
private $players; private $players;
/** @var string */ /** @var string */
private $hash; private $hash;
/** @var string */ /** @var string */
private $backend; private $backend;
/** @var string */ /** @var string */
private $path; private $path;
public function __construct( public function __construct(
int $id, int $id,
string $url, string $url,
string $name, string $name,
string $server, string $server,
float $duration, float $duration,
string $nick, string $nick,
string $map, string $map,
\DateTime $time, \DateTime $time,
string $red, string $red,
string $blue, string $blue,
int $redScore, int $redScore,
int $blueScore, int $blueScore,
int $playerCount, int $playerCount,
int $uploader, int $uploader,
string $hash, string $hash,
string $backend, string $backend,
string $path string $path
) { ) {
$this->id = $id; $this->id = $id;
$this->url = $url; $this->url = $url;
$this->name = $name; $this->name = $name;
$this->server = $server; $this->server = $server;
$this->duration = $duration; $this->duration = $duration;
$this->nick = $nick; $this->nick = $nick;
$this->map = $map; $this->map = $map;
$this->time = $time; $this->time = $time;
$this->red = $red; $this->red = $red;
$this->blue = $blue; $this->blue = $blue;
$this->redScore = $redScore; $this->redScore = $redScore;
$this->blueScore = $blueScore; $this->blueScore = $blueScore;
$this->playerCount = $playerCount; $this->playerCount = $playerCount;
$this->uploader = $uploader; $this->uploader = $uploader;
$this->hash = $hash; $this->hash = $hash;
$this->backend = $backend; $this->backend = $backend;
$this->path = $path; $this->path = $path;
} }
public function getId(): int { public function getId(): int {
return $this->id; return $this->id;
} }
public function getUrl(): string { public function getUrl(): string {
return $this->url; return $this->url;
} }
public function getName(): string { public function getName(): string {
return $this->name; return $this->name;
} }
public function getServer(): string { public function getServer(): string {
return $this->server; return $this->server;
} }
public function getDuration(): float { public function getDuration(): float {
return $this->duration; return $this->duration;
} }
public function getNick(): string { public function getNick(): string {
return $this->nick; return $this->nick;
} }
public function getMap(): string { public function getMap(): string {
return $this->map; return $this->map;
} }
public function getTime(): \DateTime { public function getTime(): \DateTime {
return $this->time; return $this->time;
} }
public function getRed(): string { public function getRed(): string {
return $this->red; return $this->red;
} }
public function getBlue(): string { public function getBlue(): string {
return $this->blue; return $this->blue;
} }
public function getRedScore(): int { public function getRedScore(): int {
return $this->redScore; return $this->redScore;
} }
public function getBlueScore(): int { public function getBlueScore(): int {
return $this->blueScore; return $this->blueScore;
} }
public function getPlayerCount(): int { public function getPlayerCount(): int {
return $this->playerCount; return $this->playerCount;
} }
public function getUploader(): int { public function getUploader(): int {
return $this->uploader; return $this->uploader;
} }
public function getUploaderUser(): ?User { public function getUploaderUser(): ?User {
return $this->uploaderUser; return $this->uploaderUser;
} }
public function setUploaderUser(User $uploaderUser) { public function setUploaderUser(User $uploaderUser) {
$this->uploaderUser = $uploaderUser; $this->uploaderUser = $uploaderUser;
} }
public static function fromRow($row): Demo { public static function fromRow($row): Demo {
return new Demo( return new Demo(
(int)$row['id'], (int)$row['id'],
$row['url'], $row['url'],
$row['name'], $row['name'],
$row['server'], $row['server'],
(int)$row['duration'], (int)$row['duration'],
$row['nick'], $row['nick'],
$row['map'], $row['map'],
\DateTime::createFromFormat('U', '' . strtotime($row['created_at'])), \DateTime::createFromFormat('U', '' . strtotime($row['created_at'])),
$row['red'], $row['red'],
$row['blu'], $row['blu'],
(int)$row['scoreRed'], (int)$row['scoreRed'],
(int)$row['scoreBlue'], (int)$row['scoreBlue'],
(int)$row['playerCount'], (int)$row['playerCount'],
(int)$row['uploader'], (int)$row['uploader'],
$row['hash'], $row['hash'],
$row['backend'], $row['backend'],
$row['path'] $row['path']
); );
} }
/** /**
* @return DemoPlayer[] * @return DemoPlayer[]
*/ */
public function getPlayers(): array { public function getPlayers(): array {
return $this->players; return $this->players;
} }
public function setPlayers(array $players) { public function setPlayers(array $players) {
$this->players = $players; $this->players = $players;
} }
public function getHash(): string { public function getHash(): string {
return $this->hash; return $this->hash;
} }
public function getBackend(): string { public function getBackend(): string {
return $this->backend; return $this->backend;
} }
public function getPath(): string { public function getPath(): string {
return $this->path; return $this->path;
} }
public function jsonSerialize() { public function jsonSerialize() {
$data = [ $data = [
'id' => $this->getId(), 'id' => $this->getId(),
'url' => $this->getUrl(), 'url' => $this->getUrl(),
'name' => $this->getName(), 'name' => $this->getName(),
'server' => $this->getServer(), 'server' => $this->getServer(),
'duration' => $this->getDuration(), 'duration' => $this->getDuration(),
'nick' => $this->getNick(), 'nick' => $this->getNick(),
'map' => $this->getMap(), 'map' => $this->getMap(),
'time' => $this->getTime()->getTimestamp(), 'time' => $this->getTime()->getTimestamp(),
'red' => $this->getRed(), 'red' => $this->getRed(),
'blue' => $this->getBlue(), 'blue' => $this->getBlue(),
'redScore' => $this->getRedScore(), 'redScore' => $this->getRedScore(),
'blueScore' => $this->getBlueScore(), 'blueScore' => $this->getBlueScore(),
'playerCount' => $this->getPlayerCount(), 'playerCount' => $this->getPlayerCount(),
'uploader' => $this->uploaderUser ? $this->getUploaderUser()->jsonSerialize() : $this->getUploader(), 'uploader' => $this->uploaderUser ? $this->getUploaderUser()->jsonSerialize() : $this->getUploader(),
'hash' => $this->getHash(), 'hash' => $this->getHash(),
'backend' => $this->getBackend(), 'backend' => $this->getBackend(),
'path' => $this->getPath() 'path' => $this->getPath()
]; ];
if ($this->players) { if ($this->players) {
$data['players'] = $this->getPlayers(); $data['players'] = $this->getPlayers();
} }
return $data; return $data;
} }
} }

View file

@ -14,79 +14,79 @@ use Demostf\API\Providers\PlayerProvider;
use Demostf\API\Providers\UserProvider; use Demostf\API\Providers\UserProvider;
class DemoSaver { class DemoSaver {
/** @var KillProvider */ /** @var KillProvider */
private $killProvider; private $killProvider;
/** @var PlayerProvider */ /** @var PlayerProvider */
private $playerProvider; private $playerProvider;
/** @var ChatProvider */ /** @var ChatProvider */
private $chatProvider; private $chatProvider;
/** @var UserProvider */ /** @var UserProvider */
private $userProvider; private $userProvider;
/** @var DemoProvider */ /** @var DemoProvider */
private $demoProvider; private $demoProvider;
public function __construct(KillProvider $killProvider, PlayerProvider $playerProvider, ChatProvider $chatProvider, UserProvider $userProvider, DemoProvider $demoProvider) { public function __construct(KillProvider $killProvider, PlayerProvider $playerProvider, ChatProvider $chatProvider, UserProvider $userProvider, DemoProvider $demoProvider) {
$this->killProvider = $killProvider; $this->killProvider = $killProvider;
$this->playerProvider = $playerProvider; $this->playerProvider = $playerProvider;
$this->chatProvider = $chatProvider; $this->chatProvider = $chatProvider;
$this->userProvider = $userProvider; $this->userProvider = $userProvider;
$this->demoProvider = $demoProvider; $this->demoProvider = $demoProvider;
} }
public function saveDemo(ParsedDemo $demo, Header $header, StoredDemo $storedDemo, Upload $upload): int { public function saveDemo(ParsedDemo $demo, Header $header, StoredDemo $storedDemo, Upload $upload): int {
/** @var int[] $userMap [$demoUserId => $dbUserId] */ /** @var int[] $userMap [$demoUserId => $dbUserId] */
$userMap = [0 => 0]; $userMap = [0 => 0];
$demoId = $this->demoProvider->storeDemo(new Demo( $demoId = $this->demoProvider->storeDemo(new Demo(
0, 0,
$storedDemo->getUrl(), $storedDemo->getUrl(),
$upload->getName(), $upload->getName(),
$header->getServer(), $header->getServer(),
$header->getDuration(), $header->getDuration(),
$header->getNick(), $header->getNick(),
$header->getMap(), $header->getMap(),
new \DateTime(), new \DateTime(),
$upload->getRed(), $upload->getRed(),
$upload->getBlue(), $upload->getBlue(),
$demo->getRedScore(), $demo->getRedScore(),
$demo->getBlueScore(), $demo->getBlueScore(),
count($demo->getPlayers()), count($demo->getPlayers()),
$upload->getUploaderId(), $upload->getUploaderId(),
$upload->getHash(), $upload->getHash(),
$storedDemo->getBackend(), $storedDemo->getBackend(),
$storedDemo->getPath() $storedDemo->getPath()
), $storedDemo->getBackend(), $storedDemo->getPath()); ), $storedDemo->getBackend(), $storedDemo->getPath());
foreach ($demo->getPlayers() as $player) { foreach ($demo->getPlayers() as $player) {
$userId = $this->userProvider->getUserId($player->getSteamId()); $userId = $this->userProvider->getUserId($player->getSteamId());
$userMap[$player->getDemoUserId()] = $userId; $userMap[$player->getDemoUserId()] = $userId;
$this->playerProvider->store(new Player( $this->playerProvider->store(new Player(
0, 0,
$demoId, $demoId,
$player->getDemoUserId(), $player->getDemoUserId(),
$userId, $userId,
$player->getName(), $player->getName(),
$player->getTeam(), $player->getTeam(),
$player->getClass() $player->getClass()
)); ));
} }
foreach ($demo->getKills() as $kill) { foreach ($demo->getKills() as $kill) {
$this->killProvider->store(new Kill( $this->killProvider->store(new Kill(
0, 0,
$demoId, $demoId,
$userMap[$kill->getAttackerDemoId()], $userMap[$kill->getAttackerDemoId()],
$userMap[$kill->getAssisterDemoId()], $userMap[$kill->getAssisterDemoId()],
$userMap[$kill->getVictimDemoId()], $userMap[$kill->getVictimDemoId()],
$kill->getWeapon() $kill->getWeapon()
)); ));
} }
foreach ($demo->getChat() as $chat) { foreach ($demo->getChat() as $chat) {
$this->chatProvider->storeChatMessage($demoId, $chat); $this->chatProvider->storeChatMessage($demoId, $chat);
} }
return $demoId; return $demoId;
} }
} }

View file

@ -3,35 +3,35 @@
use Demostf\API\Data\StoredDemo; use Demostf\API\Data\StoredDemo;
class DemoStore { class DemoStore {
/** @var string */ /** @var string */
private $root; private $root;
/** @var string */ /** @var string */
private $webroot; private $webroot;
public function __construct(string $root, string $webroot) { public function __construct(string $root, string $webroot) {
$this->root = $root; $this->root = $root;
$this->webroot = $webroot; $this->webroot = $webroot;
} }
public function store(string $sourcePath, string $name): StoredDemo { public function store(string $sourcePath, string $name): StoredDemo {
$target = $this->generatePath($name); $target = $this->generatePath($name);
if (!is_dir(dirname($target))) { if (!is_dir(dirname($target))) {
mkdir(dirname($target), 0777, true); mkdir(dirname($target), 0777, true);
} }
rename($sourcePath, $target); rename($sourcePath, $target);
chmod($target, 0755); chmod($target, 0755);
return new StoredDemo($this->getUrl($name), 'static', $target); return new StoredDemo($this->getUrl($name), 'static', $target);
} }
private function generatePath(string $name): string { private function generatePath(string $name): string {
return $this->root . $this->getPrefix($name) . $name; return $this->root . $this->getPrefix($name) . $name;
} }
private function getPrefix(string $name) { private function getPrefix(string $name) {
return '/' . substr($name, 0, 2) . '/' . substr($name, 2, 2) . '/'; return '/' . substr($name, 0, 2) . '/' . substr($name, 2, 2) . '/';
} }
private function getUrl(string $name): string { private function getUrl(string $name): string {
return 'https://' . $this->webroot . $this->getPrefix($name) . $name; return 'https://' . $this->webroot . $this->getPrefix($name) . $name;
} }
} }

View file

@ -6,144 +6,144 @@ namespace Demostf\API\Demo;
* HL2 demo metadata * HL2 demo metadata
*/ */
class Header { class Header {
/** /**
* @var string * @var string
*/ */
protected $type; protected $type;
/** /**
* @var int * @var int
*/ */
protected $version; protected $version;
/** /**
* @var int * @var int
*/ */
protected $protocol; protected $protocol;
/** /**
* @var string * @var string
*/ */
protected $server; protected $server;
/** /**
* @var string * @var string
*/ */
protected $nick; protected $nick;
/** /**
* @var string * @var string
*/ */
protected $map; protected $map;
/** /**
* @var string * @var string
*/ */
protected $game; protected $game;
/** /**
* @var float * @var float
*/ */
protected $duration; protected $duration;
/** /**
* @var int * @var int
*/ */
protected $ticks; protected $ticks;
/** /**
* @var int * @var int
*/ */
protected $frames; protected $frames;
/** /**
* @var int * @var int
*/ */
protected $sigon; protected $sigon;
public function __construct( public function __construct(
string $type, string $type,
int $version, int $version,
int $protocol, int $protocol,
string $server, string $server,
string $nick, string $nick,
string $map, string $map,
string $game, string $game,
float $duration, float $duration,
int $ticks, int $ticks,
int $frames, int $frames,
int $sigon int $sigon
) { ) {
$this->type = $type; $this->type = $type;
$this->version = $version; $this->version = $version;
$this->protocol = $protocol; $this->protocol = $protocol;
$this->server = $server; $this->server = $server;
$this->nick = $nick; $this->nick = $nick;
$this->map = $map; $this->map = $map;
$this->game = $game; $this->game = $game;
$this->duration = $duration; $this->duration = $duration;
$this->ticks = $ticks; $this->ticks = $ticks;
$this->frames = $frames; $this->frames = $frames;
$this->sigon = $sigon; $this->sigon = $sigon;
} }
public function getDuration(): float { public function getDuration(): float {
return $this->duration; return $this->duration;
} }
public function getFrames(): int { public function getFrames(): int {
return $this->frames; return $this->frames;
} }
public function getGame(): string { public function getGame(): string {
return $this->game; return $this->game;
} }
public function getMap(): string { public function getMap(): string {
return $this->map; return $this->map;
} }
public function getNick(): string { public function getNick(): string {
return $this->nick; return $this->nick;
} }
public function getProtocol(): int { public function getProtocol(): int {
return $this->protocol; return $this->protocol;
} }
public function getServer(): string { public function getServer(): string {
return $this->server; return $this->server;
} }
public function getSigon(): int { public function getSigon(): int {
return $this->sigon; return $this->sigon;
} }
public function getTicks(): int { public function getTicks(): int {
return $this->ticks; return $this->ticks;
} }
public function getType(): string { public function getType(): string {
return $this->type; return $this->type;
} }
public function getVersion(): int { public function getVersion(): int {
return $this->version; return $this->version;
} }
public static function fromArray(array $info) { public static function fromArray(array $info) {
return new Header( return new Header(
$info['type'], $info['type'],
$info['version'], $info['version'],
$info['protocol'], $info['protocol'],
$info['server'], $info['server'],
$info['nick'], $info['nick'],
$info['map'], $info['map'],
$info['game'], $info['game'],
$info['duration'], $info['duration'],
$info['ticks'], $info['ticks'],
$info['frames'], $info['frames'],
$info['sigon'] $info['sigon']
); );
} }
} }

View file

@ -3,44 +3,46 @@
namespace Demostf\API\Demo; namespace Demostf\API\Demo;
class HeaderParser { class HeaderParser {
/** /**
* @param string $head string containing the demo header binary data * @param string $head string containing the demo header binary data
* @return Header * @return Header
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function parseString(string $head): Header { public function parseString(string $head): Header {
$info = @unpack('A8type/Iversion/Iprotocol/A260server/A260nick/A260map/A260game/fduration/Vticks/Vframes/Vsigon', $info = @unpack(
$head); 'A8type/Iversion/Iprotocol/A260server/A260nick/A260map/A260game/fduration/Vticks/Vframes/Vsigon',
if (!isset($info['type']) || $info['type'] !== 'HL2DEMO') { $head
throw new \InvalidArgumentException('Not an HL2 demo'); );
} if (!isset($info['type']) || $info['type'] !== 'HL2DEMO') {
return Header::fromArray($info); throw new \InvalidArgumentException('Not an HL2 demo');
} }
return Header::fromArray($info);
}
/** /**
* Parse demo info from a stream * Parse demo info from a stream
* *
* @param resource $stream * @param resource $stream
* @return Header * @return Header
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function parseStream($stream): Header { public function parseStream($stream): Header {
$head = fread($stream, 2048); $head = fread($stream, 2048);
return $this->parseString($head); return $this->parseString($head);
} }
/** /**
* Parse demo info from a local file * Parse demo info from a local file
* *
* @param string $path * @param string $path
* @return Header * @return Header
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function parseHeader(string $path): Header { public function parseHeader(string $path): Header {
if (!is_readable($path)) { if (!is_readable($path)) {
throw new \InvalidArgumentException('Unable to open demo: ' . $path); throw new \InvalidArgumentException('Unable to open demo: ' . $path);
} }
$fh = fopen($path, 'rb'); $fh = fopen($path, 'rb');
return $this->parseStream($fh); return $this->parseStream($fh);
} }
} }

View file

@ -13,118 +13,118 @@ use Demostf\API\Data\Player;
* Processes the raw demo.js output to something more suitable for our purpose * Processes the raw demo.js output to something more suitable for our purpose
*/ */
class Parser { class Parser {
const CLASSES = [ const CLASSES = [
1 => 'scout', 1 => 'scout',
2 => 'sniper', 2 => 'sniper',
3 => 'soldier', 3 => 'soldier',
4 => 'demoman', 4 => 'demoman',
5 => 'medic', 5 => 'medic',
6 => 'heavyweapons', 6 => 'heavyweapons',
7 => 'pyro', 7 => 'pyro',
8 => 'spy', 8 => 'spy',
9 => 'engineer' 9 => 'engineer'
]; ];
/** @var RawParser */ /** @var RawParser */
private $rawParser; private $rawParser;
public function __construct(RawParser $rawParser) { public function __construct(RawParser $rawParser) {
$this->rawParser = $rawParser; $this->rawParser = $rawParser;
} }
public function analyse(string $path): ParsedDemo { public function analyse(string $path): ParsedDemo {
$data = $this->rawParser->parse($path); $data = $this->rawParser->parse($path);
if (!is_array($data)) { if (!is_array($data)) {
throw new \InvalidArgumentException('Error parsing demo'); throw new \InvalidArgumentException('Error parsing demo');
} }
return $this->handleData($data); return $this->handleData($data);
} }
private function handleData(array $data): ParsedDemo { private function handleData(array $data): ParsedDemo {
$intervalPerTick = $data['intervalPerTick']; $intervalPerTick = $data['intervalPerTick'];
$red = 0; $red = 0;
$blue = 0; $blue = 0;
/** @var ChatMessage[] $chat */ /** @var ChatMessage[] $chat */
$chat = []; $chat = [];
/** @var ParsedPlayer[] $players */ /** @var ParsedPlayer[] $players */
$players = []; $players = [];
foreach ($data['rounds'] as $round) { foreach ($data['rounds'] as $round) {
if ($round['winner'] === 'red') { if ($round['winner'] === 'red') {
$red++; $red++;
} else { } else {
$blue++; $blue++;
} }
} }
foreach ($data['chat'] as $message) { foreach ($data['chat'] as $message) {
if (isset($message['from'])) { if (isset($message['from'])) {
$chat[] = new ChatMessage($message['from'], (int)floor(($message['tick'] - $data['startTick']) * $intervalPerTick), $message['text']); $chat[] = new ChatMessage($message['from'], (int)floor(($message['tick'] - $data['startTick']) * $intervalPerTick), $message['text']);
} }
} }
foreach ($data['users'] as $player) { foreach ($data['users'] as $player) {
$class = 0; $class = 0;
$classSpawns = 0; $classSpawns = 0;
foreach ($player['classes'] as $classId => $spawns) { foreach ($player['classes'] as $classId => $spawns) {
if ($spawns > $classSpawns) { if ($spawns > $classSpawns) {
$classSpawns = $spawns; $classSpawns = $spawns;
$class = $classId; $class = $classId;
} }
} }
if ($class && $player['steamId']) {//skip spectators if ($class && $player['steamId']) {//skip spectators
$players[] = new ParsedPlayer( $players[] = new ParsedPlayer(
$player['name'], $player['name'],
$player['userId'], $player['userId'],
$this->convertSteamIdToCommunityId($player['steamId']), $this->convertSteamIdToCommunityId($player['steamId']),
$player['team'], $player['team'],
$this->getClassName((int)$class) $this->getClassName((int)$class)
); );
} }
} }
$kills = array_map(function (array $death) { $kills = array_map(function (array $death) {
return new ParsedKill($death['killer'] ?? 0, $death['assister'] ?? 0, $death['victim'] ?? 0, $death['weapon']); return new ParsedKill($death['killer'] ?? 0, $death['assister'] ?? 0, $death['victim'] ?? 0, $death['weapon']);
}, $data['deaths']); }, $data['deaths']);
return new ParsedDemo( return new ParsedDemo(
$red, $red,
$blue, $blue,
$chat, $chat,
$players, $players,
$kills $kills
); );
} }
private function getClassName(int $classId): string { private function getClassName(int $classId): string {
return self::CLASSES[$classId] ?? 'Unknown'; return self::CLASSES[$classId] ?? 'Unknown';
} }
/** /**
* Credit to https://github.com/koraktor/steam-condenser-php * Credit to https://github.com/koraktor/steam-condenser-php
* *
* Converts a SteamID as reported by game servers to a 64bit numeric * Converts a SteamID as reported by game servers to a 64bit numeric
* SteamID as used by the Steam Community * SteamID as used by the Steam Community
* *
* @param string $steamId The SteamID string as used on servers, like * @param string $steamId The SteamID string as used on servers, like
* <var>STEAM_0:0:12345</var> * <var>STEAM_0:0:12345</var>
* @return string The converted 64bit numeric SteamID * @return string The converted 64bit numeric SteamID
* @throws \InvalidArgumentException if the SteamID doesn't have the correct * @throws \InvalidArgumentException if the SteamID doesn't have the correct
* format * format
*/ */
public function convertSteamIdToCommunityId($steamId) { public function convertSteamIdToCommunityId($steamId) {
if ($steamId === 'STEAM_ID_LAN' || $steamId === 'BOT') { if ($steamId === 'STEAM_ID_LAN' || $steamId === 'BOT') {
throw new \InvalidArgumentException("Cannot convert SteamID \"$steamId\" to a community ID."); throw new \InvalidArgumentException("Cannot convert SteamID \"$steamId\" to a community ID.");
} }
if (preg_match('/^STEAM_[0-1]:[0-1]:[0-9]+$/', $steamId)) { if (preg_match('/^STEAM_[0-1]:[0-1]:[0-9]+$/', $steamId)) {
$steamParts = explode(':', substr($steamId, 8)); $steamParts = explode(':', substr($steamId, 8));
$steamId = $steamParts[0] + $steamParts[1] * 2 + 1197960265728; $steamId = $steamParts[0] + $steamParts[1] * 2 + 1197960265728;
return '7656' . $steamId; return '7656' . $steamId;
} else if (preg_match('/^\[U:[0-1]:[0-9]+\]$/', $steamId)) { } elseif (preg_match('/^\[U:[0-1]:[0-9]+\]$/', $steamId)) {
$steamParts = explode(':', substr($steamId, 3, -1)); $steamParts = explode(':', substr($steamId, 3, -1));
$steamId = $steamParts[0] + $steamParts[1] + 1197960265727; $steamId = $steamParts[0] + $steamParts[1] + 1197960265727;
return '7656' . $steamId; return '7656' . $steamId;
} else { } else {
throw new \InvalidArgumentException("SteamID \"$steamId\" doesn't have the correct format."); throw new \InvalidArgumentException("SteamID \"$steamId\" doesn't have the correct format.");
} }
} }
} }

View file

@ -11,30 +11,30 @@ use GuzzleHttp\Exception\GuzzleException;
* Doesn't do any post-processing on the result * Doesn't do any post-processing on the result
*/ */
class RawParser { class RawParser {
/** @var string */ /** @var string */
private $parserUrl; private $parserUrl;
public function __construct(string $parserUrl) { public function __construct(string $parserUrl) {
$this->parserUrl = $parserUrl; $this->parserUrl = $parserUrl;
} }
public function parse(string $path): ?array { public function parse(string $path): ?array {
try { try {
$client = new Client(); $client = new Client();
$response = $client->post($this->parserUrl, [ $response = $client->post($this->parserUrl, [
'body' => fopen($path, 'r') 'body' => fopen($path, 'r')
]); ]);
$result = json_decode($response->getBody()->getContents(), true); $result = json_decode($response->getBody()->getContents(), true);
if (is_null($result)) { if (is_null($result)) {
throw new \Exception('Failed to parse demo, unexpected result from parser'); throw new \Exception('Failed to parse demo, unexpected result from parser');
} else { } else {
return $result; return $result;
} }
} catch (GuzzleException $e) { } catch (GuzzleException $e) {
if (strpos($e->getMessage(), 'cURL error 52') !== false) { if (strpos($e->getMessage(), 'cURL error 52') !== false) {
throw new \Exception('Failed to parse demo, can\'t reach demo parser'); throw new \Exception('Failed to parse demo, can\'t reach demo parser');
} }
throw new \Exception('Failed to parse demo, ' . $e->getMessage()); throw new \Exception('Failed to parse demo, ' . $e->getMessage());
} }
} }
} }

View file

@ -4,35 +4,35 @@ use Doctrine\DBAL\Connection;
use RandomLib\Generator; use RandomLib\Generator;
class AuthProvider extends BaseProvider { class AuthProvider extends BaseProvider {
/** /**
* @var Generator * @var Generator
*/ */
private $generator; private $generator;
public function __construct(Connection $db, Generator $generator) { public function __construct(Connection $db, Generator $generator) {
parent::__construct($db); parent::__construct($db);
$this->generator = $generator; $this->generator = $generator;
} }
public function generateToken() { public function generateToken() {
return $this->generator->generateString(32, Generator::CHAR_ALNUM); return $this->generator->generateString(32, Generator::CHAR_ALNUM);
} }
public function setUser($token, \SteamId $steamid, $key) { public function setUser($token, \SteamId $steamid, $key) {
apcu_store($token, [ apcu_store($token, [
'name' => $steamid->getNickname(), 'name' => $steamid->getNickname(),
'steamid' => $steamid->getSteamId64(), 'steamid' => $steamid->getSteamId64(),
'key' => $key 'key' => $key
]); ]);
} }
public function getUser($token) { public function getUser($token) {
$found = true; $found = true;
$result = apcu_fetch($token, $found); $result = apcu_fetch($token, $found);
return $found ? $result : ['name' => null, 'steamid' => null, 'key' => null]; return $found ? $result : ['name' => null, 'steamid' => null, 'key' => null];
} }
public function logout($token) { public function logout($token) {
apcu_delete($token); apcu_delete($token);
} }
} }

View file

@ -7,64 +7,64 @@ use Doctrine\DBAL\Query\QueryBuilder;
use LessQL\Database; use LessQL\Database;
class BaseProvider { class BaseProvider {
/** /**
* @var Connection * @var Connection
*/ */
protected $connection; protected $connection;
/** /**
* @var \LessQL\Database * @var \LessQL\Database
*/ */
protected $db; protected $db;
public function __construct(Connection $connection) { public function __construct(Connection $connection) {
$this->connection = $connection; $this->connection = $connection;
$this->db = new Database($connection->getWrappedConnection()); $this->db = new Database($connection->getWrappedConnection());
$this->dbConfig(); $this->dbConfig();
} }
private function dbConfig() { private function dbConfig() {
$platform = $this->connection->getDatabasePlatform(); $platform = $this->connection->getDatabasePlatform();
if ($platform instanceof MySqlPlatform) { if ($platform instanceof MySqlPlatform) {
$this->db->setIdentifierDelimiter("`"); $this->db->setIdentifierDelimiter("`");
} else { } else {
$this->db->setIdentifierDelimiter('"'); $this->db->setIdentifierDelimiter('"');
} }
$this->db->setRewrite(function ($table) { $this->db->setRewrite(function ($table) {
$rawNames = ['chat']; $rawNames = ['chat'];
$aliases = [ $aliases = [
]; ];
if (isset($aliases[$table])) { if (isset($aliases[$table])) {
return $aliases[$table]; return $aliases[$table];
} else if (array_search($table, $rawNames) === false) { } elseif (array_search($table, $rawNames) === false) {
return $table . 's'; return $table . 's';
} else { } else {
return $table; return $table;
} }
}); });
} }
protected function query($sql, array $params = []) { protected function query($sql, array $params = []) {
$delimiter = $this->db->getIdentifierDelimiter(); $delimiter = $this->db->getIdentifierDelimiter();
$platform = $this->connection->getDatabasePlatform(); $platform = $this->connection->getDatabasePlatform();
$sql = str_replace('`', $delimiter, $sql); $sql = str_replace('`', $delimiter, $sql);
if ($platform instanceof PostgreSqlPlatform) { if ($platform instanceof PostgreSqlPlatform) {
$sql = str_replace('FROM_UNIXTIME(', 'to_timestamp(', $sql); $sql = str_replace('FROM_UNIXTIME(', 'to_timestamp(', $sql);
} }
$query = $this->connection->prepare($sql); $query = $this->connection->prepare($sql);
$query->execute($params); $query->execute($params);
return $query; return $query;
} }
/** /**
* @return QueryBuilder * @return QueryBuilder
*/ */
protected function getQueryBuilder() { protected function getQueryBuilder() {
return new QueryBuilder($this->connection); return new QueryBuilder($this->connection);
} }
} }

View file

@ -3,33 +3,33 @@
use Demostf\API\Demo\ChatMessage; use Demostf\API\Demo\ChatMessage;
class ChatProvider extends BaseProvider { class ChatProvider extends BaseProvider {
public function getChat(int $demoId) { public function getChat(int $demoId) {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->select('text', '"from"', 'time') $query->select('text', '"from"', 'time')
->from('chat') ->from('chat')
->where($query->expr()->eq('demo_id', $query->createNamedParameter($demoId, \PDO::PARAM_INT))); ->where($query->expr()->eq('demo_id', $query->createNamedParameter($demoId, \PDO::PARAM_INT)));
$result = $query->execute(); $result = $query->execute();
return array_map(function (array $row) { return array_map(function (array $row) {
return new ChatMessage( return new ChatMessage(
$row['from'], $row['from'],
(int)$row['time'], (int)$row['time'],
$row['text'] $row['text']
); );
}, $result->fetchAll()); }, $result->fetchAll());
} }
public function storeChatMessage(int $demoId, ChatMessage $message) { public function storeChatMessage(int $demoId, ChatMessage $message) {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->insert('chat') $query->insert('chat')
->values([ ->values([
'demo_id' => $query->createNamedParameter($demoId, \PDO::PARAM_INT), 'demo_id' => $query->createNamedParameter($demoId, \PDO::PARAM_INT),
'text' => $query->createNamedParameter($message->getMessage()), 'text' => $query->createNamedParameter($message->getMessage()),
'"from"' => $query->createNamedParameter($message->getUser()), '"from"' => $query->createNamedParameter($message->getUser()),
'time' => $query->createNamedParameter($message->getTime(), \PDO::PARAM_INT), 'time' => $query->createNamedParameter($message->getTime(), \PDO::PARAM_INT),
'created_at' => 'now()', 'created_at' => 'now()',
'updated_at' => 'now()', 'updated_at' => 'now()',
]); ]);
$query->execute(); $query->execute();
} }
} }

View file

@ -4,74 +4,74 @@ use Demostf\API\Demo\Demo;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
class DemoListProvider extends BaseProvider { class DemoListProvider extends BaseProvider {
public function listUploads(string $steamid, int $page, array $where = []) { public function listUploads(string $steamid, int $page, array $where = []) {
$user = $this->db->user()->where('steamid', $steamid); $user = $this->db->user()->where('steamid', $steamid);
$where['uploader'] = $user->fetch()->id; $where['uploader'] = $user->fetch()->id;
return $this->listDemos($page, $where); return $this->listDemos($page, $where);
} }
public function listProfile(int $page, array $where = []) { public function listProfile(int $page, array $where = []) {
$users = $this->db->user()->where('steamid', $where['players']); $users = $this->db->user()->where('steamid', $where['players']);
unset($where['players']); unset($where['players']);
$userIds = []; $userIds = [];
foreach ($users as $user) { foreach ($users as $user) {
$userIds[] = $user['id']; $userIds[] = $user['id'];
} }
$in = implode(', ', array_fill(0, count($userIds), '?')); $in = implode(', ', array_fill(0, count($userIds), '?'));
$sql = 'SELECT demos.id FROM demos INNER JOIN players ON players.demo_id = demos.id $sql = 'SELECT demos.id FROM demos INNER JOIN players ON players.demo_id = demos.id
WHERE players.user_id IN (' . $in . ') GROUP BY demos.id HAVING COUNT(user_id) = ? ORDER BY demos.id DESC LIMIT 50 OFFSET ' . ((int)$page - 1) * 50; WHERE players.user_id IN (' . $in . ') GROUP BY demos.id HAVING COUNT(user_id) = ? ORDER BY demos.id DESC LIMIT 50 OFFSET ' . ((int)$page - 1) * 50;
$params = $userIds; $params = $userIds;
$params[] = count($userIds); $params[] = count($userIds);
$result = $this->query($sql, $params); $result = $this->query($sql, $params);
$demoIds = $result->fetchAll(\PDO::FETCH_COLUMN); $demoIds = $result->fetchAll(\PDO::FETCH_COLUMN);
$demos = $this->db->demo()->where('id', $demoIds) $demos = $this->db->demo()->where('id', $demoIds)
->where($where) ->where($where)
->orderBy('id', 'DESC'); ->orderBy('id', 'DESC');
return $this->formatList($demos->fetchAll()); return $this->formatList($demos->fetchAll());
} }
/** /**
* @param int $page * @param int $page
* @param array $where * @param array $where
* @param string $order * @param string $order
* @return Demo[] * @return Demo[]
*/ */
public function listDemos(int $page, array $where = [], $order = 'DESC') { public function listDemos(int $page, array $where = [], $order = 'DESC') {
if (isset($where['players']) and is_array($where['players']) and count($where['players']) > 0) { if (isset($where['players']) and is_array($where['players']) and count($where['players']) > 0) {
return $this->listProfile($page, $where); return $this->listProfile($page, $where);
} }
$offset = ($page - 1) * 50; $offset = ($page - 1) * 50;
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->select('d.*') $query->select('d.*')
->from('demos', 'd') ->from('demos', 'd')
->leftJoin('d', 'upload_blacklist', 'b', $query->expr()->eq('uploader_id', 'uploader')) ->leftJoin('d', 'upload_blacklist', 'b', $query->expr()->eq('uploader_id', 'uploader'))
->where($query->expr()->isNull('b.id')); ->where($query->expr()->isNull('b.id'));
if (isset($where['map'])) { if (isset($where['map'])) {
$query->where($query->expr()->eq('map', $query->createNamedParameter($where['map']))); $query->where($query->expr()->eq('map', $query->createNamedParameter($where['map'])));
} }
if (isset($where['playerCount'])) { if (isset($where['playerCount'])) {
$query->where($query->expr()->in('"playerCount"', $query->createNamedParameter($where['playerCount'], Connection::PARAM_INT_ARRAY))); $query->where($query->expr()->in('"playerCount"', $query->createNamedParameter($where['playerCount'], Connection::PARAM_INT_ARRAY)));
} }
if (isset($where['uploader'])) { if (isset($where['uploader'])) {
$query->where($query->expr()->in('uploader', $query->createNamedParameter($where['uploader'], \PDO::PARAM_INT))); $query->where($query->expr()->in('uploader', $query->createNamedParameter($where['uploader'], \PDO::PARAM_INT)));
} }
$query->orderBy('d.id', $order) $query->orderBy('d.id', $order)
->setMaxResults(50) ->setMaxResults(50)
->setFirstResult($offset); ->setFirstResult($offset);
$demos = $query->execute()->fetchAll(\PDO::FETCH_ASSOC); $demos = $query->execute()->fetchAll(\PDO::FETCH_ASSOC);
return $this->formatList($demos); return $this->formatList($demos);
} }
protected function formatList(array $rows) { protected function formatList(array $rows) {
return array_map(function ($row) { return array_map(function ($row) {
return Demo::fromRow($row); return Demo::fromRow($row);
}, $rows); }, $rows);
} }
} }

View file

@ -7,13 +7,13 @@ use Demostf\API\Data\User;
use Demostf\API\Demo\Demo; use Demostf\API\Demo\Demo;
class DemoProvider extends BaseProvider { class DemoProvider extends BaseProvider {
const VERSION = 4; const VERSION = 4;
public function get(int $id, bool $fetchDetails = true): ?Demo { public function get(int $id, bool $fetchDetails = true): ?Demo {
$demo = $this->db->demo()->where('id', $id); $demo = $this->db->demo()->where('id', $id);
// sql magic // sql magic
$sql = 'WITH demokills AS (SELECT attacker_id, assister_id, victim_id FROM kills WHERE demo_id = ?) $sql = 'WITH demokills AS (SELECT attacker_id, assister_id, victim_id FROM kills WHERE demo_id = ?)
SELECT players.id, user_id, players.name, team, class, users.steamid, users.avatar, SELECT players.id, user_id, players.name, team, class, users.steamid, users.avatar,
(SELECT COUNT(*) FROM demokills WHERE attacker_id=players.user_id) AS kills, (SELECT COUNT(*) FROM demokills WHERE attacker_id=players.user_id) AS kills,
(SELECT COUNT(*) FROM demokills WHERE assister_id=players.user_id) AS assists, (SELECT COUNT(*) FROM demokills WHERE assister_id=players.user_id) AS assists,
@ -22,73 +22,73 @@ class DemoProvider extends BaseProvider {
INNER JOIN users ON players.user_id = users.id INNER JOIN users ON players.user_id = users.id
WHERE demo_id = ?'; WHERE demo_id = ?';
$demoData = $demo->fetch(); $demoData = $demo->fetch();
if (!$demoData) { if (!$demoData) {
return null; return null;
} }
$formattedDemo = Demo::fromRow($demoData); $formattedDemo = Demo::fromRow($demoData);
if ($fetchDetails) { if ($fetchDetails) {
$uploader = $demo->user()->via('uploader')->fetch(); $uploader = $demo->user()->via('uploader')->fetch();
$playerQuery = $this->query($sql, [$formattedDemo->getId(), $formattedDemo->getId()]); $playerQuery = $this->query($sql, [$formattedDemo->getId(), $formattedDemo->getId()]);
$players = $playerQuery->fetchAll(\PDO::FETCH_ASSOC); $players = $playerQuery->fetchAll(\PDO::FETCH_ASSOC);
$formattedDemo->setUploaderUser(User::fromRow([ $formattedDemo->setUploaderUser(User::fromRow([
'id' => $uploader['id'], 'id' => $uploader['id'],
'steamid' => $uploader['steamid'], 'steamid' => $uploader['steamid'],
'name' => $uploader['name'], 'name' => $uploader['name'],
'avatar' => $uploader['avatar'] 'avatar' => $uploader['avatar']
])); ]));
$formattedDemo->setPlayers(array_map(function ($player) { $formattedDemo->setPlayers(array_map(function ($player) {
return DemoPlayer::fromRow($player); return DemoPlayer::fromRow($player);
}, $players)); }, $players));
} }
return $formattedDemo; return $formattedDemo;
} }
public function demoIdByHash($hash): int { public function demoIdByHash($hash): int {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->select('id') $query->select('id')
->from('demos') ->from('demos')
->where($query->expr()->eq('hash', $query->createNamedParameter($hash))); ->where($query->expr()->eq('hash', $query->createNamedParameter($hash)));
return (int)$query->execute()->fetchColumn(); return (int)$query->execute()->fetchColumn();
} }
public function storeDemo(Demo $demo, string $backend, string $path): int { public function storeDemo(Demo $demo, string $backend, string $path): int {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->insert('demos') $query->insert('demos')
->values([ ->values([
'name' => $query->createNamedParameter($demo->getName()), 'name' => $query->createNamedParameter($demo->getName()),
'url' => $query->createNamedParameter($demo->getUrl()), 'url' => $query->createNamedParameter($demo->getUrl()),
'map' => $query->createNamedParameter($demo->getMap()), 'map' => $query->createNamedParameter($demo->getMap()),
'red' => $query->createNamedParameter($demo->getRed()), 'red' => $query->createNamedParameter($demo->getRed()),
'blu' => $query->createNamedParameter($demo->getBlue()), 'blu' => $query->createNamedParameter($demo->getBlue()),
'uploader' => $query->createNamedParameter($demo->getUploader(), \PDO::PARAM_INT), 'uploader' => $query->createNamedParameter($demo->getUploader(), \PDO::PARAM_INT),
'duration' => $query->createNamedParameter((int)$demo->getDuration(), \PDO::PARAM_INT), 'duration' => $query->createNamedParameter((int)$demo->getDuration(), \PDO::PARAM_INT),
'created_at' => $query->createNamedParameter($demo->getTime()->format(\DATE_ATOM)), 'created_at' => $query->createNamedParameter($demo->getTime()->format(\DATE_ATOM)),
'updated_at' => 'now()', 'updated_at' => 'now()',
'backend' => $query->createNamedParameter($backend), 'backend' => $query->createNamedParameter($backend),
'path' => $query->createNamedParameter($path), 'path' => $query->createNamedParameter($path),
'"scoreBlue"' => $query->createNamedParameter($demo->getBlueScore(), \PDO::PARAM_INT), '"scoreBlue"' => $query->createNamedParameter($demo->getBlueScore(), \PDO::PARAM_INT),
'"scoreRed"' => $query->createNamedParameter($demo->getRedScore(), \PDO::PARAM_INT), '"scoreRed"' => $query->createNamedParameter($demo->getRedScore(), \PDO::PARAM_INT),
'version' => $query->createNamedParameter(self::VERSION, \PDO::PARAM_INT), 'version' => $query->createNamedParameter(self::VERSION, \PDO::PARAM_INT),
'server' => $query->createNamedParameter($demo->getServer()), 'server' => $query->createNamedParameter($demo->getServer()),
'nick' => $query->createNamedParameter($demo->getNick()), 'nick' => $query->createNamedParameter($demo->getNick()),
'"playerCount"' => $query->createNamedParameter($demo->getPlayerCount(), \PDO::PARAM_INT), '"playerCount"' => $query->createNamedParameter($demo->getPlayerCount(), \PDO::PARAM_INT),
'hash' => $query->createNamedParameter($demo->getHash()) 'hash' => $query->createNamedParameter($demo->getHash())
]) ])
->execute(); ->execute();
return (int)$this->connection->lastInsertId(); return (int)$this->connection->lastInsertId();
} }
public function setDemoUrl(int $id, string $backend, string $url, string $path) { public function setDemoUrl(int $id, string $backend, string $url, string $path) {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->update('demos') $query->update('demos')
->set('backend', $query->createNamedParameter($backend)) ->set('backend', $query->createNamedParameter($backend))
->set('url', $query->createNamedParameter($url)) ->set('url', $query->createNamedParameter($url))
->set('path', $query->createNamedParameter($path)) ->set('path', $query->createNamedParameter($path))
->where($query->expr()->eq('id', $query->createNamedParameter($id, \PDO::PARAM_INT))) ->where($query->expr()->eq('id', $query->createNamedParameter($id, \PDO::PARAM_INT)))
->execute(); ->execute();
} }
} }

View file

@ -1,19 +1,19 @@
<?php namespace Demostf\API\Providers; <?php namespace Demostf\API\Providers;
class InfoProvider extends BaseProvider { class InfoProvider extends BaseProvider {
public function listMaps() { public function listMaps() {
$sql = 'SELECT DISTINCT(map), COUNT(map) AS count from demos GROUP BY map ORDER BY count DESC'; $sql = 'SELECT DISTINCT(map), COUNT(map) AS count from demos GROUP BY map ORDER BY count DESC';
$result = $this->query($sql); $result = $this->query($sql);
return $result->fetchAll(\PDO::FETCH_COLUMN); return $result->fetchAll(\PDO::FETCH_COLUMN);
} }
public function getStats() { public function getStats() {
$demoCount = $this->db->demo()->count(); $demoCount = $this->db->demo()->count();
$playerCount = $this->db->user()->count(); $playerCount = $this->db->user()->count();
return [ return [
'demos' => $demoCount, 'demos' => $demoCount,
'players' => $playerCount 'players' => $playerCount
]; ];
} }
} }

View file

@ -5,20 +5,20 @@ namespace Demostf\API\Providers;
use Demostf\API\Data\Kill; use Demostf\API\Data\Kill;
class KillProvider extends BaseProvider { class KillProvider extends BaseProvider {
public function store(Kill $kill): int { public function store(Kill $kill): int {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->insert('kills') $query->insert('kills')
->values([ ->values([
'demo_id' => $query->createNamedParameter($kill->getDemoId()), 'demo_id' => $query->createNamedParameter($kill->getDemoId()),
'attacker_id' => $query->createNamedParameter($kill->getAttackerId()), 'attacker_id' => $query->createNamedParameter($kill->getAttackerId()),
'assister_id' => $query->createNamedParameter($kill->getAssisterId()), 'assister_id' => $query->createNamedParameter($kill->getAssisterId()),
'victim_id' => $query->createNamedParameter($kill->getVictimId()), 'victim_id' => $query->createNamedParameter($kill->getVictimId()),
'weapon' => $query->createNamedParameter($kill->getWeapon()), 'weapon' => $query->createNamedParameter($kill->getWeapon()),
'created_at' => 'now()', 'created_at' => 'now()',
'updated_at' => 'now()' 'updated_at' => 'now()'
]); ]);
$query->execute(); $query->execute();
return (int)$this->connection->lastInsertId(); return (int)$this->connection->lastInsertId();
} }
} }

View file

@ -5,21 +5,21 @@ namespace Demostf\API\Providers;
use Demostf\API\Data\Player; use Demostf\API\Data\Player;
class PlayerProvider extends BaseProvider { class PlayerProvider extends BaseProvider {
public function store(Player $player): int { public function store(Player $player): int {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->insert('players') $query->insert('players')
->values([ ->values([
'demo_id' => $query->createNamedParameter($player->getDemoId()), 'demo_id' => $query->createNamedParameter($player->getDemoId()),
'demo_user_id' => $query->createNamedParameter($player->getDemoUserId()), 'demo_user_id' => $query->createNamedParameter($player->getDemoUserId()),
'user_id' => $query->createNamedParameter($player->getUserId()), 'user_id' => $query->createNamedParameter($player->getUserId()),
'name' => $query->createNamedParameter($player->getName()), 'name' => $query->createNamedParameter($player->getName()),
'team' => $query->createNamedParameter($player->getTeam()), 'team' => $query->createNamedParameter($player->getTeam()),
'class' => $query->createNamedParameter($player->getClass()), 'class' => $query->createNamedParameter($player->getClass()),
'created_at' => 'now()', 'created_at' => 'now()',
'updated_at' => 'now()' 'updated_at' => 'now()'
]); ]);
$query->execute(); $query->execute();
return (int)$this->connection->lastInsertId(); return (int)$this->connection->lastInsertId();
} }
} }

View file

@ -13,97 +13,98 @@ use Doctrine\DBAL\Connection;
use RandomLib\Generator; use RandomLib\Generator;
class UploadProvider extends BaseProvider { class UploadProvider extends BaseProvider {
/** @var Generator */ /** @var Generator */
private $generator; private $generator;
/** @var HeaderParser */ /** @var HeaderParser */
private $headerParser; private $headerParser;
/** @var Parser */ /** @var Parser */
private $parser; private $parser;
/** @var DemoStore */ /** @var DemoStore */
private $store; private $store;
/** @var UserProvider */ /** @var UserProvider */
private $userProvider; private $userProvider;
/** @var DemoProvider */ /** @var DemoProvider */
private $demoProvider; private $demoProvider;
/** @var DemoSaver */ /** @var DemoSaver */
private $demoSaver; private $demoSaver;
private $baseUrl; private $baseUrl;
public function __construct(Connection $db, public function __construct(
string $baseUrl, Connection $db,
HeaderParser $headerParser, string $baseUrl,
Parser $parser, HeaderParser $headerParser,
DemoStore $store, Parser $parser,
UserProvider $userProvider, DemoStore $store,
DemoProvider $demoProvider, UserProvider $userProvider,
DemoSaver $demoSaver DemoProvider $demoProvider,
) { DemoSaver $demoSaver
parent::__construct($db); ) {
$this->baseUrl = $baseUrl; parent::__construct($db);
$this->headerParser = $headerParser; $this->baseUrl = $baseUrl;
$this->parser = $parser; $this->headerParser = $headerParser;
$this->store = $store; $this->parser = $parser;
$this->userProvider = $userProvider; $this->store = $store;
$this->demoProvider = $demoProvider; $this->userProvider = $userProvider;
$this->demoSaver = $demoSaver; $this->demoProvider = $demoProvider;
} $this->demoSaver = $demoSaver;
}
public function upload(string $key, string $red, string $blu, string $name, string $demoFile): string { public function upload(string $key, string $red, string $blu, string $name, string $demoFile): string {
$user = $this->userProvider->byKey($key); $user = $this->userProvider->byKey($key);
if (!$user) { if (!$user) {
return 'Invalid key'; return 'Invalid key';
} }
$hash = hash_file('md5', $demoFile); $hash = hash_file('md5', $demoFile);
$existingDemo = $this->demoProvider->demoIdByHash($hash); $existingDemo = $this->demoProvider->demoIdByHash($hash);
if ($existingDemo) { if ($existingDemo) {
return 'STV available at: ' . $this->baseUrl . '/' . $existingDemo; return 'STV available at: ' . $this->baseUrl . '/' . $existingDemo;
} }
$header = $this->headerParser->parseHeader($demoFile); $header = $this->headerParser->parseHeader($demoFile);
$error = $this->validateHeader(filesize($demoFile), $header); $error = $this->validateHeader(filesize($demoFile), $header);
if ($error) { if ($error) {
return $error; return $error;
} }
$parsed = $this->parser->analyse($demoFile); $parsed = $this->parser->analyse($demoFile);
$error = $this->validateParsed($header, $parsed); $error = $this->validateParsed($header, $parsed);
if ($error) { if ($error) {
return $error; return $error;
} }
$storedDemo = $this->store->store($demoFile, $hash . '_' . $name); $storedDemo = $this->store->store($demoFile, $hash . '_' . $name);
$upload = new Upload($name, $red, $blu, $user->getId(), $hash); $upload = new Upload($name, $red, $blu, $user->getId(), $hash);
$id = $this->demoSaver->saveDemo($parsed, $header, $storedDemo, $upload); $id = $this->demoSaver->saveDemo($parsed, $header, $storedDemo, $upload);
return 'STV available at: ' . $this->baseUrl . '/' . $id; return 'STV available at: ' . $this->baseUrl . '/' . $id;
} }
public function validateHeader(int $size, Header $header) { public function validateHeader(int $size, Header $header) {
if ($size < 1024) { if ($size < 1024) {
return 'Demos needs to be at least 1KB is size'; return 'Demos needs to be at least 1KB is size';
} }
if ($size > 100 * 1024 * 1024) { if ($size > 100 * 1024 * 1024) {
return 'Demos cant be more than 100MB in size'; return 'Demos cant be more than 100MB in size';
} }
if ($header->getDuration() > (60 * 60)) { if ($header->getDuration() > (60 * 60)) {
return 'Demos cant be longer than one hour'; return 'Demos cant be longer than one hour';
} }
return null; return null;
} }
public function validateParsed(Header $header, ParsedDemo $parsedDemo) { public function validateParsed(Header $header, ParsedDemo $parsedDemo) {
$rounds = $parsedDemo->getRedScore() + $parsedDemo->getBlueScore(); $rounds = $parsedDemo->getRedScore() + $parsedDemo->getBlueScore();
if ($rounds === 0 && $header->getDuration() < (5 * 60)) { if ($rounds === 0 && $header->getDuration() < (5 * 60)) {
return 'Demos must be at least 5 minutes long'; return 'Demos must be at least 5 minutes long';
} }
return null; return null;
} }
} }

View file

@ -7,131 +7,131 @@ use Doctrine\DBAL\Connection;
use RandomLib\Generator; use RandomLib\Generator;
class UserProvider extends BaseProvider { class UserProvider extends BaseProvider {
/** /**
* @var Generator * @var Generator
*/ */
private $generator; private $generator;
public function __construct(Connection $db, Generator $generator) { public function __construct(Connection $db, Generator $generator) {
parent::__construct($db); parent::__construct($db);
$this->generator = $generator; $this->generator = $generator;
} }
public function store(\SteamId $steamId): string { public function store(\SteamId $steamId): string {
$token = $this->generator->generateString(64, Generator::EASY_TO_READ); $token = $this->generator->generateString(64, Generator::EASY_TO_READ);
$user = $this->get($steamId->getSteamId64()); $user = $this->get($steamId->getSteamId64());
if ($user) { if ($user) {
return $user->getToken(); return $user->getToken();
} }
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->insert('users') $query->insert('users')
->values([ ->values([
'steamid' => $query->createNamedParameter($steamId->getSteamId64()), 'steamid' => $query->createNamedParameter($steamId->getSteamId64()),
'name' => $query->createNamedParameter($steamId->getNickname()), 'name' => $query->createNamedParameter($steamId->getNickname()),
'avatar' => $query->createNamedParameter($steamId->getMediumAvatarUrl()), 'avatar' => $query->createNamedParameter($steamId->getMediumAvatarUrl()),
'token' => $query->createNamedParameter($token) 'token' => $query->createNamedParameter($token)
])->add('orderBy', 'ON CONFLICT DO NOTHING')// hack to append arbitrary string to sql ])->add('orderBy', 'ON CONFLICT DO NOTHING')// hack to append arbitrary string to sql
->execute(); ->execute();
$user = $this->get($steamId->getSteamId64()); $user = $this->get($steamId->getSteamId64());
return $user ? $user->getToken() : $token; return $user ? $user->getToken() : $token;
} }
public function get(string $steamid): ?User { public function get(string $steamid): ?User {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->select(['id', 'steamid', 'name', 'avatar', 'token']) $query->select(['id', 'steamid', 'name', 'avatar', 'token'])
->from('users') ->from('users')
->where($query->expr()->eq('steamid', $query->createNamedParameter($steamid))); ->where($query->expr()->eq('steamid', $query->createNamedParameter($steamid)));
$row = $query->execute()->fetch(); $row = $query->execute()->fetch();
return $row ? User::fromRow($row) : null; return $row ? User::fromRow($row) : null;
} }
private function searchBySteamId(string $steamId): ?array { private function searchBySteamId(string $steamId): ?array {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->select('u.id', 'p.name', 'count(demo_id) as count', 'steamid') $query->select('u.id', 'p.name', 'count(demo_id) as count', 'steamid')
->from('players', 'p') ->from('players', 'p')
->innerJoin('p', 'users', 'u', $query->expr()->eq('p.user_id', 'u.id')) ->innerJoin('p', 'users', 'u', $query->expr()->eq('p.user_id', 'u.id'))
->where($query->expr()->eq('steamid', $query->createNamedParameter($steamId))) ->where($query->expr()->eq('steamid', $query->createNamedParameter($steamId)))
->groupBy('p.name, u.id') ->groupBy('p.name, u.id')
->orderBy('count(demo_id)', 'DESC') ->orderBy('count(demo_id)', 'DESC')
->setMaxResults(1); ->setMaxResults(1);
$result = $query->execute()->fetch(); $result = $query->execute()->fetch();
if (is_array($result)) { if (is_array($result)) {
return $result; return $result;
} else { } else {
return null; return null;
} }
} }
public function search($query): array { public function search($query): array {
$bySteamId = $this->searchBySteamId($query); $bySteamId = $this->searchBySteamId($query);
if ($bySteamId) { if ($bySteamId) {
return [ return [
$bySteamId $bySteamId
]; ];
} }
$sql = 'SELECT user_id, players.name, count(demo_id) AS count, steamid, $sql = 'SELECT user_id, players.name, count(demo_id) AS count, steamid,
1-(players.name <-> ?) AS sim FROM players 1-(players.name <-> ?) AS sim FROM players
INNER JOIN users ON users.id = players.user_id INNER JOIN users ON users.id = players.user_id
WHERE players.name % ? OR players.name ~* ? WHERE players.name % ? OR players.name ~* ?
GROUP BY players.name, user_id, steamid GROUP BY players.name, user_id, steamid
ORDER BY count DESC ORDER BY count DESC
LIMIT 100'; LIMIT 100';
$result = $this->query($sql, [$query, $query, $query]); $result = $this->query($sql, [$query, $query, $query]);
$players = $result->fetchAll(\PDO::FETCH_ASSOC); $players = $result->fetchAll(\PDO::FETCH_ASSOC);
usort($players, function ($b, $a) use ($query) { usort($players, function ($b, $a) use ($query) {
if ($a['steamid'] === $query && $a['steamid'] !== $query) { if ($a['steamid'] === $query && $a['steamid'] !== $query) {
return -1; return -1;
} }
$countWeight = 1; $countWeight = 1;
$simWeight = 5; $simWeight = 5;
$diff = ($a['sim'] * $simWeight + $a['count'] * $countWeight) - ($b['sim'] * $simWeight + $b['count'] * $countWeight); $diff = ($a['sim'] * $simWeight + $a['count'] * $countWeight) - ($b['sim'] * $simWeight + $b['count'] * $countWeight);
if ($diff === 0) { if ($diff === 0) {
return 0; return 0;
} else { } else {
return ($diff < 0) ? -1 : 1; return ($diff < 0) ? -1 : 1;
} }
}); });
$result = []; $result = [];
foreach ($players as $player) { foreach ($players as $player) {
$id = $player['user_id']; $id = $player['user_id'];
if (!isset($result[$id])) { if (!isset($result[$id])) {
$result[$id] = [ $result[$id] = [
'id' => $id, 'id' => $id,
'name' => $player['name'], 'name' => $player['name'],
'steamid' => $player['steamid'] 'steamid' => $player['steamid']
]; ];
} }
} }
return array_values($result); return array_values($result);
} }
public function byKey($key): ?User { public function byKey($key): ?User {
$query = $this->getQueryBuilder(); $query = $this->getQueryBuilder();
$query->select(['id', 'steamid', 'name', 'avatar', 'token']) $query->select(['id', 'steamid', 'name', 'avatar', 'token'])
->from('users') ->from('users')
->where($query->expr()->eq('token', $query->createNamedParameter($key))); ->where($query->expr()->eq('token', $query->createNamedParameter($key)));
$row = $query->execute()->fetch(); $row = $query->execute()->fetch();
return $row ? User::fromRow($row) : null; return $row ? User::fromRow($row) : null;
} }
public function getUserId(string $steamId) { public function getUserId(string $steamId) {
$existing = $this->get($steamId); $existing = $this->get($steamId);
if ($existing) { if ($existing) {
return $existing->getId(); return $existing->getId();
} }
$this->store(new \SteamId($steamId)); $this->store(new \SteamId($steamId));
return $this->get($steamId)->getId(); return $this->get($steamId)->getId();
} }
} }

View file

@ -8,32 +8,32 @@ use Flight;
$container = require __DIR__ . '/init.php'; $container = require __DIR__ . '/init.php';
$demoController = new Controllers\DemoController( $demoController = new Controllers\DemoController(
$container->getDemoProvider(), $container->getDemoProvider(),
$container->getChatProvider(), $container->getChatProvider(),
$container->getDemoListProvider(), $container->getDemoListProvider(),
$container->getEditKey() $container->getEditKey()
); );
$authController = new Controllers\AuthController( $authController = new Controllers\AuthController(
$container->getUserProvider(), $container->getUserProvider(),
$container->getAuthProvider(), $container->getAuthProvider(),
$container->getBaseUrl(), $container->getBaseUrl(),
$container->getApiRoot() $container->getApiRoot()
); );
$userController = new Controllers\UserController($container->getUserProvider()); $userController = new Controllers\UserController($container->getUserProvider());
$infoController = new Controllers\InfoController($container->getInfoProvider()); $infoController = new Controllers\InfoController($container->getInfoProvider());
Flight::route('/*', function () { Flight::route('/*', function () {
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Origin: *');
return true; return true;
}); });
Flight::route('/auth/*', function () { Flight::route('/auth/*', function () {
session_start(); session_start();
return true; return true;
}); });
Flight::route('/', function () { Flight::route('/', function () {
echo 'hello world!'; echo 'hello world!';
}); });
Flight::route('/maps', [$infoController, 'listMaps']); Flight::route('/maps', [$infoController, 'listMaps']);

View file

@ -5,19 +5,19 @@ use Demostf\API\Container;
$autoloader = require __DIR__ . '/../vendor/autoload.php'; $autoloader = require __DIR__ . '/../vendor/autoload.php';
if (!getenv('DB_TYPE')) { if (!getenv('DB_TYPE')) {
Dotenv::load(__DIR__ . '/../'); Dotenv::load(__DIR__ . '/../');
} }
$connectionParams = array( $connectionParams = [
'dbname' => getenv('DB_DATABASE'), 'dbname' => getenv('DB_DATABASE'),
'user' => getenv('DB_USERNAME'), 'user' => getenv('DB_USERNAME'),
'password' => getenv('DB_PASSWORD'), 'password' => getenv('DB_PASSWORD'),
'host' => getenv('DB_HOST'), 'host' => getenv('DB_HOST'),
'port' => getenv('DB_PORT'), 'port' => getenv('DB_PORT'),
'driver' => getenv('DB_TYPE'), 'driver' => getenv('DB_TYPE'),
); ];
if ($connectionParams['driver'] === 'pgsql') { if ($connectionParams['driver'] === 'pgsql') {
$connectionParams['driver'] = 'pdo_pgsql'; $connectionParams['driver'] = 'pdo_pgsql';
} }
$db = \Doctrine\DBAL\DriverManager::getConnection($connectionParams); $db = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
$host = getenv('BASE_HOST') ?: ''; $host = getenv('BASE_HOST') ?: '';
@ -31,14 +31,14 @@ $factory = new \RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator(); $generator = $factory->getMediumStrengthGenerator();
$container = new Container( $container = new Container(
$db, $db,
$generator, $generator,
'https://' . $host, 'https://' . $host,
$parserUrl, $parserUrl,
$storeRoot, $storeRoot,
$storeHost, $storeHost,
$appRoot, $appRoot,
$editKey $editKey
); );
return $container; return $container;

View file

@ -11,8 +11,8 @@ $container = require __DIR__ . '/init.php';
$uploadController = new Controllers\UploadController($container->getUploadProvider()); $uploadController = new Controllers\UploadController($container->getUploadProvider());
Flight::route('/*', function () { Flight::route('/*', function () {
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Origin: *');
return true; return true;
}); });
Flight::route('/upload', [$uploadController, 'upload']); Flight::route('/upload', [$uploadController, 'upload']);

View file

@ -6,22 +6,22 @@ use Demostf\API\Data\DemoPlayer;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class DemoPlayerTest extends TestCase { class DemoPlayerTest extends TestCase {
public function testParseSerialize() { public function testParseSerialize() {
$data = [ $data = [
'id' => 1, 'id' => 1,
'user_id' => 2, 'user_id' => 2,
'name' => 'foo', 'name' => 'foo',
'team' => 'red', 'team' => 'red',
'class' => 'sniper', 'class' => 'sniper',
'steamid' => 'asd', 'steamid' => 'asd',
'avatar' => 'asd.png', 'avatar' => 'asd.png',
'kills' => 5, 'kills' => 5,
'assists' => 3, 'assists' => 3,
'deaths' => 7 'deaths' => 7
]; ];
$demoPlayer = DemoPlayer::fromRow($data); $demoPlayer = DemoPlayer::fromRow($data);
$this->assertEquals($data, $demoPlayer->jsonSerialize()); $this->assertEquals($data, $demoPlayer->jsonSerialize());
} }
} }

View file

@ -18,95 +18,96 @@ use Demostf\API\Providers\UserProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class DemoSaverTest extends TestCase { class DemoSaverTest extends TestCase {
public function testSave() { public function testSave() {
$steamId1 = $this->getSteamId('1234567', 'user1');
$steamId2 = $this->getSteamId('2345678', 'user2');
$steamId1 = $this->getSteamId('1234567', 'user1'); $userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator());
$steamId2 = $this->getSteamId('2345678', 'user2'); $demoProvider = new DemoProvider($this->getDatabaseConnection());
$chatProvider = new ChatProvider($this->getDatabaseConnection());
$userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator()); $userProvider->store($steamId1);
$demoProvider = new DemoProvider($this->getDatabaseConnection()); $userProvider->store($steamId2);
$chatProvider = new ChatProvider($this->getDatabaseConnection());
$userProvider->store($steamId1); $upload = new Upload(
$userProvider->store($steamId2); 'foodemo',
'DER',
'ULB',
$userProvider->getUserId('2345678'),
'securehash'
);
$upload = new Upload( $header = new Header(
'foodemo', 'HL2DEMO',
'DER', 12,
'ULB', 13,
$userProvider->getUserId('2345678'), 'My Server',
'securehash' 'STV',
); 'pl_badwater',
'tf',
60,
60 * 60,
2,
1
);
$header = new Header( $parsed = new ParsedDemo(
'HL2DEMO', 2,
12, 3,
13, [
'My Server', new ChatMessage('user1', 12, 'msg1'),
'STV', new ChatMessage('user2', 13, 'msg2')
'pl_badwater', ],
'tf', [
60, new ParsedPlayer('user1', 1, '1234567', 'red', 'scout'),
60 * 60, new ParsedPlayer('user2', 2, '2345678', 'blue', 'soldier'),
2, ],
1 [
); new ParsedKill(1, 0, 2, 'pan'),
new ParsedKill(1, 2, 2, 'pan'),
new ParsedKill(2, 0, 1, 'pan'),
]
);
$parsed = new ParsedDemo(2, 3, $saver = new DemoSaver(
[ new KillProvider($this->getDatabaseConnection()),
new ChatMessage('user1', 12, 'msg1'), new PlayerProvider($this->getDatabaseConnection()),
new ChatMessage('user2', 13, 'msg2') $chatProvider,
], $userProvider,
[ $demoProvider
new ParsedPlayer('user1', 1, '1234567', 'red', 'scout'), );
new ParsedPlayer('user2', 2, '2345678', 'blue', 'soldier'),
],
[
new ParsedKill(1, 0, 2, 'pan'),
new ParsedKill(1, 2, 2, 'pan'),
new ParsedKill(2, 0, 1, 'pan'),
]
);
$saver = new DemoSaver( $storedDemo = new StoredDemo('http://example.com/foo', 'foo', 'example');
new KillProvider($this->getDatabaseConnection()),
new PlayerProvider($this->getDatabaseConnection()),
$chatProvider,
$userProvider,
$demoProvider
);
$storedDemo = new StoredDemo('http://example.com/foo', 'foo', 'example'); $demoId = $saver->saveDemo($parsed, $header, $storedDemo, $upload);
$demoId = $saver->saveDemo($parsed, $header, $storedDemo, $upload); $retrievedDemo = $demoProvider->get($demoId, true);
$retrievedDemo = $demoProvider->get($demoId, true); $this->assertEquals(2, $retrievedDemo->getPlayerCount());
$this->assertEquals(2, $retrievedDemo->getRedScore());
$this->assertEquals(3, $retrievedDemo->getBlueScore());
$this->assertEquals('DER', $retrievedDemo->getRed());
$this->assertEquals('ULB', $retrievedDemo->getBlue());
$this->assertEquals(2, $retrievedDemo->getPlayerCount()); $this->assertEquals('user2', $retrievedDemo->getUploaderUser()->getName());
$this->assertEquals(2, $retrievedDemo->getRedScore());
$this->assertEquals(3, $retrievedDemo->getBlueScore());
$this->assertEquals('DER', $retrievedDemo->getRed());
$this->assertEquals('ULB', $retrievedDemo->getBlue());
$this->assertEquals('user2', $retrievedDemo->getUploaderUser()->getName()); $this->assertEquals('user2', $retrievedDemo->getPlayers()[0]->getName());
$this->assertEquals(1, $retrievedDemo->getPlayers()[0]->getKills());
$this->assertEquals(1, $retrievedDemo->getPlayers()[0]->getAssists());
$this->assertEquals(2, $retrievedDemo->getPlayers()[0]->getDeaths());
$this->assertEquals('blue', $retrievedDemo->getPlayers()[0]->getTeam());
$this->assertEquals('soldier', $retrievedDemo->getPlayers()[0]->getClass());
$this->assertEquals('user2', $retrievedDemo->getPlayers()[0]->getName()); $this->assertEquals('user1', $retrievedDemo->getPlayers()[1]->getName());
$this->assertEquals(1, $retrievedDemo->getPlayers()[0]->getKills()); $this->assertEquals(2, $retrievedDemo->getPlayers()[1]->getKills());
$this->assertEquals(1, $retrievedDemo->getPlayers()[0]->getAssists()); $this->assertEquals(0, $retrievedDemo->getPlayers()[1]->getAssists());
$this->assertEquals(2, $retrievedDemo->getPlayers()[0]->getDeaths()); $this->assertEquals(1, $retrievedDemo->getPlayers()[1]->getDeaths());
$this->assertEquals('blue', $retrievedDemo->getPlayers()[0]->getTeam()); $this->assertEquals('red', $retrievedDemo->getPlayers()[1]->getTeam());
$this->assertEquals('soldier', $retrievedDemo->getPlayers()[0]->getClass()); $this->assertEquals('scout', $retrievedDemo->getPlayers()[1]->getClass());
$this->assertEquals('user1', $retrievedDemo->getPlayers()[1]->getName()); $this->assertEquals([
$this->assertEquals(2, $retrievedDemo->getPlayers()[1]->getKills()); new ChatMessage('user1', 12, 'msg1'),
$this->assertEquals(0, $retrievedDemo->getPlayers()[1]->getAssists()); new ChatMessage('user2', 13, 'msg2')
$this->assertEquals(1, $retrievedDemo->getPlayers()[1]->getDeaths()); ], $chatProvider->getChat($demoId));
$this->assertEquals('red', $retrievedDemo->getPlayers()[1]->getTeam()); }
$this->assertEquals('scout', $retrievedDemo->getPlayers()[1]->getClass());
$this->assertEquals([
new ChatMessage('user1', 12, 'msg1'),
new ChatMessage('user2', 13, 'msg2')
], $chatProvider->getChat($demoId));
}
} }

View file

@ -6,26 +6,26 @@ use Demostf\API\Demo\DemoStore;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class DemoStoreTest extends TestCase { class DemoStoreTest extends TestCase {
public function testStore() { public function testStore() {
$targetDir = tempnam(sys_get_temp_dir(), 'dummy_target_'); $targetDir = tempnam(sys_get_temp_dir(), 'dummy_target_');
unlink($targetDir); unlink($targetDir);
mkdir($targetDir); mkdir($targetDir);
$demoStore = new DemoStore($targetDir, 'static.example.com'); $demoStore = new DemoStore($targetDir, 'static.example.com');
$file = tempnam(sys_get_temp_dir(), 'dummy_'); $file = tempnam(sys_get_temp_dir(), 'dummy_');
file_put_contents($file, 'foobar'); file_put_contents($file, 'foobar');
$storedDemo = $demoStore->store($file, 'foodemo.dem'); $storedDemo = $demoStore->store($file, 'foodemo.dem');
$this->assertStringEndsWith('/foodemo.dem', $storedDemo->getUrl()); $this->assertStringEndsWith('/foodemo.dem', $storedDemo->getUrl());
$this->assertStringStartsWith('https://static.example.com/', $storedDemo->getUrl()); $this->assertStringStartsWith('https://static.example.com/', $storedDemo->getUrl());
$this->assertEquals('static', $storedDemo->getBackend()); $this->assertEquals('static', $storedDemo->getBackend());
$this->assertStringEqualsFile($storedDemo->getPath(), 'foobar'); $this->assertStringEqualsFile($storedDemo->getPath(), 'foobar');
unlink($storedDemo->getPath()); unlink($storedDemo->getPath());
rmdir(dirname($storedDemo->getPath())); rmdir(dirname($storedDemo->getPath()));
rmdir(dirname($storedDemo->getPath(), 2)); rmdir(dirname($storedDemo->getPath(), 2));
rmdir($targetDir); rmdir($targetDir);
} }
} }

View file

@ -7,60 +7,60 @@ use Demostf\API\Demo\HeaderParser;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class HeaderParserTest extends TestCase { class HeaderParserTest extends TestCase {
public function testParseFile() { public function testParseFile() {
$parser = new HeaderParser(); $parser = new HeaderParser();
$expected = new Header( $expected = new Header(
'HL2DEMO', 'HL2DEMO',
3, 3,
24, 24,
'UGC Highlander Match', 'UGC Highlander Match',
'SourceTV Demo', 'SourceTV Demo',
'koth_product_rc8', 'koth_product_rc8',
'tf', 'tf',
778.4849853515625, 778.4849853515625,
51899, 51899,
25703, 25703,
818263 818263
); );
$parsed = $parser->parseHeader(__DIR__ . '/../data/product.dem'); $parsed = $parser->parseHeader(__DIR__ . '/../data/product.dem');
$this->assertEquals($expected->getServer(), $parsed->getServer()); $this->assertEquals($expected->getServer(), $parsed->getServer());
$this->assertEquals($expected->getDuration(), $parsed->getDuration()); $this->assertEquals($expected->getDuration(), $parsed->getDuration());
$this->assertEquals($expected->getTicks(), $parsed->getTicks()); $this->assertEquals($expected->getTicks(), $parsed->getTicks());
$this->assertEquals($expected->getFrames(), $parsed->getFrames()); $this->assertEquals($expected->getFrames(), $parsed->getFrames());
$this->assertEquals($expected->getGame(), $parsed->getGame()); $this->assertEquals($expected->getGame(), $parsed->getGame());
$this->assertEquals($expected->getMap(), $parsed->getMap()); $this->assertEquals($expected->getMap(), $parsed->getMap());
$this->assertEquals($expected->getNick(), $parsed->getNick()); $this->assertEquals($expected->getNick(), $parsed->getNick());
$this->assertEquals($expected->getProtocol(), $parsed->getProtocol()); $this->assertEquals($expected->getProtocol(), $parsed->getProtocol());
$this->assertEquals($expected->getSigon(), $parsed->getSigon()); $this->assertEquals($expected->getSigon(), $parsed->getSigon());
$this->assertEquals($expected->getType(), $parsed->getType()); $this->assertEquals($expected->getType(), $parsed->getType());
$this->assertEquals($expected->getVersion(), $parsed->getVersion()); $this->assertEquals($expected->getVersion(), $parsed->getVersion());
} }
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
* @expectedExceptionMessage Not an HL2 demo * @expectedExceptionMessage Not an HL2 demo
*/ */
public function testNonDemoShort() { public function testNonDemoShort() {
$parser = new HeaderParser(); $parser = new HeaderParser();
$parser->parseString("short"); $parser->parseString("short");
} }
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
* @expectedExceptionMessage Not an HL2 demo * @expectedExceptionMessage Not an HL2 demo
*/ */
public function testNonDemoLong() { public function testNonDemoLong() {
$parser = new HeaderParser(); $parser = new HeaderParser();
$parser->parseHeader(__FILE__); $parser->parseHeader(__FILE__);
} }
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
*/ */
public function testNonExisting() { public function testNonExisting() {
$parser = new HeaderParser(); $parser = new HeaderParser();
$parser->parseHeader('/non/existing'); $parser->parseHeader('/non/existing');
} }
} }

View file

@ -7,87 +7,87 @@ use Demostf\API\Demo\RawParser;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class ParserTest extends TestCase { class ParserTest extends TestCase {
/** @var RawParser|\PHPUnit_Framework_MockObject_MockObject */ /** @var RawParser|\PHPUnit_Framework_MockObject_MockObject */
private $rawParser; private $rawParser;
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->rawParser = $this->getMockBuilder(RawParser::class) $this->rawParser = $this->getMockBuilder(RawParser::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->rawParser->expects($this->any()) $this->rawParser->expects($this->any())
->method('parse') ->method('parse')
->will($this->returnCallback(function ($path) { ->will($this->returnCallback(function ($path) {
$jsonPath = str_replace('.dem', '-raw.json', $path); $jsonPath = str_replace('.dem', '-raw.json', $path);
return json_decode(file_get_contents($jsonPath), true); return json_decode(file_get_contents($jsonPath), true);
})); }));
} }
public function testAnalyse() { public function testAnalyse() {
$parser = new Parser($this->rawParser); $parser = new Parser($this->rawParser);
$result = $parser->analyse(__DIR__ . '/../data/product.dem'); $result = $parser->analyse(__DIR__ . '/../data/product.dem');
$expectedRaw = json_decode(file_get_contents(__DIR__ . '/../data/product-analyse.json'), true); $expectedRaw = json_decode(file_get_contents(__DIR__ . '/../data/product-analyse.json'), true);
$expectedChat = $expectedRaw['chat']; $expectedChat = $expectedRaw['chat'];
$this->assertCount(count($expectedChat), $result->getChat()); $this->assertCount(count($expectedChat), $result->getChat());
$this->assertEquals($expectedChat[0]['text'], $result->getChat()[0]->getMessage()); $this->assertEquals($expectedChat[0]['text'], $result->getChat()[0]->getMessage());
$this->assertEquals($expectedChat[0]['time'], $result->getChat()[0]->getTime()); $this->assertEquals($expectedChat[0]['time'], $result->getChat()[0]->getTime());
$this->assertEquals($expectedChat[0]['from'], $result->getChat()[0]->getUser()); $this->assertEquals($expectedChat[0]['from'], $result->getChat()[0]->getUser());
$this->assertEquals($expectedRaw['score']['red'], $result->getRedScore()); $this->assertEquals($expectedRaw['score']['red'], $result->getRedScore());
$this->assertEquals($expectedRaw['score']['blue'], $result->getBlueScore()); $this->assertEquals($expectedRaw['score']['blue'], $result->getBlueScore());
$expectedPlayers = $expectedRaw['players']; $expectedPlayers = $expectedRaw['players'];
$this->assertCount(count($expectedPlayers), $result->getPlayers()); $this->assertCount(count($expectedPlayers), $result->getPlayers());
$this->assertEquals($expectedPlayers[0]['name'], $result->getPlayers()[0]->getName()); $this->assertEquals($expectedPlayers[0]['name'], $result->getPlayers()[0]->getName());
$this->assertEquals($expectedPlayers[0]['demo_user_id'], $result->getPlayers()[0]->getDemoUserId()); $this->assertEquals($expectedPlayers[0]['demo_user_id'], $result->getPlayers()[0]->getDemoUserId());
$this->assertEquals($expectedPlayers[0]['team'], $result->getPlayers()[0]->getTeam()); $this->assertEquals($expectedPlayers[0]['team'], $result->getPlayers()[0]->getTeam());
$this->assertEquals($expectedPlayers[0]['class'], $result->getPlayers()[0]->getClass()); $this->assertEquals($expectedPlayers[0]['class'], $result->getPlayers()[0]->getClass());
$this->assertEquals($parser->convertSteamIdToCommunityId($expectedPlayers[0]['steam_id']), $result->getPlayers()[0]->getSteamId()); $this->assertEquals($parser->convertSteamIdToCommunityId($expectedPlayers[0]['steam_id']), $result->getPlayers()[0]->getSteamId());
$expectedKills = $expectedRaw['kills']; $expectedKills = $expectedRaw['kills'];
$this->assertCount(count($expectedKills), $result->getKills()); $this->assertCount(count($expectedKills), $result->getKills());
$this->assertEquals((int)$expectedKills[0]['killer'], $result->getKills()[0]->getAttackerDemoId()); $this->assertEquals((int)$expectedKills[0]['killer'], $result->getKills()[0]->getAttackerDemoId());
$this->assertEquals((int)$expectedKills[0]['assister'], $result->getKills()[0]->getAssisterDemoId()); $this->assertEquals((int)$expectedKills[0]['assister'], $result->getKills()[0]->getAssisterDemoId());
$this->assertEquals((int)$expectedKills[0]['victim'], $result->getKills()[0]->getVictimDemoId()); $this->assertEquals((int)$expectedKills[0]['victim'], $result->getKills()[0]->getVictimDemoId());
$this->assertEquals($expectedKills[0]['weapon'], $result->getKills()[0]->getWeapon()); $this->assertEquals($expectedKills[0]['weapon'], $result->getKills()[0]->getWeapon());
} }
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
*/ */
public function testFailedParse() { public function testFailedParse() {
/** @var RawParser|\PHPUnit_Framework_MockObject_MockObject $rawParser */ /** @var RawParser|\PHPUnit_Framework_MockObject_MockObject $rawParser */
$rawParser = $this->getMockBuilder(RawParser::class) $rawParser = $this->getMockBuilder(RawParser::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$parser = new Parser($rawParser); $parser = new Parser($rawParser);
$rawParser->expects($this->any()) $rawParser->expects($this->any())
->method('parse') ->method('parse')
->willReturn(null); ->willReturn(null);
$parser->analyse('foo'); $parser->analyse('foo');
} }
public function testConvertSteamIdToCommunityId() { public function testConvertSteamIdToCommunityId() {
$parser = new Parser($this->rawParser); $parser = new Parser($this->rawParser);
$steamId64 = $parser->convertSteamIdToCommunityId('STEAM_0:0:12345'); $steamId64 = $parser->convertSteamIdToCommunityId('STEAM_0:0:12345');
$this->assertEquals('76561197960290418', $steamId64); $this->assertEquals('76561197960290418', $steamId64);
} }
public function testConvertUIdToCommunityId() { public function testConvertUIdToCommunityId() {
$parser = new Parser($this->rawParser); $parser = new Parser($this->rawParser);
$steamId64 = $parser->convertSteamIdToCommunityId('[U:1:12345]'); $steamId64 = $parser->convertSteamIdToCommunityId('[U:1:12345]');
$this->assertEquals('76561197960278073', $steamId64); $this->assertEquals('76561197960278073', $steamId64);
$steamId64 = $parser->convertSteamIdToCommunityId('[U:1:39743963]'); $steamId64 = $parser->convertSteamIdToCommunityId('[U:1:39743963]');
$this->assertEquals('76561198000009691', $steamId64); $this->assertEquals('76561198000009691', $steamId64);
} }
} }

View file

@ -7,33 +7,33 @@ use Demostf\API\Providers\ChatProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class ChatProviderTest extends TestCase { class ChatProviderTest extends TestCase {
/** @var ChatProvider */ /** @var ChatProvider */
private $provider; private $provider;
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->provider = new ChatProvider($this->getDatabaseConnection()); $this->provider = new ChatProvider($this->getDatabaseConnection());
} }
public function testGetEmptyChat() { public function testGetEmptyChat() {
$this->assertCount(0, $this->provider->getChat(1)); $this->assertCount(0, $this->provider->getChat(1));
} }
public function testStoreRetrieve() { public function testStoreRetrieve() {
$message1 = new ChatMessage('foo', 2, 'bar'); $message1 = new ChatMessage('foo', 2, 'bar');
$message2 = new ChatMessage('foo2', 2, 'bar2'); $message2 = new ChatMessage('foo2', 2, 'bar2');
$message3 = new ChatMessage('foo2', 2, 'bar2'); $message3 = new ChatMessage('foo2', 2, 'bar2');
$this->provider->storeChatMessage(1, $message1); $this->provider->storeChatMessage(1, $message1);
$this->provider->storeChatMessage(1, $message2); $this->provider->storeChatMessage(1, $message2);
$this->provider->storeChatMessage(2, $message3); $this->provider->storeChatMessage(2, $message3);
$result = $this->provider->getChat(1); $result = $this->provider->getChat(1);
sort($result); sort($result);
$this->assertCount(2, $result); $this->assertCount(2, $result);
$this->assertEquals($message1, $result[0]); $this->assertEquals($message1, $result[0]);
$this->assertEquals($message2, $result[1]); $this->assertEquals($message2, $result[1]);
} }
} }

View file

@ -11,153 +11,153 @@ use Demostf\API\Providers\UserProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class DemoListProviderTest extends TestCase { class DemoListProviderTest extends TestCase {
/** @var DemoListProvider */ /** @var DemoListProvider */
private $demoListProvider; private $demoListProvider;
/** @var DemoProvider */ /** @var DemoProvider */
private $demoProvider; private $demoProvider;
/** @var PlayerProvider */ /** @var PlayerProvider */
private $playerProvider; private $playerProvider;
/** @var UserProvider */ /** @var UserProvider */
private $userProvider; private $userProvider;
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->demoListProvider = new DemoListProvider($this->getDatabaseConnection()); $this->demoListProvider = new DemoListProvider($this->getDatabaseConnection());
$this->demoProvider = new DemoProvider($this->getDatabaseConnection()); $this->demoProvider = new DemoProvider($this->getDatabaseConnection());
$this->playerProvider = new PlayerProvider($this->getDatabaseConnection()); $this->playerProvider = new PlayerProvider($this->getDatabaseConnection());
$this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator()); $this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator());
} }
private function getDemo(int $uploaderId, $map = 'map', $playerCount = 18) { private function getDemo(int $uploaderId, $map = 'map', $playerCount = 18) {
return new Demo( return new Demo(
0, 0,
'http://example.com', 'http://example.com',
'name', 'name',
'server', 'server',
12, 12,
'nick', 'nick',
$map, $map,
new \DateTime(), new \DateTime(),
'RED', 'RED',
'BLUE', 'BLUE',
1, 1,
2, 2,
$playerCount, $playerCount,
$uploaderId, $uploaderId,
'hash', 'hash',
'backend', 'backend',
'path' 'path'
); );
} }
public function testListEmpty() { public function testListEmpty() {
$this->assertEquals([], $this->demoListProvider->listDemos(1)); $this->assertEquals([], $this->demoListProvider->listDemos(1));
} }
public function testListSimple() { public function testListSimple() {
$id1 = $this->demoProvider->storeDemo($this->getDemo(1), 'foo', 'bar'); $id1 = $this->demoProvider->storeDemo($this->getDemo(1), 'foo', 'bar');
$id2 = $this->demoProvider->storeDemo($this->getDemo(1), 'foo', 'bar'); $id2 = $this->demoProvider->storeDemo($this->getDemo(1), 'foo', 'bar');
$id3 = $this->demoProvider->storeDemo($this->getDemo(1), 'foo', 'bar'); $id3 = $this->demoProvider->storeDemo($this->getDemo(1), 'foo', 'bar');
$list = $this->demoListProvider->listDemos(1); $list = $this->demoListProvider->listDemos(1);
$this->assertCount(3, $list); $this->assertCount(3, $list);
$this->assertEquals($id3, $list[0]->getId()); $this->assertEquals($id3, $list[0]->getId());
$this->assertEquals($id2, $list[1]->getId()); $this->assertEquals($id2, $list[1]->getId());
$this->assertEquals($id1, $list[2]->getId()); $this->assertEquals($id1, $list[2]->getId());
} }
public function testFilterMap() { public function testFilterMap() {
$id1 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1'), 'foo', 'bar'); $id1 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1'), 'foo', 'bar');
$id2 = $this->demoProvider->storeDemo($this->getDemo(1, 'map2'), 'foo', 'bar'); $id2 = $this->demoProvider->storeDemo($this->getDemo(1, 'map2'), 'foo', 'bar');
$id3 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1'), 'foo', 'bar'); $id3 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1'), 'foo', 'bar');
$list = $this->demoListProvider->listDemos(1, ['map' => 'map1']); $list = $this->demoListProvider->listDemos(1, ['map' => 'map1']);
$this->assertCount(2, $list); $this->assertCount(2, $list);
$this->assertEquals($id3, $list[0]->getId()); $this->assertEquals($id3, $list[0]->getId());
$this->assertEquals($id1, $list[1]->getId()); $this->assertEquals($id1, $list[1]->getId());
} }
public function testFilterPlayerCount() { public function testFilterPlayerCount() {
$id1 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 17), 'foo', 'bar'); $id1 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 17), 'foo', 'bar');
$id2 = $this->demoProvider->storeDemo($this->getDemo(1, 'map2', 18), 'foo', 'bar'); $id2 = $this->demoProvider->storeDemo($this->getDemo(1, 'map2', 18), 'foo', 'bar');
$id3 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 12), 'foo', 'bar'); $id3 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 12), 'foo', 'bar');
$list = $this->demoListProvider->listDemos(1, ['playerCount' => [17, 18, 19]]); $list = $this->demoListProvider->listDemos(1, ['playerCount' => [17, 18, 19]]);
$this->assertCount(2, $list); $this->assertCount(2, $list);
$this->assertEquals($id2, $list[0]->getId()); $this->assertEquals($id2, $list[0]->getId());
$this->assertEquals($id1, $list[1]->getId()); $this->assertEquals($id1, $list[1]->getId());
} }
public function testByUploader() { public function testByUploader() {
$steamId = $this->getSteamId('12345', 'bar'); $steamId = $this->getSteamId('12345', 'bar');
$this->userProvider->store($steamId); $this->userProvider->store($steamId);
$userId = $this->userProvider->get($steamId->getSteamId64())->getId(); $userId = $this->userProvider->get($steamId->getSteamId64())->getId();
$id1 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map1', 17), 'foo', 'bar'); $id1 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map1', 17), 'foo', 'bar');
$id2 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map2', 18), 'foo', 'bar'); $id2 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map2', 18), 'foo', 'bar');
$id3 = $this->demoProvider->storeDemo($this->getDemo($userId + 1, 'map1', 12), 'foo', 'bar'); $id3 = $this->demoProvider->storeDemo($this->getDemo($userId + 1, 'map1', 12), 'foo', 'bar');
$list = $this->demoListProvider->listUploads($steamId->getSteamId64(), 1); $list = $this->demoListProvider->listUploads($steamId->getSteamId64(), 1);
$this->assertEquals($id2, $list[0]->getId()); $this->assertEquals($id2, $list[0]->getId());
$this->assertEquals($id1, $list[1]->getId()); $this->assertEquals($id1, $list[1]->getId());
} }
public function testByUploaderFilter() { public function testByUploaderFilter() {
$steamId = $this->getSteamId('12345', 'bar'); $steamId = $this->getSteamId('12345', 'bar');
$this->userProvider->store($steamId); $this->userProvider->store($steamId);
$userId = $this->userProvider->get($steamId->getSteamId64())->getId(); $userId = $this->userProvider->get($steamId->getSteamId64())->getId();
$id1 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map1', 12), 'foo', 'bar'); $id1 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map1', 12), 'foo', 'bar');
$id2 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map2', 18), 'foo', 'bar'); $id2 = $this->demoProvider->storeDemo($this->getDemo($userId, 'map2', 18), 'foo', 'bar');
$id3 = $this->demoProvider->storeDemo($this->getDemo($userId + 1, 'map1', 12), 'foo', 'bar'); $id3 = $this->demoProvider->storeDemo($this->getDemo($userId + 1, 'map1', 12), 'foo', 'bar');
$list = $this->demoListProvider->listUploads($steamId->getSteamId64(), 1, ['playerCount' => [17, 18, 19]]); $list = $this->demoListProvider->listUploads($steamId->getSteamId64(), 1, ['playerCount' => [17, 18, 19]]);
$this->assertEquals($id2, $list[0]->getId()); $this->assertEquals($id2, $list[0]->getId());
} }
private function addPlayer($demoId, $userId) { private function addPlayer($demoId, $userId) {
$player = new Player(0, $demoId, 0, $userId, 'foo', 'red', 'scout'); $player = new Player(0, $demoId, 0, $userId, 'foo', 'red', 'scout');
$this->playerProvider->store($player); $this->playerProvider->store($player);
} }
public function testFilterPlayer() { public function testFilterPlayer() {
$steamId1 = $this->getSteamId('12345', 'bar1'); $steamId1 = $this->getSteamId('12345', 'bar1');
$steamId2 = $this->getSteamId('22345', 'bar2'); $steamId2 = $this->getSteamId('22345', 'bar2');
$steamId3 = $this->getSteamId('32345', 'bar3'); $steamId3 = $this->getSteamId('32345', 'bar3');
$this->userProvider->store($steamId1); $this->userProvider->store($steamId1);
$this->userProvider->store($steamId2); $this->userProvider->store($steamId2);
$this->userProvider->store($steamId3); $this->userProvider->store($steamId3);
$userId1 = $this->userProvider->get($steamId1->getSteamId64())->getId(); $userId1 = $this->userProvider->get($steamId1->getSteamId64())->getId();
$userId2 = $this->userProvider->get($steamId2->getSteamId64())->getId(); $userId2 = $this->userProvider->get($steamId2->getSteamId64())->getId();
$userId3 = $this->userProvider->get($steamId3->getSteamId64())->getId(); $userId3 = $this->userProvider->get($steamId3->getSteamId64())->getId();
$id1 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 17), 'foo', 'bar'); $id1 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 17), 'foo', 'bar');
$id2 = $this->demoProvider->storeDemo($this->getDemo(1, 'map2', 18), 'foo', 'bar'); $id2 = $this->demoProvider->storeDemo($this->getDemo(1, 'map2', 18), 'foo', 'bar');
$id3 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 12), 'foo', 'bar'); $id3 = $this->demoProvider->storeDemo($this->getDemo(1, 'map1', 12), 'foo', 'bar');
$this->addPlayer($id1, $userId1); $this->addPlayer($id1, $userId1);
$this->addPlayer($id1, $userId2); $this->addPlayer($id1, $userId2);
$this->addPlayer($id2, $userId1); $this->addPlayer($id2, $userId1);
$this->addPlayer($id2, $userId3); $this->addPlayer($id2, $userId3);
$this->addPlayer($id3, $userId3); $this->addPlayer($id3, $userId3);
$list = $this->demoListProvider->listDemos(1, ['players' => [$steamId1->getSteamId64()]]); $list = $this->demoListProvider->listDemos(1, ['players' => [$steamId1->getSteamId64()]]);
$this->assertCount(2, $list); $this->assertCount(2, $list);
$this->assertEquals($id2, $list[0]->getId()); $this->assertEquals($id2, $list[0]->getId());
$this->assertEquals($id1, $list[1]->getId()); $this->assertEquals($id1, $list[1]->getId());
$list = $this->demoListProvider->listDemos(1, ['players' => [$steamId1->getSteamId64(), $steamId3->getSteamId64()]]); $list = $this->demoListProvider->listDemos(1, ['players' => [$steamId1->getSteamId64(), $steamId3->getSteamId64()]]);
$this->assertCount(1, $list); $this->assertCount(1, $list);
$this->assertEquals($id2, $list[0]->getId()); $this->assertEquals($id2, $list[0]->getId());
$list = $this->demoListProvider->listDemos(1, ['players' => [$steamId2->getSteamId64(), $steamId3->getSteamId64()]]); $list = $this->demoListProvider->listDemos(1, ['players' => [$steamId2->getSteamId64(), $steamId3->getSteamId64()]]);
$this->assertCount(0, $list); $this->assertCount(0, $list);
} }
} }

View file

@ -13,187 +13,187 @@ use Demostf\API\Providers\UserProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class DemoProviderTest extends TestCase { class DemoProviderTest extends TestCase {
/** @var DemoProvider */ /** @var DemoProvider */
private $provider; private $provider;
/** @var UserProvider */ /** @var UserProvider */
private $userProvider; private $userProvider;
/** @var PlayerProvider */ /** @var PlayerProvider */
private $playerProvider; private $playerProvider;
/** @var KillProvider */ /** @var KillProvider */
private $killProvider; private $killProvider;
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->provider = new DemoProvider($this->getDatabaseConnection()); $this->provider = new DemoProvider($this->getDatabaseConnection());
$this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator()); $this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator());
$this->playerProvider = new PlayerProvider($this->getDatabaseConnection()); $this->playerProvider = new PlayerProvider($this->getDatabaseConnection());
$this->killProvider = new KillProvider($this->getDatabaseConnection()); $this->killProvider = new KillProvider($this->getDatabaseConnection());
} }
public function testGetNonExisting() { public function testGetNonExisting() {
$this->assertNull($this->provider->get(1)); $this->assertNull($this->provider->get(1));
} }
public function testStoreRetrieve() { public function testStoreRetrieve() {
$uploaderSteamId = $this->getSteamId('12345', 'test'); $uploaderSteamId = $this->getSteamId('12345', 'test');
$this->userProvider->store($uploaderSteamId); $this->userProvider->store($uploaderSteamId);
$uploader = $this->userProvider->get($uploaderSteamId->getSteamId64()); $uploader = $this->userProvider->get($uploaderSteamId->getSteamId64());
$demo = new Demo( $demo = new Demo(
0, 0,
'http://example.com', 'http://example.com',
'name', 'name',
'server', 'server',
12, 12,
'nick', 'nick',
'map', 'map',
new \DateTime(), new \DateTime(),
'RED', 'RED',
'BLUE', 'BLUE',
1, 1,
2, 2,
18, 18,
$uploader->getId(), $uploader->getId(),
'hash', 'hash',
'dummy', 'dummy',
'path' 'path'
); );
$demo->setUploaderUser($uploader); $demo->setUploaderUser($uploader);
$id = $this->provider->storeDemo($demo, 'dummy', 'path'); $id = $this->provider->storeDemo($demo, 'dummy', 'path');
$retrieved = $this->provider->get($id); $retrieved = $this->provider->get($id);
$this->assertInstanceOf(Demo::class, $retrieved); $this->assertInstanceOf(Demo::class, $retrieved);
$storedData = $demo->jsonSerialize(); $storedData = $demo->jsonSerialize();
$storedData['id'] = $id; $storedData['id'] = $id;
$this->assertEquals($storedData, $retrieved->jsonSerialize()); $this->assertEquals($storedData, $retrieved->jsonSerialize());
$this->assertEquals($id, $this->provider->demoIdByHash('hash')); $this->assertEquals($id, $this->provider->demoIdByHash('hash'));
} }
public function testRetrieveWithPlayers() { public function testRetrieveWithPlayers() {
$uploaderSteamId = $this->getSteamId('12345', 'test'); $uploaderSteamId = $this->getSteamId('12345', 'test');
$this->userProvider->store($uploaderSteamId); $this->userProvider->store($uploaderSteamId);
$steamId1 = $this->getSteamId('1', 'u1'); $steamId1 = $this->getSteamId('1', 'u1');
$steamId2 = $this->getSteamId('2', 'u2'); $steamId2 = $this->getSteamId('2', 'u2');
$steamId3 = $this->getSteamId('3', 'u3'); $steamId3 = $this->getSteamId('3', 'u3');
$steamId4 = $this->getSteamId('4', 'u4'); $steamId4 = $this->getSteamId('4', 'u4');
$this->userProvider->store($steamId1); $this->userProvider->store($steamId1);
$this->userProvider->store($steamId2); $this->userProvider->store($steamId2);
$this->userProvider->store($steamId3); $this->userProvider->store($steamId3);
$this->userProvider->store($steamId4); $this->userProvider->store($steamId4);
$user1 = $this->userProvider->get($steamId1->getSteamId64()); $user1 = $this->userProvider->get($steamId1->getSteamId64());
$user2 = $this->userProvider->get($steamId2->getSteamId64()); $user2 = $this->userProvider->get($steamId2->getSteamId64());
$user3 = $this->userProvider->get($steamId3->getSteamId64()); $user3 = $this->userProvider->get($steamId3->getSteamId64());
$user4 = $this->userProvider->get($steamId4->getSteamId64()); $user4 = $this->userProvider->get($steamId4->getSteamId64());
$uploader = $this->userProvider->get($uploaderSteamId->getSteamId64()); $uploader = $this->userProvider->get($uploaderSteamId->getSteamId64());
$demo = new Demo( $demo = new Demo(
0, 0,
'http://example.com', 'http://example.com',
'name', 'name',
'server', 'server',
12, 12,
'nick', 'nick',
'map', 'map',
new \DateTime(), new \DateTime(),
'RED', 'RED',
'BLUE', 'BLUE',
1, 1,
2, 2,
18, 18,
$uploader->getId(), $uploader->getId(),
'hash', 'hash',
'backend', 'backend',
'path', 'path',
'dummy', 'dummy',
'path' 'path'
); );
$id = $this->provider->storeDemo($demo, 'dummy', 'path'); $id = $this->provider->storeDemo($demo, 'dummy', 'path');
$player1 = $this->addPlayer($id, 101, $user1->getId(), 'red', 'scout'); $player1 = $this->addPlayer($id, 101, $user1->getId(), 'red', 'scout');
$player2 = $this->addPlayer($id, 102, $user2->getId(), 'red', 'soldier'); $player2 = $this->addPlayer($id, 102, $user2->getId(), 'red', 'soldier');
$player3 = $this->addPlayer($id, 103, $user3->getId(), 'blue', 'engineer'); $player3 = $this->addPlayer($id, 103, $user3->getId(), 'blue', 'engineer');
$player4 = $this->addPlayer($id, 104, $user4->getId(), 'blue', 'spy'); $player4 = $this->addPlayer($id, 104, $user4->getId(), 'blue', 'spy');
$this->addKill($id, $user1->getId(), 0, $user3->getId(), 'pan'); $this->addKill($id, $user1->getId(), 0, $user3->getId(), 'pan');
$this->addKill($id, $user1->getId(), $user2->getId(), $user3->getId(), 'pan'); $this->addKill($id, $user1->getId(), $user2->getId(), $user3->getId(), 'pan');
$this->addKill($id, $user4->getId(), 0, $user1->getId(), 'pan'); $this->addKill($id, $user4->getId(), 0, $user1->getId(), 'pan');
$retrieved = $this->provider->get($id, true); $retrieved = $this->provider->get($id, true);
$this->assertInstanceOf(Demo::class, $retrieved); $this->assertInstanceOf(Demo::class, $retrieved);
$players = $retrieved->getPlayers(); $players = $retrieved->getPlayers();
$this->assertCount(4, $players); $this->assertCount(4, $players);
usort($players, function (DemoPlayer $a, DemoPlayer $b) { usort($players, function (DemoPlayer $a, DemoPlayer $b) {
return $a->getUserId() - $b->getUserId(); return $a->getUserId() - $b->getUserId();
}); });
$this->assertEquals([ $this->assertEquals([
new DemoPlayer($player1, $user1->getId(), 'user_' . $user1->getId(), 'red', 'scout', '1', 'foo_medium.jpg', 2, 0, 1), new DemoPlayer($player1, $user1->getId(), 'user_' . $user1->getId(), 'red', 'scout', '1', 'foo_medium.jpg', 2, 0, 1),
new DemoPlayer($player2, $user2->getId(), 'user_' . $user2->getId(), 'red', 'soldier', '2', 'foo_medium.jpg', 0, 1, 0), new DemoPlayer($player2, $user2->getId(), 'user_' . $user2->getId(), 'red', 'soldier', '2', 'foo_medium.jpg', 0, 1, 0),
new DemoPlayer($player3, $user3->getId(), 'user_' . $user3->getId(), 'blue', 'engineer', '3', 'foo_medium.jpg', 0, 0, 2), new DemoPlayer($player3, $user3->getId(), 'user_' . $user3->getId(), 'blue', 'engineer', '3', 'foo_medium.jpg', 0, 0, 2),
new DemoPlayer($player4, $user4->getId(), 'user_' . $user4->getId(), 'blue', 'spy', '4', 'foo_medium.jpg', 1, 0, 0), new DemoPlayer($player4, $user4->getId(), 'user_' . $user4->getId(), 'blue', 'spy', '4', 'foo_medium.jpg', 1, 0, 0),
], $players); ], $players);
} }
private function addPlayer(int $demoId, int $demoUserId, int $userId, string $team, string $class): int { private function addPlayer(int $demoId, int $demoUserId, int $userId, string $team, string $class): int {
$player = new Player(0, $demoId, $demoUserId, $userId, 'user_' . $userId, $team, $class); $player = new Player(0, $demoId, $demoUserId, $userId, 'user_' . $userId, $team, $class);
return $this->playerProvider->store($player); return $this->playerProvider->store($player);
} }
private function addKill(int $demoId, int $attackerId, int $assisterId, int $victimId, string $weapon): int { private function addKill(int $demoId, int $attackerId, int $assisterId, int $victimId, string $weapon): int {
$kill = new Kill(0, $demoId, $attackerId, $assisterId, $victimId, $weapon); $kill = new Kill(0, $demoId, $attackerId, $assisterId, $victimId, $weapon);
return $this->killProvider->store($kill); return $this->killProvider->store($kill);
} }
public function testSetDemoUrl() { public function testSetDemoUrl() {
$uploaderSteamId = $this->getSteamId('12345', 'test'); $uploaderSteamId = $this->getSteamId('12345', 'test');
$this->userProvider->store($uploaderSteamId); $this->userProvider->store($uploaderSteamId);
$uploader = $this->userProvider->get($uploaderSteamId->getSteamId64()); $uploader = $this->userProvider->get($uploaderSteamId->getSteamId64());
$demo = new Demo( $demo = new Demo(
0, 0,
'http://example.com', 'http://example.com',
'name', 'name',
'server', 'server',
12, 12,
'nick', 'nick',
'map', 'map',
new \DateTime(), new \DateTime(),
'RED', 'RED',
'BLUE', 'BLUE',
1, 1,
2, 2,
18, 18,
$uploader->getId(), $uploader->getId(),
'hash', 'hash',
'dummy', 'dummy',
'path' 'path'
); );
$id = $this->provider->storeDemo($demo, 'dummy', 'path'); $id = $this->provider->storeDemo($demo, 'dummy', 'path');
$id2 = $this->provider->storeDemo($demo, 'dummy', 'path'); $id2 = $this->provider->storeDemo($demo, 'dummy', 'path');
$this->provider->setDemoUrl($id, 'foobackend', 'http://foo.example.com', 'bar'); $this->provider->setDemoUrl($id, 'foobackend', 'http://foo.example.com', 'bar');
$storedDemo = $this->provider->get($id); $storedDemo = $this->provider->get($id);
$this->assertEquals('http://foo.example.com', $storedDemo->getUrl()); $this->assertEquals('http://foo.example.com', $storedDemo->getUrl());
$this->assertEquals('foobackend', $storedDemo->getBackend()); $this->assertEquals('foobackend', $storedDemo->getBackend());
$this->assertEquals('bar', $storedDemo->getPath()); $this->assertEquals('bar', $storedDemo->getPath());
$storedDemo2 = $this->provider->get($id2); $storedDemo2 = $this->provider->get($id2);
$this->assertEquals('http://example.com', $storedDemo2->getUrl()); $this->assertEquals('http://example.com', $storedDemo2->getUrl());
} }
} }

View file

@ -19,284 +19,289 @@ use Demostf\API\Providers\UserProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class UploadProviderTest extends TestCase { class UploadProviderTest extends TestCase {
/** @var RawParser */ /** @var RawParser */
private $rawParser; private $rawParser;
/** @var HeaderParser */ /** @var HeaderParser */
private $headerParser; private $headerParser;
/** @var Parser */ /** @var Parser */
private $parser; private $parser;
/** @var DemoStore */ /** @var DemoStore */
private $demoStore; private $demoStore;
/** @var UserProvider */ /** @var UserProvider */
private $userProvider; private $userProvider;
/** @var DemoProvider */ /** @var DemoProvider */
private $demoProvider; private $demoProvider;
/** @var DemoSaver */ /** @var DemoSaver */
private $demoSaver; private $demoSaver;
/** @var UploadProvider */ /** @var UploadProvider */
private $uploadProvider; private $uploadProvider;
/** @var string */ /** @var string */
private $tmpDir; private $tmpDir;
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->rawParser = $this->getMockBuilder(RawParser::class) $this->rawParser = $this->getMockBuilder(RawParser::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->rawParser->expects($this->any()) $this->rawParser->expects($this->any())
->method('parse') ->method('parse')
->will($this->returnCallback(function ($path) { ->will($this->returnCallback(function ($path) {
$jsonPath = str_replace('.dem', '-raw.json', $path); $jsonPath = str_replace('.dem', '-raw.json', $path);
return json_decode(file_get_contents($jsonPath), true); return json_decode(file_get_contents($jsonPath), true);
})); }));
$targetDir = tempnam(sys_get_temp_dir(), 'dummy_target_'); $targetDir = tempnam(sys_get_temp_dir(), 'dummy_target_');
unlink($targetDir); unlink($targetDir);
mkdir($targetDir); mkdir($targetDir);
$this->tmpDir = $targetDir; $this->tmpDir = $targetDir;
$this->headerParser = new HeaderParser(); $this->headerParser = new HeaderParser();
$this->parser = new Parser($this->rawParser); $this->parser = new Parser($this->rawParser);
$this->demoStore = new DemoStore($targetDir, 'example.com'); $this->demoStore = new DemoStore($targetDir, 'example.com');
$this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator()); $this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator());
$this->demoProvider = new DemoProvider($this->getDatabaseConnection()); $this->demoProvider = new DemoProvider($this->getDatabaseConnection());
$this->demoSaver = new DemoSaver( $this->demoSaver = new DemoSaver(
new KillProvider($this->getDatabaseConnection()), new KillProvider($this->getDatabaseConnection()),
new PlayerProvider($this->getDatabaseConnection()), new PlayerProvider($this->getDatabaseConnection()),
new ChatProvider($this->getDatabaseConnection()), new ChatProvider($this->getDatabaseConnection()),
$this->userProvider, $this->userProvider,
$this->demoProvider $this->demoProvider
); );
$this->uploadProvider = new UploadProvider( $this->uploadProvider = new UploadProvider(
$this->getDatabaseConnection(), $this->getDatabaseConnection(),
'http://example.com', 'http://example.com',
$this->headerParser, $this->headerParser,
$this->parser, $this->parser,
$this->demoStore, $this->demoStore,
$this->userProvider, $this->userProvider,
$this->demoProvider, $this->demoProvider,
$this->demoSaver $this->demoSaver
); );
} }
private function rmdirr($dir) { private function rmdirr($dir) {
$it = new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS); $it = new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS);
$files = new \RecursiveIteratorIterator($it, $files = new \RecursiveIteratorIterator(
\RecursiveIteratorIterator::CHILD_FIRST); $it,
foreach ($files as $file) { \RecursiveIteratorIterator::CHILD_FIRST
if ($file->isDir()) { );
rmdir($file->getRealPath()); foreach ($files as $file) {
} else { if ($file->isDir()) {
unlink($file->getRealPath()); rmdir($file->getRealPath());
} } else {
} unlink($file->getRealPath());
rmdir($dir); }
} }
rmdir($dir);
}
public function tearDown() { public function tearDown() {
$this->rmdirr($this->tmpDir); $this->rmdirr($this->tmpDir);
parent::tearDown(); parent::tearDown();
} }
public function testValidateHeaderToSmall() { public function testValidateHeaderToSmall() {
$this->assertEquals('Demos needs to be at least 1KB is size', $this->uploadProvider->validateHeader( $this->assertEquals('Demos needs to be at least 1KB is size', $this->uploadProvider->validateHeader(
12, 12,
new Header( new Header(
'HL2DEMO', 'HL2DEMO',
1, 1,
2, 2,
'Server', 'Server',
'Nick', 'Nick',
'cp_gullywash', 'cp_gullywash',
'tf', 'tf',
12, 12,
12, 12,
12, 12,
12 12
) )
)); ));
} }
public function testValidateHeaderToBig() { public function testValidateHeaderToBig() {
$this->assertEquals('Demos cant be more than 100MB in size', $this->uploadProvider->validateHeader( $this->assertEquals('Demos cant be more than 100MB in size', $this->uploadProvider->validateHeader(
99999999999, 99999999999,
new Header( new Header(
'HL2DEMO', 'HL2DEMO',
1, 1,
2, 2,
'Server', 'Server',
'Nick', 'Nick',
'cp_gullywash', 'cp_gullywash',
'tf', 'tf',
12, 12,
12, 12,
12, 12,
12 12
) )
)); ));
} }
public function testValidateHeaderToLong() { public function testValidateHeaderToLong() {
$this->assertEquals('Demos cant be longer than one hour', $this->uploadProvider->validateHeader( $this->assertEquals('Demos cant be longer than one hour', $this->uploadProvider->validateHeader(
9999, 9999,
new Header( new Header(
'HL2DEMO', 'HL2DEMO',
1, 1,
2, 2,
'Server', 'Server',
'Nick', 'Nick',
'cp_gullywash', 'cp_gullywash',
'tf', 'tf',
999999, 999999,
12, 12,
12, 12,
12 12
) )
)); ));
} }
public function testValidateParsedToShortNoRounds() { public function testValidateParsedToShortNoRounds() {
$this->assertEquals('Demos must be at least 5 minutes long', $this->uploadProvider->validateParsed( $this->assertEquals('Demos must be at least 5 minutes long', $this->uploadProvider->validateParsed(
new Header( new Header(
'HL2DEMO', 'HL2DEMO',
1, 1,
2, 2,
'Server', 'Server',
'Nick', 'Nick',
'cp_gullywash', 'cp_gullywash',
'tf', 'tf',
60, 60,
12, 12,
12, 12,
12 12
), ),
new ParsedDemo(0, 0, [], [], []) new ParsedDemo(0, 0, [], [], [])
)); ));
} }
public function testValidateParsedToShortRounds() { public function testValidateParsedToShortRounds() {
$this->assertNull($this->uploadProvider->validateParsed( $this->assertNull($this->uploadProvider->validateParsed(
new Header( new Header(
'HL2DEMO', 'HL2DEMO',
1, 1,
2, 2,
'Server', 'Server',
'Nick', 'Nick',
'cp_gullywash', 'cp_gullywash',
'tf', 'tf',
60, 60,
12, 12,
12, 12,
12 12
), ),
new ParsedDemo(1, 0, [], [], []) new ParsedDemo(1, 0, [], [], [])
)); ));
} }
public function testUploadInvalidKey() { public function testUploadInvalidKey() {
$this->assertEquals('Invalid key', $this->assertEquals(
$this->uploadProvider->upload('asdasd', 'RED', 'BLU', 'asdasd', 'asdas') 'Invalid key',
); $this->uploadProvider->upload('asdasd', 'RED', 'BLU', 'asdasd', 'asdas')
} );
}
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
* @expectedExceptionMessage Not an HL2 demo * @expectedExceptionMessage Not an HL2 demo
*/ */
public function testUploadNonDemo() { public function testUploadNonDemo() {
file_put_contents($this->tmpDir . '/foo.dem', 'asd'); file_put_contents($this->tmpDir . '/foo.dem', 'asd');
$steamId = $this->getSteamId('123', 'a'); $steamId = $this->getSteamId('123', 'a');
$token = $this->userProvider->store($steamId); $token = $this->userProvider->store($steamId);
$this->uploadProvider->upload($token, 'RED', 'BLU', 'asdasd', $this->tmpDir . '/foo.dem'); $this->uploadProvider->upload($token, 'RED', 'BLU', 'asdasd', $this->tmpDir . '/foo.dem');
} }
public function testUploadExisting() { public function testUploadExisting() {
$source = fopen(__DIR__ . '/../data/product.dem', 'r'); $source = fopen(__DIR__ . '/../data/product.dem', 'r');
file_put_contents($this->tmpDir . '/foo.dem', fread($source, 2048)); file_put_contents($this->tmpDir . '/foo.dem', fread($source, 2048));
fclose($source); fclose($source);
$hash = md5_file($this->tmpDir . '/foo.dem'); $hash = md5_file($this->tmpDir . '/foo.dem');
$id = $this->demoProvider->storeDemo( $id = $this->demoProvider->storeDemo(
new Demo( new Demo(
0, 0,
'a', 'a',
'b', 'b',
'c', 'c',
12, 12,
'n', 'n',
'm', 'm',
new \DateTime(), new \DateTime(),
'r', 'r',
'b', 'b',
1, 1,
2, 2,
2, 2,
1, 1,
$hash, $hash,
'b', 'b',
'p' 'p'
), ),
'test', 'test' 'test',
); 'test'
);
$steamId = $this->getSteamId('123', 'a'); $steamId = $this->getSteamId('123', 'a');
$token = $this->userProvider->store($steamId); $token = $this->userProvider->store($steamId);
$this->assertEquals('STV available at: http://example.com/' . $id, $this->assertEquals(
$this->uploadProvider->upload($token, 'RED', 'BLU', 'asdasd', $this->tmpDir . '/foo.dem') 'STV available at: http://example.com/' . $id,
); $this->uploadProvider->upload($token, 'RED', 'BLU', 'asdasd', $this->tmpDir . '/foo.dem')
} );
}
private function saveSteamId($steamId, $name) { private function saveSteamId($steamId, $name) {
$steamId = $this->getSteamId($this->parser->convertSteamIdToCommunityId($steamId), $name); $steamId = $this->getSteamId($this->parser->convertSteamIdToCommunityId($steamId), $name);
$this->userProvider->store($steamId); $this->userProvider->store($steamId);
} }
public function testUpload() { public function testUpload() {
copy(__DIR__ . '/../data/product.dem', $this->tmpDir . '/foo.dem'); copy(__DIR__ . '/../data/product.dem', $this->tmpDir . '/foo.dem');
copy(__DIR__ . '/../data/product-raw.json', $this->tmpDir . '/foo-raw.json'); copy(__DIR__ . '/../data/product-raw.json', $this->tmpDir . '/foo-raw.json');
$steamId = $this->getSteamId('123', 'a'); $steamId = $this->getSteamId('123', 'a');
$token = $this->userProvider->store($steamId); $token = $this->userProvider->store($steamId);
// pre-save the names so we dont have to get them from steam // pre-save the names so we dont have to get them from steam
$this->saveSteamId('[U:1:64229260]', 'Icewind'); $this->saveSteamId('[U:1:64229260]', 'Icewind');
$this->saveSteamId('[U:1:115748435]', 'Foz'); $this->saveSteamId('[U:1:115748435]', 'Foz');
$this->saveSteamId('[U:1:115754284]', 'Deity'); $this->saveSteamId('[U:1:115754284]', 'Deity');
$this->saveSteamId('[U:1:92428736]', 'Kireek'); $this->saveSteamId('[U:1:92428736]', 'Kireek');
$this->saveSteamId('[U:1:22958903]', 'Vinegar'); $this->saveSteamId('[U:1:22958903]', 'Vinegar');
$this->saveSteamId('[U:1:32061783]', 'Kimo'); $this->saveSteamId('[U:1:32061783]', 'Kimo');
$this->saveSteamId('[U:1:67502510]', 'magikarp'); $this->saveSteamId('[U:1:67502510]', 'magikarp');
$this->saveSteamId('[U:1:55128465]', 'Solar'); $this->saveSteamId('[U:1:55128465]', 'Solar');
$this->saveSteamId('[U:1:301587080]', 'ztreak'); $this->saveSteamId('[U:1:301587080]', 'ztreak');
$this->saveSteamId('[U:1:22162172]', 'TheMasterOfDisaster'); $this->saveSteamId('[U:1:22162172]', 'TheMasterOfDisaster');
$this->saveSteamId('[U:1:13559571]', 'Sage'); $this->saveSteamId('[U:1:13559571]', 'Sage');
$this->saveSteamId('[U:1:71706948]', 'Sketis'); $this->saveSteamId('[U:1:71706948]', 'Sketis');
$this->saveSteamId('[U:1:157204170]', 'Pyla'); $this->saveSteamId('[U:1:157204170]', 'Pyla');
$this->saveSteamId('[U:1:30838206]', 'Heavy'); $this->saveSteamId('[U:1:30838206]', 'Heavy');
$this->saveSteamId('[U:1:174774002]', 'Soldier'); $this->saveSteamId('[U:1:174774002]', 'Soldier');
$this->saveSteamId('[U:1:92096346]', 'Fish'); $this->saveSteamId('[U:1:92096346]', 'Fish');
$this->saveSteamId('[U:1:143626373]', 'Pendulum'); $this->saveSteamId('[U:1:143626373]', 'Pendulum');
$this->saveSteamId('[U:1:30220936]', 'Jedi'); $this->saveSteamId('[U:1:30220936]', 'Jedi');
$result = $this->uploadProvider->upload($token, 'RED', 'BLU', 'foodemo', $this->tmpDir . '/foo.dem'); $result = $this->uploadProvider->upload($token, 'RED', 'BLU', 'foodemo', $this->tmpDir . '/foo.dem');
$this->assertStringStartsWith('STV available at: http://example.com/', $result); $this->assertStringStartsWith('STV available at: http://example.com/', $result);
$demoId = (int)substr($result, strlen('STV available at: http://example.com/')); $demoId = (int)substr($result, strlen('STV available at: http://example.com/'));
$demo = $this->demoProvider->get($demoId, true); $demo = $this->demoProvider->get($demoId, true);
$this->assertNotNull($demo); $this->assertNotNull($demo);
$this->assertEquals('koth_product_rc8', $demo->getMap()); $this->assertEquals('koth_product_rc8', $demo->getMap());
$this->assertEquals(0, $demo->getBlueScore()); $this->assertEquals(0, $demo->getBlueScore());
$this->assertEquals(3, $demo->getRedScore()); $this->assertEquals(3, $demo->getRedScore());
} }
} }

View file

@ -6,73 +6,73 @@ use Demostf\API\Providers\UserProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
class UserProviderTest extends TestCase { class UserProviderTest extends TestCase {
/** @var UserProvider */ /** @var UserProvider */
private $provider; private $provider;
/** @var \SteamId */ /** @var \SteamId */
private $steamId; private $steamId;
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->steamId = $this->getSteamId('76561198024494988', 'Icewind'); $this->steamId = $this->getSteamId('76561198024494988', 'Icewind');
$this->provider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator()); $this->provider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator());
} }
public function testGetNonExisting() { public function testGetNonExisting() {
$this->assertNull($this->provider->get('76561198024494988')); $this->assertNull($this->provider->get('76561198024494988'));
} }
public function testStoreRetrieve() { public function testStoreRetrieve() {
$this->provider->store($this->steamId); $this->provider->store($this->steamId);
$user = $this->provider->get('76561198024494988'); $user = $this->provider->get('76561198024494988');
$this->assertEquals($this->steamId->getNickname(), $user->getName()); $this->assertEquals($this->steamId->getNickname(), $user->getName());
$this->assertEquals($this->steamId->getSteamId64(), $user->getSteamId()); $this->assertEquals($this->steamId->getSteamId64(), $user->getSteamId());
} }
public function returnTokenExisting() { public function returnTokenExisting() {
$token1 = $this->provider->store($this->steamId); $token1 = $this->provider->store($this->steamId);
$token2 = $this->provider->store($this->steamId); $token2 = $this->provider->store($this->steamId);
$this->assertEquals($token1, $token2); $this->assertEquals($token1, $token2);
} }
public function testDoubleInsert() { public function testDoubleInsert() {
$this->provider->store($this->steamId); $this->provider->store($this->steamId);
$this->provider->store($this->steamId); $this->provider->store($this->steamId);
$this->assertTrue(true); $this->assertTrue(true);
} }
public function testByKey() { public function testByKey() {
$token = $this->provider->store($this->steamId); $token = $this->provider->store($this->steamId);
$byKey = $this->provider->byKey($token); $byKey = $this->provider->byKey($token);
$this->assertEquals('76561198024494988', $byKey->getSteamId()); $this->assertEquals('76561198024494988', $byKey->getSteamId());
} }
public function testSearch() { public function testSearch() {
$result = $this->provider->search('__NOT__FOUND__'); $result = $this->provider->search('__NOT__FOUND__');
$this->assertCount(0, $result); $this->assertCount(0, $result);
} }
public function testGetIdExisting() { public function testGetIdExisting() {
$this->provider->store($this->steamId); $this->provider->store($this->steamId);
$user = $this->provider->get($this->steamId->getSteamId64()); $user = $this->provider->get($this->steamId->getSteamId64());
$this->assertEquals($user->getId(), $this->provider->getUserId($this->steamId->getSteamId64())); $this->assertEquals($user->getId(), $this->provider->getUserId($this->steamId->getSteamId64()));
} }
public function testGetIdNew() { public function testGetIdNew() {
$id = $this->provider->getUserId($this->steamId->getSteamId64()); $id = $this->provider->getUserId($this->steamId->getSteamId64());
$user = $this->provider->get($this->steamId->getSteamId64()); $user = $this->provider->get($this->steamId->getSteamId64());
$this->assertEquals($user->getId(), $id); $this->assertEquals($user->getId(), $id);
} }
} }

View file

@ -4,63 +4,62 @@ use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\DriverManager;
abstract class TestCase extends \PHPUnit\Framework\TestCase { abstract class TestCase extends \PHPUnit\Framework\TestCase {
/** @var Connection */ /** @var Connection */
private $database; private $database;
protected function getDatabaseConnection() { protected function getDatabaseConnection() {
if (!$this->database instanceof Connection) { if (!$this->database instanceof Connection) {
$connectionParams = array( $connectionParams = [
'dbname' => getenv('DB_DATABASE'), 'dbname' => getenv('DB_DATABASE'),
'user' => getenv('DB_USERNAME'), 'user' => getenv('DB_USERNAME'),
'password' => getenv('DB_PASSWORD'), 'password' => getenv('DB_PASSWORD'),
'host' => getenv('DB_HOST'), 'host' => getenv('DB_HOST'),
'port' => getenv('DB_PORT'), 'port' => getenv('DB_PORT'),
'driver' => getenv('DB_TYPE'), 'driver' => getenv('DB_TYPE'),
); ];
if ($connectionParams['driver'] === 'pgsql') { if ($connectionParams['driver'] === 'pgsql') {
$connectionParams['driver'] = 'pdo_pgsql'; $connectionParams['driver'] = 'pdo_pgsql';
} }
$this->database = DriverManager::getConnection($connectionParams); $this->database = DriverManager::getConnection($connectionParams);
} }
return $this->database; return $this->database;
} }
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
} }
public function tearDown() { public function tearDown() {
$this->clearDatabase(); $this->clearDatabase();
parent::tearDown(); parent::tearDown();
} }
private function clearDatabase() { private function clearDatabase() {
if ($this->database instanceof Connection) { if ($this->database instanceof Connection) {
$tables = $this->database->getSchemaManager()->listTables(); $tables = $this->database->getSchemaManager()->listTables();
foreach ($tables as $table) { foreach ($tables as $table) {
$this->truncateTable($table->getName()); $this->truncateTable($table->getName());
} }
} }
} }
private function truncateTable(string $tableName) { private function truncateTable(string $tableName) {
$sql = sprintf('TRUNCATE TABLE %s;', $tableName); $sql = sprintf('TRUNCATE TABLE %s;', $tableName);
$this->getDatabaseConnection()->query($sql); $this->getDatabaseConnection()->query($sql);
} }
protected function getRandomGenerator() { protected function getRandomGenerator() {
$factory = new \RandomLib\Factory; $factory = new \RandomLib\Factory;
return $factory->getMediumStrengthGenerator(); return $factory->getMediumStrengthGenerator();
} }
protected function getSteamId($steamId, $name) {
$steamId = new \SteamId($steamId, false);
$closure = \Closure::bind(function ($steamId) use ($name) {
$steamId->nickname = $name;
$steamId->imageUrl = 'foo';
}, null, $steamId);
$closure($steamId);
return $steamId;
}
protected function getSteamId($steamId, $name) {
$steamId = new \SteamId($steamId, false);
$closure = \Closure::bind(function ($steamId) use ($name) {
$steamId->nickname = $name;
$steamId->imageUrl = 'foo';
}, null, $steamId);
$closure($steamId);
return $steamId;
}
} }

View file

@ -3,41 +3,41 @@
$_SERVER['SCRIPT_NAME'] = ''; $_SERVER['SCRIPT_NAME'] = '';
if ($_SERVER["REQUEST_URI"] === '/upload') { if ($_SERVER["REQUEST_URI"] === '/upload') {
require __DIR__ . '/../src/public/upload.php'; require __DIR__ . '/../src/public/upload.php';
} else if ($_SERVER["REQUEST_URI"] === '/reset') { } elseif ($_SERVER["REQUEST_URI"] === '/reset') {
// allow the api tests to reset the database // allow the api tests to reset the database
/** @var \Demostf\API\Container $container */ /** @var \Demostf\API\Container $container */
$container = require __DIR__ . '/../src/init.php'; $container = require __DIR__ . '/../src/init.php';
$connection = $container->getConnection(); $connection = $container->getConnection();
clearDatabase($connection); clearDatabase($connection);
} else if ($_SERVER["REQUEST_URI"] === '/testuser') { } elseif ($_SERVER["REQUEST_URI"] === '/testuser') {
// allow the api tests to create a test user // allow the api tests to create a test user
/** @var \Demostf\API\Container $container */ /** @var \Demostf\API\Container $container */
$container = require __DIR__ . '/../src/init.php'; $container = require __DIR__ . '/../src/init.php';
$connection = $container->getConnection(); $connection = $container->getConnection();
$query = $connection->createQueryBuilder(); $query = $connection->createQueryBuilder();
$query->insert('users') $query->insert('users')
->values([ ->values([
'steamid' => $query->createNamedParameter('steamid1'), 'steamid' => $query->createNamedParameter('steamid1'),
'name' => $query->createNamedParameter('nickname1'), 'name' => $query->createNamedParameter('nickname1'),
'avatar' => $query->createNamedParameter('avatar1'), 'avatar' => $query->createNamedParameter('avatar1'),
'token' => $query->createNamedParameter('key1') 'token' => $query->createNamedParameter('key1')
])->add('orderBy', 'ON CONFLICT DO NOTHING')// hack to append arbitrary string to sql ])->add('orderBy', 'ON CONFLICT DO NOTHING')// hack to append arbitrary string to sql
->execute(); ->execute();
} else { } else {
require __DIR__ . '/../src/public/index.php'; require __DIR__ . '/../src/public/index.php';
} }
function clearDatabase(\Doctrine\DBAL\Connection $connection) { function clearDatabase(\Doctrine\DBAL\Connection $connection) {
$tables = $connection->getSchemaManager()->listTables(); $tables = $connection->getSchemaManager()->listTables();
foreach ($tables as $table) { foreach ($tables as $table) {
truncateTable($connection, $table->getName()); truncateTable($connection, $table->getName());
} }
} }
function truncateTable(\Doctrine\DBAL\Connection $connection, string $tableName) { function truncateTable(\Doctrine\DBAL\Connection $connection, string $tableName) {
$sql = sprintf('TRUNCATE TABLE %s;', $tableName); $sql = sprintf('TRUNCATE TABLE %s;', $tableName);
$connection->query($sql); $connection->query($sql);
} }