Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ composer: ## Install PHP dependencies
cache: ## Clear Symfony cache
@docker compose exec php bin/console c:c

test-build:
@$(TEST_COMPOSE) build
test: ## Run PHPUnit tests (isolated test containers)
@echo "Starting test containers..."
@$(TEST_COMPOSE) up -d --build --wait
@$(TEST_COMPOSE) up -d
@echo "Setting up test database..."
@$(TEST_COMPOSE) exec php bin/console d:d:c -n --if-not-exists
@$(TEST_COMPOSE) exec php bin/console d:m:m -n
Expand All @@ -55,7 +57,7 @@ test: ## Run PHPUnit tests (isolated test containers)
@$(TEST_COMPOSE) down

test-up: ## Start test containers (keep running)
@$(TEST_COMPOSE) up -d --build --wait
@$(TEST_COMPOSE) up -d
@$(TEST_COMPOSE) exec php bin/console d:d:c -n --if-not-exists
@$(TEST_COMPOSE) exec php bin/console d:m:m -n
@$(TEST_COMPOSE) exec php bin/console app:populate:users -n
Expand Down Expand Up @@ -90,7 +92,7 @@ coverage-text: ## Show code coverage in terminal
@$(TEST_COMPOSE) up -d --build --wait
@$(TEST_COMPOSE) exec php bin/console d:d:c -n --if-not-exists
@$(TEST_COMPOSE) exec php bin/console d:m:m -n
@$(TEST_COMPOSE) exec php bin/console app:populate:users -n
@$(TEST_COMPOSE) exec php bin/console app:populate:users -n 1 -f Test -l User
@$(TEST_COMPOSE) exec php bin/console app:populate:capitals --purge -n
@$(TEST_COMPOSE) exec php bin/console app:populate:flags --purge -n
@$(TEST_COMPOSE) exec php php -d pcov.enabled=1 vendor/bin/phpunit --coverage-text
Expand All @@ -103,7 +105,7 @@ qa: ## Run full quality assurance pipeline CS-FIXER PSALM PHPUNIT
@$(TEST_COMPOSE) up -d --build --wait
@$(TEST_COMPOSE) exec php bin/console d:d:c -n --if-not-exists
@$(TEST_COMPOSE) exec php bin/console d:m:m -n
@$(TEST_COMPOSE) exec php bin/console app:populate:users -n
@$(TEST_COMPOSE) exec php bin/console app:populate:users -n 1 -f Test -l User
@$(TEST_COMPOSE) exec php bin/console app:populate:capitals --purge -n
@$(TEST_COMPOSE) exec php bin/console app:populate:flags --purge -n
@echo ""
Expand All @@ -127,6 +129,9 @@ pipeline: qa ## Alias for qa (run full pipeline like GitHub Actions)
psalm: ## Run Psalm static analysis
@docker compose exec php vendor/bin/psalm --no-cache

psalm-baseline-update: ## Update baseline file (new errors will not be added)
@docker compose exec php vendor/bin/psalm --no-cache --update-baseline

cs-fix: ## Fix code style (PHP CS Fixer + PHPCS)
@echo "Fixing code style with PHP CS Fixer..."
@docker compose exec php vendor/bin/php-cs-fixer fix
Expand Down
8 changes: 0 additions & 8 deletions app/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@
<code><![CDATA[$date]]></code>
</PossiblyUnusedProperty>
</file>
<file src="src/Flags/Entity/Answer.php">
</file>
<file src="src/Flags/Entity/Capital.php">
<PossiblyUnusedMethod>
<code><![CDATA[getId]]></code>
Expand Down Expand Up @@ -129,8 +127,6 @@
<code><![CDATA[$user]]></code>
</UnusedProperty>
</file>
<file src="src/Flags/Entity/Score.php">
</file>
<file src="src/Flags/Entity/User.php">
<MissingOverrideAttribute>
<code><![CDATA[public function eraseCredentials()]]></code>
Expand Down Expand Up @@ -180,7 +176,6 @@
<file src="src/Flags/Repository/CapitalsStatRepository.php">
<PossiblyUnusedMethod>
<code><![CDATA[__construct]]></code>
<code><![CDATA[getHighScores]]></code>
<code><![CDATA[getHighScores2]]></code>
<code><![CDATA[getHighScores3]]></code>
</PossiblyUnusedMethod>
Expand Down Expand Up @@ -218,7 +213,6 @@
<file src="src/Flags/Repository/UserRepository.php">
<PossiblyUnusedMethod>
<code><![CDATA[__construct]]></code>
<code><![CDATA[getAnyUser]]></code>
</PossiblyUnusedMethod>
<PossiblyUnusedParam>
<code><![CDATA[$registry]]></code>
Expand All @@ -228,8 +222,6 @@
<file src="src/Flags/Security/HqAuthAuthenticator.php">
<MissingOverrideAttribute>
<code><![CDATA[public function authenticate(Request $request): Passport]]></code>
<code><![CDATA[public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response]]></code>
<code><![CDATA[public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response]]></code>
<code><![CDATA[public function supports(Request $request): ?bool]]></code>
</MissingOverrideAttribute>
<UnusedClass>
Expand Down
18 changes: 16 additions & 2 deletions app/src/Flags/ConsoleCommand/SetWebhookCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class SetWebhookCommand extends Command
Expand Down Expand Up @@ -41,12 +45,22 @@ protected function configure()
;
}

/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$arg1 = $input->getArgument('arg1');
// $r = $this->client->request(Request::METHOD_GET, 'https://api.telegram.org/bot' . $this->botToken . '/setWebhook?url=' . $arg1);
$r = $this->client->request(Request::METHOD_GET, 'https://api.telegram.org/bot' . $this->botToken . '/setWebhook?url=' . $arg1);
// $r = $this->client->request(
// Request::METHOD_GET, 'https://api.telegram.org/bot' . $this->botToken . '/setWebhook?url=' . $arg1);
$r = $this->client->request(
Request::METHOD_GET,
'https://api.telegram.org/bot' . $this->botToken . '/setWebhook?url=' . $arg1,
);
if ($arg1) {
$io->note(sprintf('You passed an argument: %s', $arg1));
}
Expand Down
8 changes: 6 additions & 2 deletions app/src/Flags/Controller/CapitalsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ public function gameOver(Request $request, CapitalsGameService $service): JsonRe
}

#[Route('/capitals/answer/{game}/{countryCode}/{answer}', name: 'get_question_for_game', methods: ['GET'])]
public function getQuestion(Game $game, string $countryCode, string $answer, CapitalsGameService $service): JsonResponse
{
public function getQuestion(
Game $game,
string $countryCode,
string $answer,
CapitalsGameService $service,
): JsonResponse {
return $this->json($service->giveAnswer($countryCode, base64_decode($answer), $game));
}

Expand Down
7 changes: 5 additions & 2 deletions app/src/Flags/Controller/FlagsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,11 @@ public function getHighScores(UserRepository $repository): Response
* @throws \JsonException
*/
#[Route('/scores', name: 'submit_game_results', methods: ['POST'])]
public function postScore(Request $request, EntityManagerInterface $entityManager, #[CurrentUser] User $user): Response
{
public function postScore(
Request $request,
EntityManagerInterface $entityManager,
#[CurrentUser] User $user,
): Response {
$requestArray = json_decode($request->getContent(), true, 512, JSON_THROW_ON_ERROR);
$scoreDTO = new ScoreDTO($requestArray);
$score = new Score()->fromDTO($scoreDTO);
Expand Down
5 changes: 3 additions & 2 deletions app/src/Flags/Entity/CapitalsStat.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
namespace App\Flags\Entity;

use App\Flags\Entity\Enum\GameType;
use App\Flags\Repository\CapitalsStatRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: "App\Flags\Repository\CapitalsStatRepository")]
#[ORM\Entity(repositoryClass: CapitalsStatRepository::class)]
class CapitalsStat
{
#[ORM\Id]
Expand All @@ -19,7 +20,7 @@ class CapitalsStat
#[ORM\Column(type: 'integer', length: 255)]
protected int $score;

#[ORM\ManyToOne(targetEntity: "App\Flags\Entity\User")]
#[ORM\ManyToOne(targetEntity: User::class)]
protected readonly User $user;

#[ORM\Column(type: 'string', length: 255)]
Expand Down
38 changes: 6 additions & 32 deletions app/src/Flags/Repository/AnswerRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public function __construct(ManagerRegistry $registry)

public function findIncorrectGuesses(string $userId): array
{
// SELECT COUNT(answer.flag_code) as incorrect, answer.flag_code FROM answer WHERE answer.user_id = 6 AND answer.correct = 0
// SELECT COUNT(answer.flag_code) as incorrect,
// answer.flag_code FROM answer WHERE answer.user_id = 6 AND answer.correct = 0
// GROUP BY answer.flag_code ORDER BY incorrect DESC;

return $this->createQueryBuilder('a')
Expand All @@ -41,7 +42,8 @@ public function findIncorrectGuesses(string $userId): array

public function findCorrectGuesses(string $userId): array
{
// SELECT COUNT(answer.flag_code) as incorrect, answer.flag_code FROM answer WHERE answer.user_id = 6 AND answer.correct = 0
// SELECT COUNT(answer.flag_code) as incorrect,
// answer.flag_code FROM answer WHERE answer.user_id = 6 AND answer.correct = 0
// GROUP BY answer.flag_code ORDER BY incorrect DESC;

return $this->createQueryBuilder('a')
Expand All @@ -60,7 +62,8 @@ public function findCorrectGuesses(string $userId): array

public function findAllGuesses(string $userId): array
{
// SELECT COUNT(answer.flag_code) as incorrect, answer.flag_code FROM answer WHERE answer.user_id = 6 AND answer.correct = 0
// SELECT COUNT(answer.flag_code) as incorrect,
// answer.flag_code FROM answer WHERE answer.user_id = 6 AND answer.correct = 0
// GROUP BY answer.flag_code ORDER BY incorrect DESC;

return $this->createQueryBuilder('a')
Expand All @@ -74,33 +77,4 @@ public function findAllGuesses(string $userId): array
->getArrayResult()
;
}

// /**
// * @return Flag[] Returns an array of Flag objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('f')
->andWhere('f.exampleField = :val')
->setParameter('val', $value)
->orderBy('f.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/

/*
public function findOneBySomeField($value): ?Flag
{
return $this->createQueryBuilder('f')
->andWhere('f.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
31 changes: 5 additions & 26 deletions app/src/Flags/Repository/GameRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Flags\Entity\Game;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\EntityNotFoundException;
use Doctrine\Persistence\ManagerRegistry;

/**
Expand All @@ -19,32 +20,10 @@ public function __construct(ManagerRegistry $registry)
parent::__construct($registry, Game::class);
}

// /**
// * @return Game[] Returns an array of Game objects
// */
/*
public function findByExampleField($value)
/** @psalm-suppress PossiblyUnusedParam */
public function getById(int $id): Game
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->orderBy('g.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
return $this->findOneBy(['id' => $id])
?? throw EntityNotFoundException::fromClassNameAndIdentifier(className: Game::class, id: [$id]);
}
*/

/*
public function findOneBySomeField($value): ?Game
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
48 changes: 3 additions & 45 deletions app/src/Flags/Repository/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use App\Flags\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Persistence\ManagerRegistry;
use League\OAuth2\Client\Provider\GenericResourceOwner;
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
Expand All @@ -13,6 +12,7 @@
/**
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User[] findAll()
* @method User|null findOneBy(array $criteria)
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository implements UserLoaderInterface
Expand All @@ -22,7 +22,7 @@ public function __construct(ManagerRegistry $registry)
parent::__construct($registry, User::class);
}

public function getHighScores()
public function getHighScores(): array
{
return $this->createQueryBuilder('u')
->select('u.firstName')
Expand All @@ -32,53 +32,11 @@ public function getHighScores()
->addSelect('u.gamesTotal')
->addOrderBy('u.highScore', 'DESC')
->addOrderBy('u.bestTime', 'ASC')
->setMaxResults(5)
->getQuery()
->getScalarResult()
;
}

public function getAnyUser(): User
{
return $this->matching(
($criteria = new Criteria())
->where(
$criteria
->expr()
->gt('id', 0)
)
->setMaxResults(1)
)->get(0);
}

// /**
// * @return User[] Returns an array of User objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('u')
->andWhere('u.exampleField = :val')
->setParameter('val', $value)
->orderBy('u.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/

/*
public function findOneBySomeField($value): ?User
{
return $this->createQueryBuilder('u')
->andWhere('u.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
->getScalarResult()
;
}
*/

public function loadUserByIdentifier(string $identifier): ?UserInterface
{
Expand Down
Loading