From 63e0040e8f6b657e627d61378c5944df4cace086 Mon Sep 17 00:00:00 2001 From: "Buster \"Silver Eagle\" Neece" Date: Mon, 31 Aug 2020 17:32:30 -0500 Subject: [PATCH] Bump static analysis level and make strict type fixes. --- phpstan.neon | 2 +- src/AppFactory.php | 17 ++++----- .../Admin/AbstractAdminCrudController.php | 4 +-- .../Api/AbstractApiCrudController.php | 2 +- src/Controller/Api/Admin/UsersController.php | 2 +- .../AbstractScheduledEntityController.php | 4 +-- .../Api/Stations/ServicesController.php | 8 ----- .../Frontend/PublicPages/PlaylistAction.php | 2 -- .../AbstractStationCrudController.php | 4 +-- src/Doctrine/DecoratedEntityManager.php | 4 ++- .../ClearEntityManagerSubscriber.php | 14 ++++---- src/Doctrine/Repository.php | 16 +++------ src/Entity/Listener.php | 2 +- .../Repository/StationMediaRepository.php | 2 +- src/Entity/Repository/StationRepository.php | 3 +- .../Repository/StationScheduleRepository.php | 8 ++--- .../Repository/StationStreamerRepository.php | 6 ++-- src/Entity/SongHistory.php | 6 ++-- src/Entity/Station.php | 8 +---- src/Entity/StationBackendConfiguration.php | 2 +- src/Entity/StationMedia.php | 12 ++----- src/Entity/StationPlaylist.php | 2 -- src/Entity/StationQueue.php | 2 +- src/Entity/StationSchedule.php | 4 +-- src/Event/AbstractBuildMenu.php | 3 +- src/Flysystem/FilesystemGroup.php | 4 +++ src/Form/AbstractSettingsForm.php | 3 +- src/Form/EntityForm.php | 4 +-- src/Http/Response.php | 4 +-- src/Http/RouterInterface.php | 4 +-- src/Media/AlbumArt.php | 2 +- src/Middleware/EnforceSecurity.php | 2 +- src/Radio/AutoDJ.php | 2 +- src/Radio/AutoDJ/Queue.php | 2 +- src/Radio/Backend/Liquidsoap.php | 2 +- src/Radio/Backend/Liquidsoap/ConfigWriter.php | 12 ++----- src/Radio/Frontend/SHOUTcast.php | 2 +- src/Radio/Remote/AbstractRemote.php | 4 +-- src/Sync/Runner.php | 4 +-- src/Sync/Task/RadioAutomation.php | 2 +- src/Sync/Task/RadioRequests.php | 3 +- src/Timezone.php | 2 +- src/Utilities/Xml.php | 1 - .../StationPortCheckerValidator.php | 2 +- .../_generated/FunctionalTesterActions.php | 36 +++++++++++-------- .../_support/_generated/UnitTesterActions.php | 2 +- 46 files changed, 104 insertions(+), 134 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 21661a5e2..aff0cc440 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 2 + level: 3 paths: - src diff --git a/src/AppFactory.php b/src/AppFactory.php index d2b7f4c0d..2c8708d64 100644 --- a/src/AppFactory.php +++ b/src/AppFactory.php @@ -123,16 +123,17 @@ class AppFactory protected static function applyPhpSettings(Settings $settings): void { - ini_set('display_startup_errors', !$settings->isProduction() ? 1 : 0); - ini_set('display_errors', !$settings->isProduction() ? 1 : 0); - ini_set('log_errors', 1); + error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT); + + ini_set('display_startup_errors', !$settings->isProduction() ? '1' : '0'); + ini_set('display_errors', !$settings->isProduction() ? '1' : '0'); + ini_set('log_errors', '1'); ini_set('error_log', $settings[Settings::IS_DOCKER] ? '/dev/stderr' : $settings[Settings::TEMP_DIR] . '/php_errors.log'); - ini_set('error_reporting', E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT); - ini_set('session.use_only_cookies', 1); - ini_set('session.cookie_httponly', 1); - ini_set('session.cookie_lifetime', 86400); - ini_set('session.use_strict_mode', 1); + ini_set('session.use_only_cookies', '1'); + ini_set('session.cookie_httponly', '1'); + ini_set('session.cookie_lifetime', '86400'); + ini_set('session.use_strict_mode', '1'); session_cache_limiter(''); } diff --git a/src/Controller/Admin/AbstractAdminCrudController.php b/src/Controller/Admin/AbstractAdminCrudController.php index 8526f44d7..ba6bd2f91 100644 --- a/src/Controller/Admin/AbstractAdminCrudController.php +++ b/src/Controller/Admin/AbstractAdminCrudController.php @@ -5,7 +5,7 @@ use App\Exception\NotFoundException; use App\Form\EntityForm; use App\Http\ServerRequest; use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\EntityRepository; +use Doctrine\Persistence\ObjectRepository; abstract class AbstractAdminCrudController { @@ -15,7 +15,7 @@ abstract class AbstractAdminCrudController protected string $entity_class; - protected EntityRepository $record_repo; + protected ObjectRepository $record_repo; protected string $csrf_namespace; diff --git a/src/Controller/Api/AbstractApiCrudController.php b/src/Controller/Api/AbstractApiCrudController.php index 8737cb102..19b5518af 100644 --- a/src/Controller/Api/AbstractApiCrudController.php +++ b/src/Controller/Api/AbstractApiCrudController.php @@ -124,7 +124,7 @@ abstract class AbstractApiCrudController } /** - * @param array $data + * @param array|null $data * @param object|null $record * @param array $context * diff --git a/src/Controller/Api/Admin/UsersController.php b/src/Controller/Api/Admin/UsersController.php index a7969df9a..37fc02adc 100644 --- a/src/Controller/Api/Admin/UsersController.php +++ b/src/Controller/Api/Admin/UsersController.php @@ -96,7 +96,7 @@ class UsersController extends AbstractAdminApiCrudController */ public function deleteAction(ServerRequest $request, Response $response, $id): ResponseInterface { - /** @var Entity\User $record */ + /** @var Entity\User|null $record */ $record = $this->_getRecord($id); if (null === $record) { diff --git a/src/Controller/Api/Stations/AbstractScheduledEntityController.php b/src/Controller/Api/Stations/AbstractScheduledEntityController.php index f02512215..7465c78e6 100644 --- a/src/Controller/Api/Stations/AbstractScheduledEntityController.php +++ b/src/Controller/Api/Stations/AbstractScheduledEntityController.php @@ -38,7 +38,7 @@ abstract class AbstractScheduledEntityController extends AbstractStationApiCrudC ): ResponseInterface { $station = $request->getStation(); $tz = $station->getTimezoneObject(); - + $params = $request->getQueryParams(); $startDateStr = substr($params['start'], 0, 10); @@ -54,7 +54,7 @@ abstract class AbstractScheduledEntityController extends AbstractStationApiCrudC $i = $startDate; while ($i <= $endDate) { - $dayOfWeek = $i->format('N'); + $dayOfWeek = (int)$i->format('N'); if ($this->scheduler->shouldSchedulePlayOnCurrentDate($scheduleItem, $i) && $this->scheduler->isScheduleScheduledToPlayToday($scheduleItem, $dayOfWeek)) { diff --git a/src/Controller/Api/Stations/ServicesController.php b/src/Controller/Api/Stations/ServicesController.php index 09783e0d8..54f74edf5 100644 --- a/src/Controller/Api/Stations/ServicesController.php +++ b/src/Controller/Api/Stations/ServicesController.php @@ -114,13 +114,11 @@ class ServicesController $frontend->stop($station); return $response->withJson(new Entity\Api\Status(true, __('Frontend stopped.'))); - break; case 'start': $frontend->start($station); return $response->withJson(new Entity\Api\Status(true, __('Frontend started.'))); - break; case 'restart': default: @@ -133,7 +131,6 @@ class ServicesController $frontend->start($station); return $response->withJson(new Entity\Api\Status(true, __('Frontend restarted.'))); - break; } } @@ -188,7 +185,6 @@ class ServicesController } return $response->withJson(new Entity\Api\Status(true, __('Song skipped.'))); - break; case 'disconnect': if ($backend instanceof Liquidsoap) { @@ -196,19 +192,16 @@ class ServicesController } return $response->withJson(new Entity\Api\Status(true, __('Streamer disconnected.'))); - break; case 'stop': $backend->stop($station); return $response->withJson(new Entity\Api\Status(true, __('Backend stopped.'))); - break; case 'start': $backend->start($station); return $response->withJson(new Entity\Api\Status(true, __('Backend started.'))); - break; case 'restart': default: @@ -221,7 +214,6 @@ class ServicesController $backend->start($station); return $response->withJson(new Entity\Api\Status(true, __('Backend restarted.'))); - break; } } diff --git a/src/Controller/Frontend/PublicPages/PlaylistAction.php b/src/Controller/Frontend/PublicPages/PlaylistAction.php index 7277065d0..55054550a 100644 --- a/src/Controller/Frontend/PublicPages/PlaylistAction.php +++ b/src/Controller/Frontend/PublicPages/PlaylistAction.php @@ -59,7 +59,6 @@ class PlaylistAction return $response ->withHeader('Content-Type', 'audio/x-mpegurl') ->withHeader('Content-Disposition', 'attachment; filename=' . $station->getShortName() . '.m3u'); - break; // PLS Playlist Format case 'pls': @@ -84,7 +83,6 @@ class PlaylistAction return $response ->withHeader('Content-Type', 'audio/x-scpls') ->withHeader('Content-Disposition', 'attachment; filename=' . $station->getShortName() . '.pls'); - break; } } } \ No newline at end of file diff --git a/src/Controller/Stations/AbstractStationCrudController.php b/src/Controller/Stations/AbstractStationCrudController.php index dc9679133..a0752879d 100644 --- a/src/Controller/Stations/AbstractStationCrudController.php +++ b/src/Controller/Stations/AbstractStationCrudController.php @@ -8,9 +8,9 @@ use App\Exception\NotFoundException; use App\Form\EntityForm; use App\Http\ServerRequest; use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\EntityRepository; use Doctrine\ORM\OptimisticLockException; use Doctrine\ORM\ORMException; +use Doctrine\Persistence\ObjectRepository; abstract class AbstractStationCrudController { @@ -20,7 +20,7 @@ abstract class AbstractStationCrudController protected string $entity_class; - protected EntityRepository $record_repo; + protected ObjectRepository $record_repo; protected string $csrf_namespace; diff --git a/src/Doctrine/DecoratedEntityManager.php b/src/Doctrine/DecoratedEntityManager.php index 03ec6290e..64db52a86 100644 --- a/src/Doctrine/DecoratedEntityManager.php +++ b/src/Doctrine/DecoratedEntityManager.php @@ -28,7 +28,7 @@ class DecoratedEntityManager extends EntityManagerDecorator /** * Fetch a new, managed instance of an entity object, even if the EntityManager has been cleared. * - * @template T + * @template T as object The type of the entity being refetched. * * @param T $entity * @@ -37,6 +37,8 @@ class DecoratedEntityManager extends EntityManagerDecorator public function refetch($entity) { $metadata = $this->wrapped->getClassMetadata(get_class($entity)); + + /** @var T $freshValue */ $freshValue = $this->wrapped->find($metadata->getName(), $metadata->getIdentifierValues($entity)); if (!$freshValue) { diff --git a/src/Doctrine/Messenger/ClearEntityManagerSubscriber.php b/src/Doctrine/Messenger/ClearEntityManagerSubscriber.php index 9de37a8c4..a855862f4 100644 --- a/src/Doctrine/Messenger/ClearEntityManagerSubscriber.php +++ b/src/Doctrine/Messenger/ClearEntityManagerSubscriber.php @@ -15,6 +15,14 @@ class ClearEntityManagerSubscriber implements EventSubscriberInterface $this->em = $em; } + public static function getSubscribedEvents() + { + return [ + WorkerMessageHandledEvent::class => 'onWorkerMessageHandled', + WorkerMessageFailedEvent::class => 'onWorkerMessageFailed', + ]; + } + public function onWorkerMessageHandled(): void { $this->clearEntityManagers(); @@ -25,12 +33,6 @@ class ClearEntityManagerSubscriber implements EventSubscriberInterface $this->clearEntityManagers(); } - public static function getSubscribedEvents() - { - yield WorkerMessageHandledEvent::class => 'onWorkerMessageHandled'; - yield WorkerMessageFailedEvent::class => 'onWorkerMessageFailed'; - } - protected function clearEntityManagers(): void { $this->em->clear(); diff --git a/src/Doctrine/Repository.php b/src/Doctrine/Repository.php index efb66fa64..aa0756714 100644 --- a/src/Doctrine/Repository.php +++ b/src/Doctrine/Repository.php @@ -5,7 +5,7 @@ use App\Normalizer\DoctrineEntityNormalizer; use App\Settings; use Closure; use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\EntityRepository; +use Doctrine\Persistence\ObjectRepository; use Psr\Log\LoggerInterface; use Symfony\Component\Serializer\Serializer; @@ -15,7 +15,7 @@ class Repository protected string $entityClass; - protected EntityRepository $repository; + protected ObjectRepository $repository; protected Serializer $serializer; @@ -42,18 +42,12 @@ class Repository } } - /** - * @return string The extrapolated likely entity name, based on this repository's class name. - */ protected function getEntityClass(): string { return str_replace(['Repository', '\\\\'], ['', '\\'], static::class); } - /** - * @return EntityRepository - */ - public function getRepository(): EntityRepository + public function getRepository(): ObjectRepository { return $this->repository; } @@ -62,7 +56,7 @@ class Repository * Generate an array result of all records. * * @param bool $cached - * @param null $order_by + * @param string|null $order_by * @param string $order_dir * * @return array @@ -83,7 +77,7 @@ class Repository /** * Generic dropdown builder function (can be overridden for specialized use cases). * - * @param bool $add_blank + * @param bool|string $add_blank * @param Closure|NULL $display * @param string $pk * @param string $order_by diff --git a/src/Entity/Listener.php b/src/Entity/Listener.php index 401cbf606..ef9359c83 100644 --- a/src/Entity/Listener.php +++ b/src/Entity/Listener.php @@ -80,7 +80,7 @@ class Listener $this->timestamp_start = time(); $this->timestamp_end = 0; - $this->listener_uid = $client->uid; + $this->listener_uid = (int)$client->uid; $this->listener_user_agent = $this->truncateString($client->userAgent) ?? ''; $this->listener_ip = $client->ip; $this->listener_hash = self::calculateListenerHash($client); diff --git a/src/Entity/Repository/StationMediaRepository.php b/src/Entity/Repository/StationMediaRepository.php index 487dfa016..32e561542 100644 --- a/src/Entity/Repository/StationMediaRepository.php +++ b/src/Entity/Repository/StationMediaRepository.php @@ -320,7 +320,7 @@ class StationMediaRepository extends Repository throw new MediaProcessingException(sprintf('Media path "%s" not found.', $media_uri)); } - $media_mtime = $fs->getTimestamp($media_uri); + $media_mtime = (int)$fs->getTimestamp($media_uri); // No need to update if all of these conditions are true. if (!$force && !$media->needsReprocessing($media_mtime)) { diff --git a/src/Entity/Repository/StationRepository.php b/src/Entity/Repository/StationRepository.php index 224618e19..e238480e8 100644 --- a/src/Entity/Repository/StationRepository.php +++ b/src/Entity/Repository/StationRepository.php @@ -77,7 +77,7 @@ class StationRepository extends Repository } /** - * @param bool $add_blank + * @param bool|string $add_blank * @param Closure|NULL $display * @param string $pk * @param string $order_by @@ -123,7 +123,6 @@ class StationRepository extends Repository */ public function edit(Entity\Station $record): Entity\Station { - /** @var Entity\Station $original_record */ $original_record = $this->em->getUnitOfWork()->getOriginalEntityData($record); // Get the original values to check for changes. diff --git a/src/Entity/Repository/StationScheduleRepository.php b/src/Entity/Repository/StationScheduleRepository.php index 90eb94884..8a43e3689 100644 --- a/src/Entity/Repository/StationScheduleRepository.php +++ b/src/Entity/Repository/StationScheduleRepository.php @@ -8,7 +8,6 @@ use App\Settings; use Carbon\CarbonImmutable; use Carbon\CarbonInterface; use Doctrine\ORM\EntityManagerInterface; -use InvalidArgumentException; use Psr\Log\LoggerInterface; use Symfony\Component\Serializer\Serializer; @@ -75,11 +74,8 @@ class StationScheduleRepository extends Repository if ($relation instanceof Entity\StationPlaylist) { return $this->repository->findBy(['playlist' => $relation]); } - if ($relation instanceof Entity\StationStreamer) { - return $this->repository->findBy(['streamer' => $relation]); - } - throw new InvalidArgumentException('Related entity must be a Playlist or Streamer.'); + return $this->repository->findBy(['streamer' => $relation]); } /** @@ -114,7 +110,7 @@ class StationScheduleRepository extends Repository $i = $startDate; while ($i <= $endDate) { - $dayOfWeek = $i->format('N'); + $dayOfWeek = (int)$i->format('N'); if ($this->scheduler->shouldSchedulePlayOnCurrentDate($scheduleItem, $i) && $this->scheduler->isScheduleScheduledToPlayToday($scheduleItem, $dayOfWeek)) { diff --git a/src/Entity/Repository/StationStreamerRepository.php b/src/Entity/Repository/StationStreamerRepository.php index 72b8b2b83..222255944 100644 --- a/src/Entity/Repository/StationStreamerRepository.php +++ b/src/Entity/Repository/StationStreamerRepository.php @@ -132,7 +132,7 @@ class StationStreamerRepository extends Repository /** * Fetch all streamers who are deactivated and have a reactivate at timestamp set * - * @param int $reactivate_at + * @param int|null $reactivate_at * * @return Entity\StationStreamer[] */ @@ -140,7 +140,9 @@ class StationStreamerRepository extends Repository { $reactivate_at = $reactivate_at ?? time(); - return $this->repository->createQueryBuilder('s') + return $this->em->createQueryBuilder() + ->select('s') + ->from($this->entityClass, 's') ->where('s.is_active = 0') ->andWhere('s.reactivate_at <= :reactivate_at') ->setParameter('reactivate_at', $reactivate_at) diff --git a/src/Entity/SongHistory.php b/src/Entity/SongHistory.php index 730722e9c..d5d878a80 100644 --- a/src/Entity/SongHistory.php +++ b/src/Entity/SongHistory.php @@ -385,11 +385,13 @@ class SongHistory } /** - * @param Api\SongHistory $response + * @template T of Api\SongHistory + * + * @param T $response * @param ApiUtilities $api * @param UriInterface|null $base_url * - * @return Api\SongHistory + * @return T */ public function api(Api\SongHistory $response, ApiUtilities $api, UriInterface $base_url = null) { diff --git a/src/Entity/Station.php b/src/Entity/Station.php index 4a5ba8039..912e57d64 100644 --- a/src/Entity/Station.php +++ b/src/Entity/Station.php @@ -935,10 +935,7 @@ class Station public function getStorageUsed(): ?string { $raw_size = $this->getStorageUsedBytes(); - - return ($raw_size instanceof BigInteger) - ? Quota::getReadableSize($raw_size) - : ''; + return Quota::getReadableSize($raw_size); } /** @@ -1025,9 +1022,6 @@ class Station } $used = $this->getStorageUsedBytes(); - if ($used === null) { - return false; - } return ($used->compareTo($available) !== -1); } diff --git a/src/Entity/StationBackendConfiguration.php b/src/Entity/StationBackendConfiguration.php index c6460255e..1b4a451cc 100644 --- a/src/Entity/StationBackendConfiguration.php +++ b/src/Entity/StationBackendConfiguration.php @@ -163,7 +163,7 @@ class StationBackendConfiguration extends ArrayCollection $this->set(self::CROSSFADE, $crossfade); } - public function getCrossfadeDuration(): int + public function getCrossfadeDuration(): float { $crossfade = $this->getCrossfade(); $crossfadeType = $this->getCrossfadeType(); diff --git a/src/Entity/StationMedia.php b/src/Entity/StationMedia.php index ef39c72ec..cf46386df 100644 --- a/src/Entity/StationMedia.php +++ b/src/Entity/StationMedia.php @@ -346,7 +346,7 @@ class StationMedia $length_sec = $length % 60; $this->length = (float)$length; - $this->length_text = $length_min . ':' . str_pad($length_sec, 2, '0', STR_PAD_LEFT); + $this->length_text = $length_min . ':' . str_pad((string)$length_sec, 2, '0', STR_PAD_LEFT); } public function getLengthText(): ?string @@ -396,11 +396,7 @@ class StationMedia public function setAmplify(?float $amplify = null): void { - if ($amplify === '') { - $amplify = null; - } - - $this->amplify = (null === $amplify) ? null : (float)$amplify; + $this->amplify = $amplify; } public function getFadeOverlap(): ?float @@ -410,10 +406,6 @@ class StationMedia public function setFadeOverlap(?float $fade_overlap = null): void { - if ($fade_overlap === '') { - $fade_overlap = null; - } - $this->fade_overlap = $fade_overlap; } diff --git a/src/Entity/StationPlaylist.php b/src/Entity/StationPlaylist.php index f24557b17..6a04cf5b5 100644 --- a/src/Entity/StationPlaylist.php +++ b/src/Entity/StationPlaylist.php @@ -622,7 +622,6 @@ class StationPlaylist } return implode("\n", $playlist_file); - break; case 'pls': default: @@ -646,7 +645,6 @@ class StationPlaylist $playlist_file[] = 'Version=2'; return implode("\n", $playlist_file); - break; } } } diff --git a/src/Entity/StationQueue.php b/src/Entity/StationQueue.php index 8188adda4..48ebeea7e 100644 --- a/src/Entity/StationQueue.php +++ b/src/Entity/StationQueue.php @@ -221,7 +221,7 @@ class StationQueue public function sentToAutoDj(): void { $cued = $this->getTimestampCued(); - if (null === $cued || 0 === $cued) { + if (0 === $cued) { $this->setTimestampCued(time()); } diff --git a/src/Entity/StationSchedule.php b/src/Entity/StationSchedule.php index c7cb21f21..fae1c7313 100644 --- a/src/Entity/StationSchedule.php +++ b/src/Entity/StationSchedule.php @@ -235,7 +235,7 @@ class StationSchedule $parts[] = implode('/', $displayDays); } - + return implode(', ', $parts); } @@ -254,7 +254,7 @@ class StationSchedule } $timeCode = str_pad($timeCode, 4, '0', STR_PAD_LEFT); - return $now->setTime(substr($timeCode, 0, 2), substr($timeCode, 2)); + return $now->setTime((int)substr($timeCode, 0, 2), (int)substr($timeCode, 2)); } public static function displayTimeCode($timeCode): string diff --git a/src/Event/AbstractBuildMenu.php b/src/Event/AbstractBuildMenu.php index 48ef5b49f..8879fc26a 100644 --- a/src/Event/AbstractBuildMenu.php +++ b/src/Event/AbstractBuildMenu.php @@ -3,7 +3,6 @@ namespace App\Event; use App\Acl; use App\Entity\User; -use App\Http\Router; use App\Http\RouterInterface; use App\Settings; use Symfony\Contracts\EventDispatcher\Event; @@ -33,7 +32,7 @@ abstract class AbstractBuildMenu extends Event return $this->acl; } - public function getRouter(): Router + public function getRouter(): RouterInterface { return $this->router; } diff --git a/src/Flysystem/FilesystemGroup.php b/src/Flysystem/FilesystemGroup.php index dbd261379..22296d7c1 100644 --- a/src/Flysystem/FilesystemGroup.php +++ b/src/Flysystem/FilesystemGroup.php @@ -122,6 +122,10 @@ class FilesystemGroup extends MountManager [$prefix, $path] = $this->getPrefixAndPath($uri); $fs = $this->getFilesystem($prefix); + if (!($fs instanceof Filesystem)) { + throw new \RuntimeException('Filesystem cannot be iterated.'); + } + $iterator = new FilesystemIterator($fs, $path, $iteratorOptions); $options = Options::fromArray($iteratorOptions); diff --git a/src/Form/AbstractSettingsForm.php b/src/Form/AbstractSettingsForm.php index 72ed01cbb..5c27d95d1 100644 --- a/src/Form/AbstractSettingsForm.php +++ b/src/Form/AbstractSettingsForm.php @@ -4,7 +4,6 @@ namespace App\Form; use App\Entity; use App\Http\ServerRequest; use App\Settings; -use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; abstract class AbstractSettingsForm extends Form @@ -28,7 +27,7 @@ abstract class AbstractSettingsForm extends Form $this->settingsRepo = $settingsRepo; } - public function getEntityManager(): EntityManager + public function getEntityManager(): EntityManagerInterface { return $this->em; } diff --git a/src/Form/EntityForm.php b/src/Form/EntityForm.php index 1058bc336..4a049e321 100644 --- a/src/Form/EntityForm.php +++ b/src/Form/EntityForm.php @@ -68,7 +68,7 @@ class EntityForm extends Form public function getEntityRepository(): ObjectRepository { - if (null === $this->entityClass) { + if (!isset($this->entityClass)) { throw new Exception('Entity class name is not specified.'); } @@ -83,7 +83,7 @@ class EntityForm extends Form */ public function process(ServerRequest $request, $record = null) { - if (null === $this->entityClass) { + if (!isset($this->entityClass)) { throw new Exception('Entity class name is not specified.'); } diff --git a/src/Http/Response.php b/src/Http/Response.php index b16cc95d7..8900cf237 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -41,7 +41,7 @@ final class Response extends \Slim\Http\Response ->withHeader('Pragma', '') ->withHeader('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $seconds)) ->withHeader('Cache-Control', 'public, must-revalidate, max-age=' . $seconds) - ->withHeader('X-Accel-Expires', $seconds); // CloudFlare + ->withHeader('X-Accel-Expires', (string)$seconds); // CloudFlare return new static($response, $this->streamFactory); } @@ -99,7 +99,7 @@ final class Response extends \Slim\Http\Response ->withHeader('Expires', '0') ->withHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') ->withHeader('Content-Type', mime_content_type($file_path)) - ->withHeader('Content-Length', filesize($file_path)) + ->withHeader('Content-Length', (string)filesize($file_path)) ->withHeader('Content-Disposition', 'attachment; filename=' . $file_name) ->withBody($stream); diff --git a/src/Http/RouterInterface.php b/src/Http/RouterInterface.php index 684a4ab00..7d7a0dda7 100644 --- a/src/Http/RouterInterface.php +++ b/src/Http/RouterInterface.php @@ -40,7 +40,7 @@ interface RouterInterface /** * Return a named route based on the current page and its route arguments. * - * @param null $route_name + * @param string|null $route_name * @param array $route_params * @param array $query_params * @param bool $absolute @@ -57,7 +57,7 @@ interface RouterInterface /** * Same as $this->fromHere(), but merging the current GET query parameters into the request as well. * - * @param null $route_name + * @param string|null $route_name * @param array $route_params * @param array $query_params * @param bool $absolute diff --git a/src/Media/AlbumArt.php b/src/Media/AlbumArt.php index 6ef494f8f..7260dc885 100644 --- a/src/Media/AlbumArt.php +++ b/src/Media/AlbumArt.php @@ -25,7 +25,7 @@ class AlbumArt $source_gd_image = imagecreatefromstring($rawArtString); if (!is_resource($source_gd_image)) { - return false; + throw new \RuntimeException('Cannot create image from string.'); } // Crop the raw art to a 1200x1200 artboard. diff --git a/src/Middleware/EnforceSecurity.php b/src/Middleware/EnforceSecurity.php index a4ca5018a..2e2007856 100644 --- a/src/Middleware/EnforceSecurity.php +++ b/src/Middleware/EnforceSecurity.php @@ -49,7 +49,7 @@ class EnforceSecurity implements MiddlewareInterface if ('https' === $request->getUri()->getScheme()) { // Enforce secure cookies. - ini_set('session.cookie_secure', 1); + ini_set('session.cookie_secure', '1'); $csp[] = 'upgrade-insecure-requests'; diff --git a/src/Radio/AutoDJ.php b/src/Radio/AutoDJ.php index a61b69d17..88e2b7501 100644 --- a/src/Radio/AutoDJ.php +++ b/src/Radio/AutoDJ.php @@ -111,7 +111,7 @@ class AutoDJ $now = $now->addSeconds($duration); return ($duration >= $startNext) - ? $now->subMilliseconds($startNext * 1000) + ? $now->subMilliseconds((int)($startNext * 1000)) : $now; } diff --git a/src/Radio/AutoDJ/Queue.php b/src/Radio/AutoDJ/Queue.php index 8ec2b3d07..144569639 100644 --- a/src/Radio/AutoDJ/Queue.php +++ b/src/Radio/AutoDJ/Queue.php @@ -228,7 +228,7 @@ class Queue implements EventSubscriberInterface $this->em->persist($playlist); $spm = $media_to_play->getItemForPlaylist($playlist); - if ($spm instanceof Entity\StationPlaylist) { + if ($spm instanceof Entity\StationPlaylistMedia) { $spm->played($now->getTimestamp()); $this->em->persist($spm); } diff --git a/src/Radio/Backend/Liquidsoap.php b/src/Radio/Backend/Liquidsoap.php index a5edf3f38..ea1ee3528 100644 --- a/src/Radio/Backend/Liquidsoap.php +++ b/src/Radio/Backend/Liquidsoap.php @@ -124,7 +124,7 @@ class Liquidsoap extends AbstractBackend // Safety checks for cue lengths. if ($annotation_types['liq_cue_out'] < 0) { $cue_out = abs($annotation_types['liq_cue_out']); - if (0 === $cue_out || $cue_out > $annotation_types['duration']) { + if (0.0 === $cue_out || $cue_out > $annotation_types['duration']) { $annotation_types['liq_cue_out'] = null; } else { $annotation_types['liq_cue_out'] = max(0, $annotation_types['duration'] - $cue_out); diff --git a/src/Radio/Backend/Liquidsoap/ConfigWriter.php b/src/Radio/Backend/Liquidsoap/ConfigWriter.php index 4f1202d03..1e10dafbd 100644 --- a/src/Radio/Backend/Liquidsoap/ConfigWriter.php +++ b/src/Radio/Backend/Liquidsoap/ConfigWriter.php @@ -970,20 +970,16 @@ class ConfigWriter implements EventSubscriberInterface $aot = ($bitrate >= 96) ? 'mpeg4_aac_lc' : 'mpeg4_he_aac_v2'; return '%fdkaac(channels=2, samplerate=44100, bitrate=' . $bitrate . ', afterburner=' . $afterburner . ', aot="' . $aot . '", sbr_mode=true)'; - break; case Entity\StationMountInterface::FORMAT_OGG: return '%vorbis.cbr(samplerate=44100, channels=2, bitrate=' . $bitrate . ')'; - break; case Entity\StationMountInterface::FORMAT_OPUS: return '%opus(samplerate=48000, bitrate=' . $bitrate . ', vbr="constrained", application="audio", channels=2, signal="music", complexity=10, max_bandwidth="full_band")'; - break; case Entity\StationMountInterface::FORMAT_MP3: default: return '%mp3(samplerate=44100, stereo=true, bitrate=' . $bitrate . ', id3v2=true)'; - break; } } @@ -1026,18 +1022,14 @@ class ConfigWriter implements EventSubscriberInterface /** * Convert an integer or float into a Liquidsoap configuration compatible float. * - * @param float|int $number + * @param float|int|string $number * @param int $decimals * * @return string */ public static function toFloat($number, $decimals = 2): string { - if ((int)$number == $number) { - return (int)$number . '.'; - } - - return number_format($number, $decimals, '.', ''); + return number_format((float)$number, $decimals, '.', ''); } public static function formatTimeCode($time_code): string diff --git a/src/Radio/Frontend/SHOUTcast.php b/src/Radio/Frontend/SHOUTcast.php index 6312f3fa8..8280b892f 100644 --- a/src/Radio/Frontend/SHOUTcast.php +++ b/src/Radio/Frontend/SHOUTcast.php @@ -70,7 +70,7 @@ class SHOUTcast extends AbstractFrontend /** @var Entity\StationMount $mount */ $sid++; - $result = $npAdapter->getNowPlaying($sid, $includeClients); + $result = $npAdapter->getNowPlaying((string)$sid, $includeClients); $mount->setListenersTotal($result->listeners->total); $mount->setListenersUnique($result->listeners->unique); diff --git a/src/Radio/Remote/AbstractRemote.php b/src/Radio/Remote/AbstractRemote.php index baa80b9f6..c84e106fd 100644 --- a/src/Radio/Remote/AbstractRemote.php +++ b/src/Radio/Remote/AbstractRemote.php @@ -96,7 +96,7 @@ abstract class AbstractRemote * Format and return a URL for the remote path. * * @param Entity\StationRemote $remote - * @param null $custom_path + * @param string|null $custom_path * * @return string */ @@ -104,7 +104,7 @@ abstract class AbstractRemote { $uri = new Uri($remote->getUrl()); - return ($custom_path !== null) + return (null !== $custom_path) ? (string)$uri->withPath($custom_path) : (string)$uri; } diff --git a/src/Sync/Runner.php b/src/Sync/Runner.php index f12d12efc..8506d5c65 100644 --- a/src/Sync/Runner.php +++ b/src/Sync/Runner.php @@ -92,8 +92,8 @@ class Runner if (Settings::getInstance()->isCli()) { error_reporting(E_ALL & ~E_STRICT & ~E_NOTICE); - ini_set('display_errors', 1); - ini_set('log_errors', 1); + ini_set('display_errors', '1'); + ini_set('log_errors', '1'); } $this->logger->info(sprintf('Running sync task: %s', $syncInfo['name'])); diff --git a/src/Sync/Task/RadioAutomation.php b/src/Sync/Task/RadioAutomation.php index 7d600466d..5dcab3b62 100644 --- a/src/Sync/Task/RadioAutomation.php +++ b/src/Sync/Task/RadioAutomation.php @@ -136,7 +136,7 @@ class RadioAutomation extends AbstractTask $numSongs = count($mediaReport); $numPlaylists = count($playlists); - $songsPerPlaylist = floor($numSongs / $numPlaylists); + $songsPerPlaylist = (int)floor($numSongs / $numPlaylists); $i = 0; foreach ($playlists as $playlistId) { diff --git a/src/Sync/Task/RadioRequests.php b/src/Sync/Task/RadioRequests.php index bed933273..1cc26e296 100644 --- a/src/Sync/Task/RadioRequests.php +++ b/src/Sync/Task/RadioRequests.php @@ -39,11 +39,10 @@ class RadioRequests extends AbstractTask */ public function run(bool $force = false): void { - /** @var Entity\Repository\StationRepository $stations */ + /** @var Entity\Station[] $stations */ $stations = $this->em->getRepository(Entity\Station::class)->findAll(); foreach ($stations as $station) { - /** @var Entity\Station $station */ if (!$station->useManualAutoDJ()) { continue; } diff --git a/src/Timezone.php b/src/Timezone.php index 62e50bbb0..e0a48b760 100644 --- a/src/Timezone.php +++ b/src/Timezone.php @@ -79,7 +79,7 @@ class Timezone return 'UTC'; } - return 'UTC ' . $sign . str_pad($hour, 2, '0', STR_PAD_LEFT) . ':' . str_pad($minutes, 2, '0'); + return 'UTC ' . $sign . str_pad((string)$hour, 2, '0', STR_PAD_LEFT) . ':' . str_pad((string)$minutes, 2, '0'); } public static function fetchSelect(): array diff --git a/src/Utilities/Xml.php b/src/Utilities/Xml.php index 7a538b7ff..43d8e1a07 100644 --- a/src/Utilities/Xml.php +++ b/src/Utilities/Xml.php @@ -71,7 +71,6 @@ class Xml case 'close': return $child; - break; } } diff --git a/src/Validator/Constraints/StationPortCheckerValidator.php b/src/Validator/Constraints/StationPortCheckerValidator.php index 5bd77c33d..a20e0f4e5 100644 --- a/src/Validator/Constraints/StationPortCheckerValidator.php +++ b/src/Validator/Constraints/StationPortCheckerValidator.php @@ -44,7 +44,7 @@ class StationPortCheckerValidator extends ConstraintValidator $port = (int)$value; if (isset($used_ports[$port])) { $this->context->buildViolation($constraint->message) - ->setParameter('{{ port }}', $port) + ->setParameter('{{ port }}', (string)$port) ->addViolation(); } diff --git a/tests/_support/_generated/FunctionalTesterActions.php b/tests/_support/_generated/FunctionalTesterActions.php index 4b3337f5c..1f94562fa 100644 --- a/tests/_support/_generated/FunctionalTesterActions.php +++ b/tests/_support/_generated/FunctionalTesterActions.php @@ -1,4 +1,4 @@ - * ``` * - * In this case you can match that record contains fields with data types you expected. + * You can check if the record contains fields with the data types you expect. * The list of possible data types: * * * string @@ -3755,8 +3755,9 @@ trait FunctionalTesterActions * * float * * array (json object is array as well) * * boolean + * * null * - * You can also use nested data type structures: + * You can also use nested data type structures, and define multiple types for the same field: * * ```php * * ``` * - * You can also apply filters to check values. Filter can be applied with `:` char after the type declaration. + * You can also apply filters to check values. Filter can be applied with a `:` char after the type declaration, + * or after another filter if you need more than one. * * Here is the list of possible filters: * @@ -3792,16 +3794,17 @@ trait FunctionalTesterActions * // {'user_id': '1'} * $I->seeResponseMatchesJsonType([ * 'user_id' => 'string:>0', // works with strings as well - * } + * ]); * ?> * ``` * - * You can also add custom filters y accessing `JsonType::addCustomFilter` method. + * You can also add custom filters by using `{@link JsonType::addCustomFilter()}`. * See [JsonType reference](http://codeception.com/docs/reference/JsonType). * * @part json * @param array $jsonType * @param string $jsonPath + * @see JsonType * @version 2.1.3 * @see \Codeception\Module\REST::seeResponseMatchesJsonType() */ @@ -3812,9 +3815,9 @@ trait FunctionalTesterActions * [!] Method is generated. Documentation taken from corresponding module. * * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that Json matches provided types. + * Checks that JSON matches provided types. * In case you don't know the actual values of JSON data returned you can match them by type. - * Starts check with a root element. If JSON data is array it will check the first element of an array. + * It starts the check with a root element. If JSON data is an array it will check all elements of it. * You can specify the path in the json which should be checked with JsonPath * * Basic example: @@ -3834,7 +3837,7 @@ trait FunctionalTesterActions * ?> * ``` * - * In this case you can match that record contains fields with data types you expected. + * You can check if the record contains fields with the data types you expect. * The list of possible data types: * * * string @@ -3842,8 +3845,9 @@ trait FunctionalTesterActions * * float * * array (json object is array as well) * * boolean + * * null * - * You can also use nested data type structures: + * You can also use nested data type structures, and define multiple types for the same field: * * ```php * * ``` * - * You can also apply filters to check values. Filter can be applied with `:` char after the type declaration. + * You can also apply filters to check values. Filter can be applied with a `:` char after the type declaration, + * or after another filter if you need more than one. * * Here is the list of possible filters: * @@ -3879,16 +3884,17 @@ trait FunctionalTesterActions * // {'user_id': '1'} * $I->seeResponseMatchesJsonType([ * 'user_id' => 'string:>0', // works with strings as well - * } + * ]); * ?> * ``` * - * You can also add custom filters y accessing `JsonType::addCustomFilter` method. + * You can also add custom filters by using `{@link JsonType::addCustomFilter()}`. * See [JsonType reference](http://codeception.com/docs/reference/JsonType). * * @part json * @param array $jsonType * @param string $jsonPath + * @see JsonType * @version 2.1.3 * @see \Codeception\Module\REST::seeResponseMatchesJsonType() */ diff --git a/tests/_support/_generated/UnitTesterActions.php b/tests/_support/_generated/UnitTesterActions.php index b31d6b4d3..690a07fb0 100644 --- a/tests/_support/_generated/UnitTesterActions.php +++ b/tests/_support/_generated/UnitTesterActions.php @@ -1,4 +1,4 @@ -