Skip to content

Fix issues reported by PHPStan #1334 #1370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 2, 2022
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
457 changes: 0 additions & 457 deletions phpstan-baseline.neon

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
includes:
- phpstan-baseline.neon

parameters:
level: max
paths:
Expand Down
12 changes: 11 additions & 1 deletion src/Command/AddUserCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ protected function interact(InputInterface $input, OutputInterface $output): voi
}

// Ask for the password if it's not defined
/** @var string|null $password */
$password = $input->getArgument('password');

if (null !== $password) {
$this->io->text(' > <info>Password</info>: '.u('*')->repeat(u($password)->length()));
} else {
Expand Down Expand Up @@ -165,10 +167,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$stopwatch = new Stopwatch();
$stopwatch->start('add-user-command');

/** @var string $username */
$username = $input->getArgument('username');

/** @var string $plainPassword */
$plainPassword = $input->getArgument('password');

/** @var string $email */
$email = $input->getArgument('email');

/** @var string $fullName */
$fullName = $input->getArgument('full-name');

$isAdmin = $input->getOption('admin');

// make sure to validate the user data is correct
Expand Down Expand Up @@ -198,7 +208,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return Command::SUCCESS;
}

private function validateUserData($username, $plainPassword, $email, $fullName): void
private function validateUserData(string $username, string $plainPassword, string $email, string $fullName): void
{
// first check if a user with the same username already exists.
$existingUser = $this->users->findOneBy(['username' => $username]);
Expand Down
4 changes: 3 additions & 1 deletion src/Command/DeleteUserCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ protected function interact(InputInterface $input, OutputInterface $output): voi

protected function execute(InputInterface $input, OutputInterface $output): int
{
$username = $this->validator->validateUsername($input->getArgument('username'));
/** @var string|null $username */
$username = $input->getArgument('username');
$username = $this->validator->validateUsername($username);

/** @var User|null $user */
$user = $this->users->findOneByUsername($username);
Expand Down
16 changes: 12 additions & 4 deletions src/Command/ListUsersCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,25 @@ protected function configure(): void
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
/** @var int|null $maxResults */
$maxResults = $input->getOption('max-results');

// Use ->findBy() instead of ->findAll() to allow result sorting and limiting
$allUsers = $this->users->findBy([], ['id' => 'DESC'], $maxResults);

// Doctrine query returns an array of objects and we need an array of plain arrays
$usersAsPlainArrays = array_map(static function (User $user) {
$createUserArray = static function (User $user) {
return [
$user->getId(),
$user->getFullName(),
$user->getUsername(),
$user->getEmail(),
implode(', ', $user->getRoles()),
];
}, $allUsers);
};

// Doctrine query returns an array of objects, and we need an array of plain arrays
/** @var callable $createUserArray */
$usersAsPlainArrays = array_map($createUserArray, $allUsers);

// In your console commands you should always use the regular output type,
// which outputs contents directly in the console window. However, this
Expand All @@ -119,7 +124,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$usersAsATable = $bufferedOutput->fetch();
$output->write($usersAsATable);

if (null !== $email = $input->getOption('send-to')) {
/** @var string $email */
$email = $input->getOption('send-to');

if (null !== $email) {
$this->sendReport($usersAsATable, $email);
}

Expand Down
14 changes: 11 additions & 3 deletions src/Controller/Admin/BlogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\SubmitButton;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
Expand Down Expand Up @@ -80,7 +81,8 @@ public function new(

// See https://symfony.com/doc/current/form/multiple_buttons.html
$form = $this->createForm(PostType::class, $post)
->add('saveAndCreateNew', SubmitType::class);
->add('saveAndCreateNew', SubmitType::class)
;

$form->handleRequest($request);

Expand All @@ -98,7 +100,10 @@ public function new(
// See https://symfony.com/doc/current/controller.html#flash-messages
$this->addFlash('success', 'post.created_successfully');

if ($form->get('saveAndCreateNew')->isClicked()) {
/** @var SubmitButton $submit */
$submit = $form->get('saveAndCreateNew');

if ($submit->isClicked()) {
return $this->redirectToRoute('admin_post_new');
}

Expand Down Expand Up @@ -156,7 +161,10 @@ public function edit(Request $request, Post $post, EntityManagerInterface $entit
#[IsGranted('delete', subject: 'post')]
public function delete(Request $request, Post $post, EntityManagerInterface $entityManager): Response
{
if (!$this->isCsrfTokenValid('delete', $request->request->get('token'))) {
/** @var string|null $token */
$token = $request->request->get('token');

if (!$this->isCsrfTokenValid('delete', $token)) {
return $this->redirectToRoute('admin_post_index');
}

Expand Down
21 changes: 16 additions & 5 deletions src/Controller/BlogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use App\Entity\Comment;
use App\Entity\Post;
use App\Entity\Tag;
use App\Entity\User;
use App\Event\CommentCreatedEvent;
use App\Form\CommentType;
Expand Down Expand Up @@ -52,6 +53,7 @@ public function index(Request $request, int $page, string $_format, PostReposito
{
$tag = null;
if ($request->query->has('tag')) {
/** @var Tag $tag */
$tag = $tags->findOneBy(['name' => $request->query->get('tag')]);
}
$latestPosts = $posts->findLatest($page, $tag);
Expand Down Expand Up @@ -155,8 +157,8 @@ public function commentForm(Post $post): Response
#[Route('/search', methods: ['GET'], name: 'blog_search')]
public function search(Request $request, PostRepository $posts): Response
{
$query = $request->query->get('q', '');
$limit = $request->query->get('l', 10);
$query = (string) $request->query->get('q', '');
$limit = (int) $request->query->get('l', 10);

if (!$request->isXmlHttpRequest()) {
return $this->render('blog/search.html.twig', ['query' => $query]);
Expand All @@ -166,11 +168,20 @@ public function search(Request $request, PostRepository $posts): Response

$results = [];
foreach ($foundPosts as $post) {
/** @var string $author */
$author = $post->getAuthor() ? $post->getAuthor()->getFullName() : '';

/** @var string $title */
$title = $post->getTitle();

/** @var string $summary */
$summary = $post->getSummary();

$results[] = [
'title' => htmlspecialchars($post->getTitle(), \ENT_COMPAT | \ENT_HTML5),
'title' => htmlspecialchars($title, \ENT_COMPAT | \ENT_HTML5),
'date' => $post->getPublishedAt()->format('M d, Y'),
'author' => htmlspecialchars($post->getAuthor()->getFullName(), \ENT_COMPAT | \ENT_HTML5),
'summary' => htmlspecialchars($post->getSummary(), \ENT_COMPAT | \ENT_HTML5),
'author' => htmlspecialchars($author, \ENT_COMPAT | \ENT_HTML5),
'summary' => htmlspecialchars($summary, \ENT_COMPAT | \ENT_HTML5),
'url' => $this->generateUrl('blog_post', ['slug' => $post->getSlug()]),
];
}
Expand Down
5 changes: 4 additions & 1 deletion src/Controller/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ public function changePassword(
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$user->setPassword($passwordHasher->hashPassword($user, $form->get('newPassword')->getData()));
/** @var string $plainPassword */
$plainPassword = $form->get('newPassword')->getData();

$user->setPassword($passwordHasher->hashPassword($user, $plainPassword));
$entityManager->flush();

return $this->redirectToRoute('security_logout');
Expand Down
27 changes: 26 additions & 1 deletion src/DataFixtures/AppFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\String\AbstractUnicodeString;
use Symfony\Component\String\Slugger\SluggerInterface;
use function Symfony\Component\String\u;

Expand Down Expand Up @@ -67,6 +68,8 @@ private function loadTags(ObjectManager $manager): void

private function loadPosts(ObjectManager $manager): void
{
/** @var User $author */
/** @var array<Tag> $tags */
foreach ($this->getPostData() as [$title, $slug, $summary, $content, $publishedAt, $author, $tags]) {
$post = new Post();
$post->setTitle($title);
Expand All @@ -78,8 +81,11 @@ private function loadPosts(ObjectManager $manager): void
$post->addTag(...$tags);

foreach (range(1, 5) as $i) {
/** @var User $commentAuthor */
$commentAuthor = $this->getReference('john_user');

$comment = new Comment();
$comment->setAuthor($this->getReference('john_user'));
$comment->setAuthor($commentAuthor);
$comment->setContent($this->getRandomText(random_int(255, 512)));
$comment->setPublishedAt(new \DateTime('now + '.$i.'seconds'));

Expand All @@ -92,6 +98,9 @@ private function loadPosts(ObjectManager $manager): void
$manager->flush();
}

/**
* @return array<array{string, string, string, string, array<string>}>
*/
private function getUserData(): array
{
return [
Expand All @@ -102,6 +111,9 @@ private function getUserData(): array
];
}

/**
* @return string[]
*/
private function getTagData(): array
{
return [
Expand All @@ -117,6 +129,11 @@ private function getTagData(): array
];
}

/**
* @throws \Exception
*
* @return array<int, array{0: string, 1: AbstractUnicodeString, 2: string, 3: string, 4: \DateTime, 5: object, 6: array<object>}>
*/
private function getPostData(): array
{
$posts = [];
Expand All @@ -137,6 +154,9 @@ private function getPostData(): array
return $posts;
}

/**
* @return string[]
*/
private function getPhrases(): array
{
return [
Expand Down Expand Up @@ -226,6 +246,11 @@ private function getPostContent(): string
MARKDOWN;
}

/**
* @throws \Exception
*
* @return array<object>
*/
private function getRandomTags(): array
{
$tagNames = $this->getTagData();
Expand Down
10 changes: 8 additions & 2 deletions src/Entity/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ class Post
private ?User $author = null;

/**
* @var Comment[]|Collection
* @var Collection<int, Comment>
*/
#[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'post', orphanRemoval: true, cascade: ['persist'])]
#[ORM\OrderBy(['publishedAt' => 'DESC'])]
private Collection $comments;

/**
* @var Tag[]|Collection
* @var Collection<int, Tag>
*/
#[ORM\ManyToMany(targetEntity: Tag::class, cascade: ['persist'])]
#[ORM\JoinTable(name: 'symfony_demo_post_tag')]
Expand Down Expand Up @@ -143,6 +143,9 @@ public function setAuthor(User $author): void
$this->author = $author;
}

/**
* @return Collection<int, Comment>
*/
public function getComments(): Collection
{
return $this->comments;
Expand Down Expand Up @@ -185,6 +188,9 @@ public function removeTag(Tag $tag): void
$this->tags->removeElement($tag);
}

/**
* @return Collection<int, Tag>
*/
public function getTags(): Collection
{
return $this->tags;
Expand Down
14 changes: 13 additions & 1 deletion src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\Column(type: Types::STRING)]
private ?string $password = null;

/**
* @var string[]
*/
#[ORM\Column(type: Types::JSON)]
private array $roles = [];

Expand All @@ -73,7 +76,7 @@ public function getFullName(): ?string

public function getUserIdentifier(): string
{
return $this->username;
return (string) $this->username;
}

public function getUsername(): string
Expand Down Expand Up @@ -121,6 +124,9 @@ public function getRoles(): array
return array_unique($roles);
}

/**
* @param string[] $roles
*/
public function setRoles(array $roles): void
{
$this->roles = $roles;
Expand Down Expand Up @@ -151,12 +157,18 @@ public function eraseCredentials(): void
// $this->plainPassword = null;
}

/**
* @return array{int|null, string|null, string|null}
*/
public function __serialize(): array
{
// add $this->salt too if you don't use Bcrypt or Argon2i
return [$this->id, $this->username, $this->password];
}

/**
* @param array{int|null, string, string} $data
*/
public function __unserialize(array $data): void
{
// add $this->salt too if you don't use Bcrypt or Argon2i
Expand Down
3 changes: 2 additions & 1 deletion src/EventSubscriber/CheckRequirementsSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace App\EventSubscriber;

use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
Expand Down Expand Up @@ -94,6 +95,6 @@ private function isSQLitePlatform(): bool
{
$databasePlatform = $this->entityManager->getConnection()->getDatabasePlatform();

return $databasePlatform ? 'sqlite' === $databasePlatform->getName() : false;
return $databasePlatform instanceof SqlitePlatform;
}
}
Loading