diff --git a/phpstan.neon b/phpstan.neon index 583608043..7109cb5b4 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,7 +5,6 @@ includes: parameters: level: 8 - checkGenericClassInNonGenericObjectType: false checkMissingIterableValueType: false paths: diff --git a/src/Acl.php b/src/Acl.php index d0d332cea..157687845 100644 --- a/src/Acl.php +++ b/src/Acl.php @@ -135,8 +135,10 @@ class Acl $numRoles = $user->getRoles()->count(); if ($numRoles > 0) { if ($numRoles === 1) { + /** @var Entity\Role $role */ $role = $user->getRoles()->first(); - return $this->roleAllowed($role->getId(), $action, $stationId); + + return $this->roleAllowed($role->getIdRequired(), $action, $stationId); } $roles = []; diff --git a/src/Controller/Api/Admin/Stations/CloneAction.php b/src/Controller/Api/Admin/Stations/CloneAction.php index e123f3b37..8a0153709 100644 --- a/src/Controller/Api/Admin/Stations/CloneAction.php +++ b/src/Controller/Api/Admin/Stations/CloneAction.php @@ -222,6 +222,9 @@ final class CloneAction extends StationsController return $response->withJson(Entity\Api\Status::created()); } + /** + * @param Collection $collection + */ private function cloneCollection( Collection $collection, Entity\Station $newStation, diff --git a/src/Controller/Api/Stations/Files/ListAction.php b/src/Controller/Api/Stations/Files/ListAction.php index d7d3345d7..6433e8c66 100644 --- a/src/Controller/Api/Stations/Files/ListAction.php +++ b/src/Controller/Api/Stations/Files/ListAction.php @@ -331,6 +331,7 @@ final class ListAction } ); + /** @var array $result */ $paginator = Paginator::fromArray($result, $request); // Add processor-intensive data for just this page. diff --git a/src/Doctrine/Event/AuditLog.php b/src/Doctrine/Event/AuditLog.php index d3f024690..6c0c05059 100644 --- a/src/Doctrine/Event/AuditLog.php +++ b/src/Doctrine/Event/AuditLog.php @@ -136,8 +136,8 @@ class AuditLog implements EventSubscriber $associated = []; $disassociated = []; + /** @var PersistentCollection $collection */ foreach ($uow->getScheduledCollectionUpdates() as $collection) { - /** @var PersistentCollection $collection */ $owner = $collection->getOwner(); if (null === $owner) { @@ -180,8 +180,8 @@ class AuditLog implements EventSubscriber } } + /** @var PersistentCollection $collection */ foreach ($uow->getScheduledCollectionDeletions() as $collection) { - /** @var PersistentCollection $collection */ $owner = $collection->getOwner(); if (null === $owner) { @@ -259,6 +259,11 @@ class AuditLog implements EventSubscriber return !$em->getMetadataFactory()->isTransient($class); } + /** + * @template TObject of object + * @param ReflectionClass $refl + * @return bool + */ protected function isAuditable(ReflectionClass $refl): bool { $auditable = $refl->getAttributes(Auditable::class); diff --git a/src/Doctrine/Repository.php b/src/Doctrine/Repository.php index e3b126f5e..185aa6a6f 100644 --- a/src/Doctrine/Repository.php +++ b/src/Doctrine/Repository.php @@ -33,6 +33,9 @@ class Repository } } + /** + * @return ObjectRepository + */ public function getRepository(): ObjectRepository { return $this->repository; diff --git a/src/Entity/Fixture/User.php b/src/Entity/Fixture/User.php index a03632dc9..3b8bcac26 100644 --- a/src/Entity/Fixture/User.php +++ b/src/Entity/Fixture/User.php @@ -21,7 +21,11 @@ class User extends AbstractFixture implements DependentFixtureInterface $demo_user->setEmail('demo@azuracast.com'); $demo_user->setNewPassword('demo'); $demo_user->setName('AzuraCast Demo User'); - $demo_user->getRoles()->add($this->getReference('demo_role')); + + /** @var Entity\Role $demoRole */ + $demoRole = $this->getReference('demo_role'); + $demo_user->getRoles()->add($demoRole); + $manager->persist($demo_user); $this->addReference('demo_user', $demo_user); @@ -32,7 +36,9 @@ class User extends AbstractFixture implements DependentFixtureInterface $admin_user->setNewPassword($admin_password); $admin_user->setTheme('dark'); - $admin_user->getRoles()->add($this->getReference('admin_role')); + /** @var Entity\Role $adminRole */ + $adminRole = $this->getReference('admin_role'); + $admin_user->getRoles()->add($adminRole); $admin_2fa_secret = getenv('INIT_ADMIN_2FA_SECRET'); if (!empty($admin_2fa_secret)) { diff --git a/src/Entity/Podcast.php b/src/Entity/Podcast.php index a05afd98e..8948b272f 100644 --- a/src/Entity/Podcast.php +++ b/src/Entity/Podcast.php @@ -51,9 +51,11 @@ class Podcast implements Interfaces\IdentifiableEntityInterface #[Attributes\AuditIgnore] protected int $art_updated_at = 0; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'podcast', targetEntity: PodcastCategory::class)] protected Collection $categories; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'podcast', targetEntity: PodcastEpisode::class)] protected Collection $episodes; @@ -155,7 +157,7 @@ class Podcast implements Interfaces\IdentifiableEntityInterface } /** - * @return Collection|PodcastCategory[] + * @return Collection */ public function getCategories(): Collection { @@ -163,7 +165,7 @@ class Podcast implements Interfaces\IdentifiableEntityInterface } /** - * @return Collection|PodcastEpisode[] + * @return Collection */ public function getEpisodes(): Collection { diff --git a/src/Entity/Relay.php b/src/Entity/Relay.php index 112199f7a..5c8bb9d18 100644 --- a/src/Entity/Relay.php +++ b/src/Entity/Relay.php @@ -55,6 +55,7 @@ class Relay implements IdentifiableEntityInterface ] protected int $updated_at; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'relay', targetEntity: StationRemote::class)] protected Collection $remotes; @@ -129,6 +130,9 @@ class Relay implements IdentifiableEntityInterface $this->updated_at = $updated_at; } + /** + * @return Collection + */ public function getRemotes(): Collection { return $this->remotes; diff --git a/src/Entity/Role.php b/src/Entity/Role.php index 678217bf9..3b54d7e4f 100644 --- a/src/Entity/Role.php +++ b/src/Entity/Role.php @@ -31,9 +31,11 @@ class Role implements JsonSerializable, Stringable, IdentifiableEntityInterface ] protected string $name; + /** @var Collection */ #[ORM\ManyToMany(targetEntity: User::class, mappedBy: 'roles')] protected Collection $users; + /** @var Collection */ #[ OA\Property(type: "array", items: new OA\Items()), ORM\OneToMany(mappedBy: 'role', targetEntity: RolePermission::class) @@ -56,11 +58,17 @@ class Role implements JsonSerializable, Stringable, IdentifiableEntityInterface $this->name = $this->truncateString($name, 100); } + /** + * @return Collection + */ public function getUsers(): Collection { return $this->users; } + /** + * @return Collection + */ public function getPermissions(): Collection { return $this->permissions; diff --git a/src/Entity/Station.php b/src/Entity/Station.php index 15a3fb181..be1754f9a 100644 --- a/src/Entity/Station.php +++ b/src/Entity/Station.php @@ -303,6 +303,7 @@ class Station implements Stringable, IdentifiableEntityInterface ] protected ?string $default_album_art_url = null; + /** @var Collection */ #[ ORM\OneToMany(mappedBy: 'station', targetEntity: SongHistory::class), ORM\OrderBy(['timestamp_start' => 'desc']) @@ -351,6 +352,7 @@ class Station implements Stringable, IdentifiableEntityInterface ] protected ?StorageLocation $podcasts_storage_location = null; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'station', targetEntity: StationStreamer::class)] protected Collection $streamers; @@ -366,21 +368,26 @@ class Station implements Stringable, IdentifiableEntityInterface #[ORM\Column(length: 255, nullable: true)] protected ?string $fallback_path = null; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'station', targetEntity: RolePermission::class)] protected Collection $permissions; + /** @var Collection */ #[ ORM\OneToMany(mappedBy: 'station', targetEntity: StationPlaylist::class), ORM\OrderBy(['type' => 'ASC', 'weight' => 'DESC']) ] protected Collection $playlists; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'station', targetEntity: StationMount::class)] protected Collection $mounts; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'station', targetEntity: StationRemote::class)] protected Collection $remotes; + /** @var Collection */ #[ORM\OneToMany( mappedBy: 'station', targetEntity: StationWebhook::class, @@ -389,6 +396,7 @@ class Station implements Stringable, IdentifiableEntityInterface )] protected Collection $webhooks; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'station', targetEntity: SftpUser::class)] protected Collection $sftp_users; @@ -398,6 +406,7 @@ class Station implements Stringable, IdentifiableEntityInterface $this->backend_type = BackendAdapters::Liquidsoap->value; $this->history = new ArrayCollection(); + $this->permissions = new ArrayCollection(); $this->playlists = new ArrayCollection(); $this->mounts = new ArrayCollection(); $this->remotes = new ArrayCollection(); @@ -941,7 +950,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getHistory(): Collection { @@ -949,7 +958,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getStreamers(): Collection { @@ -1065,7 +1074,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getPermissions(): Collection { @@ -1073,7 +1082,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getMedia(): Collection { @@ -1081,7 +1090,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getPlaylists(): Collection { @@ -1089,7 +1098,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getMounts(): Collection { @@ -1097,7 +1106,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getRemotes(): Collection { @@ -1105,7 +1114,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getWebhooks(): Collection { @@ -1113,7 +1122,7 @@ class Station implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getSftpUsers(): Collection { diff --git a/src/Entity/StationBackendConfiguration.php b/src/Entity/StationBackendConfiguration.php index 4a0c9d0ad..7ba87e247 100644 --- a/src/Entity/StationBackendConfiguration.php +++ b/src/Entity/StationBackendConfiguration.php @@ -10,6 +10,9 @@ use App\Radio\Enums\StreamFormats; use Doctrine\Common\Collections\ArrayCollection; use InvalidArgumentException; +/** + * @extends ArrayCollection + */ class StationBackendConfiguration extends ArrayCollection { public const CHARSET = 'charset'; diff --git a/src/Entity/StationFrontendConfiguration.php b/src/Entity/StationFrontendConfiguration.php index 53ff7c0df..a4feb889c 100644 --- a/src/Entity/StationFrontendConfiguration.php +++ b/src/Entity/StationFrontendConfiguration.php @@ -7,6 +7,9 @@ namespace App\Entity; use App\Utilities\Strings; use Doctrine\Common\Collections\ArrayCollection; +/** + * @extends ArrayCollection + */ class StationFrontendConfiguration extends ArrayCollection { public function __construct(array $elements = []) diff --git a/src/Entity/StationMedia.php b/src/Entity/StationMedia.php index 9575038ab..9c25e3df3 100644 --- a/src/Entity/StationMedia.php +++ b/src/Entity/StationMedia.php @@ -191,6 +191,7 @@ class StationMedia implements ] protected int $art_updated_at = 0; + /** @var Collection */ #[ OA\Property(type: "array", items: new OA\Items()), ORM\OneToMany(mappedBy: 'media', targetEntity: StationPlaylistMedia::class), @@ -199,6 +200,7 @@ class StationMedia implements ] protected Collection $playlists; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'media', targetEntity: StationMediaCustomField::class)] protected Collection $custom_fields; @@ -428,13 +430,16 @@ class StationMedia implements } /** - * @return Collection + * @return Collection */ public function getCustomFields(): Collection { return $this->custom_fields; } + /** + * @param Collection $custom_fields + */ public function setCustomFields(Collection $custom_fields): void { $this->custom_fields = $custom_fields; @@ -462,7 +467,7 @@ class StationMedia implements } /** - * @return Collection + * @return Collection */ public function getPlaylists(): Collection { diff --git a/src/Entity/StationPlaylist.php b/src/Entity/StationPlaylist.php index cb56ca78d..5806a1073 100644 --- a/src/Entity/StationPlaylist.php +++ b/src/Entity/StationPlaylist.php @@ -181,17 +181,20 @@ class StationPlaylist implements ] protected int $queue_reset_at = 0; + /** @var Collection */ #[ ORM\OneToMany(mappedBy: 'playlist', targetEntity: StationPlaylistMedia::class, fetch: 'EXTRA_LAZY'), ORM\OrderBy(['weight' => 'ASC']) ] protected Collection $media_items; + /** @var Collection */ #[ ORM\OneToMany(mappedBy: 'playlist', targetEntity: StationPlaylistFolder::class, fetch: 'EXTRA_LAZY') ] protected Collection $folders; + /** @var Collection */ #[ OA\Property(type: "array", items: new OA\Items()), ORM\OneToMany(mappedBy: 'playlist', targetEntity: StationSchedule::class, fetch: 'EXTRA_LAZY'), @@ -438,7 +441,7 @@ class StationPlaylist implements } /** - * @return Collection + * @return Collection */ public function getMediaItems(): Collection { @@ -446,7 +449,7 @@ class StationPlaylist implements } /** - * @return Collection + * @return Collection */ public function getFolders(): Collection { @@ -454,7 +457,7 @@ class StationPlaylist implements } /** - * @return Collection + * @return Collection */ public function getScheduleItems(): Collection { diff --git a/src/Entity/StationStreamer.php b/src/Entity/StationStreamer.php index b22e12cc8..f61a3ea88 100644 --- a/src/Entity/StationStreamer.php +++ b/src/Entity/StationStreamer.php @@ -99,6 +99,7 @@ class StationStreamer implements ] protected int $art_updated_at = 0; + /** @var Collection */ #[ OA\Property(type: "array", items: new OA\Items()), ORM\OneToMany(mappedBy: 'streamer', targetEntity: StationSchedule::class), @@ -228,7 +229,7 @@ class StationStreamer implements } /** - * @return Collection + * @return Collection */ public function getScheduleItems(): Collection { diff --git a/src/Entity/StorageLocation.php b/src/Entity/StorageLocation.php index f3d5a52b0..aae81573e 100644 --- a/src/Entity/StorageLocation.php +++ b/src/Entity/StorageLocation.php @@ -100,6 +100,7 @@ class StorageLocation implements Stringable, IdentifiableEntityInterface #[Attributes\AuditIgnore] protected ?string $storageUsed = null; + /** @var Collection */ #[ORM\OneToMany(mappedBy: 'storage_location', targetEntity: StationMedia::class)] protected Collection $media; @@ -462,7 +463,7 @@ class StorageLocation implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getMedia(): Collection { @@ -508,7 +509,7 @@ class StorageLocation implements Stringable, IdentifiableEntityInterface $client = $this->getS3Client(); $client->listObjectsV2( [ - 'Bucket' => $this->s3Bucket, + 'Bucket' => $this->s3Bucket, 'max-keys' => 1, ] ); @@ -550,12 +551,12 @@ class StorageLocation implements Stringable, IdentifiableEntityInterface $s3Options = array_filter( [ 'credentials' => [ - 'key' => $this->s3CredentialKey, + 'key' => $this->s3CredentialKey, 'secret' => $this->s3CredentialSecret, ], - 'region' => $this->s3Region, - 'version' => $this->s3Version, - 'endpoint' => $this->s3Endpoint, + 'region' => $this->s3Region, + 'version' => $this->s3Version, + 'endpoint' => $this->s3Endpoint, ] ); return new S3Client($s3Options); diff --git a/src/Entity/User.php b/src/Entity/User.php index 3919d2d31..f8ee1156f 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -105,6 +105,7 @@ class User implements Stringable, IdentifiableEntityInterface ] protected int $updated_at; + /** @var Collection */ #[ OA\Property(type: "array", items: new OA\Items()), ORM\ManyToMany(targetEntity: Role::class, inversedBy: 'users', fetch: 'EAGER'), @@ -117,6 +118,7 @@ class User implements Stringable, IdentifiableEntityInterface ] protected Collection $roles; + /** @var Collection */ #[ ORM\OneToMany(mappedBy: 'user', targetEntity: ApiKey::class), Groups([EntityGroupsInterface::GROUP_ADMIN, EntityGroupsInterface::GROUP_ALL]), @@ -262,7 +264,7 @@ class User implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getRoles(): Collection { @@ -270,7 +272,7 @@ class User implements Stringable, IdentifiableEntityInterface } /** - * @return Collection + * @return Collection */ public function getApiKeys(): Collection { diff --git a/src/Paginator.php b/src/Paginator.php index 82c70a92e..6c099538c 100644 --- a/src/Paginator.php +++ b/src/Paginator.php @@ -20,6 +20,11 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Traversable; +/** + * @template TKey of array-key + * @template T of mixed + * @implements IteratorAggregate + */ class Paginator implements IteratorAggregate, Countable { protected RouterInterface $router; @@ -39,6 +44,9 @@ class Paginator implements IteratorAggregate, Countable /** @var callable|null A callable postprocessor that can be run on each result. */ protected $postprocessor; + /** + * @param Pagerfanta $paginator + */ public function __construct( protected Pagerfanta $paginator, ServerRequestInterface $request @@ -206,6 +214,13 @@ class Paginator implements IteratorAggregate, Countable ); } + /** + * @template XKey of array-key + * @template X of mixed + * + * @param array $input + * @return static + */ public static function fromArray(array $input, ServerRequestInterface $request): self { return new self( @@ -214,6 +229,13 @@ class Paginator implements IteratorAggregate, Countable ); } + /** + * @template XKey of array-key + * @template X of mixed + * + * @param Collection $collection + * @return static + */ public static function fromCollection(Collection $collection, ServerRequestInterface $request): self { return new self( @@ -222,6 +244,9 @@ class Paginator implements IteratorAggregate, Countable ); } + /** + * @return static + */ public static function fromQueryBuilder(QueryBuilder $qb, ServerRequestInterface $request): self { return new self( @@ -230,6 +255,9 @@ class Paginator implements IteratorAggregate, Countable ); } + /** + * @return static + */ public static function fromQuery(Query $query, ServerRequestInterface $request): self { return new self( diff --git a/src/Radio/AutoDJ/Scheduler.php b/src/Radio/AutoDJ/Scheduler.php index 73a2d4f35..1dec6a501 100644 --- a/src/Radio/AutoDJ/Scheduler.php +++ b/src/Radio/AutoDJ/Scheduler.php @@ -227,7 +227,7 @@ class Scheduler } /** - * @param Collection $scheduleItems + * @param Collection $scheduleItems * @param CarbonInterface $now * @return Entity\StationSchedule|null */