More code cleanup.

This commit is contained in:
Buster "Silver Eagle" Neece 2021-06-09 22:22:13 -05:00
parent 26d9a5e66a
commit a320c1a6a0
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
78 changed files with 218 additions and 161 deletions

View File

@ -88,6 +88,7 @@
"codeception/module-phpbrowser": "^1.0",
"codeception/module-rest": "^1.0",
"filp/whoops": "^2",
"jetbrains/phpstorm-attributes": "^1.0",
"mockery/mockery": "^1.0",
"php-parallel-lint/php-console-highlighter": "^0.5.0",
"php-parallel-lint/php-parallel-lint": "^1.3",

44
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5293039041c75026b99de9bd015e4ede",
"content-hash": "419126bd4b8437a667508f7085775a4e",
"packages": [
{
"name": "aws/aws-sdk-php",
@ -9868,6 +9868,48 @@
},
"time": "2020-07-09T08:09:16+00:00"
},
{
"name": "jetbrains/phpstorm-attributes",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/JetBrains/phpstorm-attributes.git",
"reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JetBrains/phpstorm-attributes/zipball/a7a83ae5df4dd3c0875484483de19de8edf60a9f",
"reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-4": {
"JetBrains\\PhpStorm\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "JetBrains",
"homepage": "https://www.jetbrains.com"
}
],
"description": "PhpStorm specific attributes",
"keywords": [
"attributes",
"jetbrains",
"phpstorm"
],
"support": {
"issues": "https://youtrack.jetbrains.com/newIssue?project=WI",
"source": "https://github.com/JetBrains/phpstorm-attributes/tree/1.0"
},
"time": "2020-11-17T11:09:47+00:00"
},
{
"name": "justinrainbow/json-schema",
"version": "5.2.10",

View File

@ -106,6 +106,7 @@ class SetupCommand extends CommandAbstract
} else {
$public_ip = $acCentral->getIp(false);
/** @noinspection HttpUrlsUsage */
$io->success(
[
__('AzuraCast installation complete!'),

View File

@ -114,6 +114,7 @@ class RelaysController
$base_url = $body['base_url'];
} else {
$serverParams = $request->getServerParams();
/** @noinspection HttpUrlsUsage */
$base_url = 'http://' . $serverParams('REMOTE_ADDR');
}

View File

@ -44,7 +44,8 @@ class ChartsAction
// Generate unique cache ID for stations.
$stationIds = [];
foreach ($stations as $station) {
$stationIds[$station->getId()] = $station->getId();
$stationId = $station->getId();
$stationIds[$stationId] = $stationId;
}
$cacheName = 'homepage_metrics_' . implode(',', $stationIds);

View File

@ -205,7 +205,7 @@ class BatchAction
foreach ($toMove as $iterator) {
foreach ($iterator as $record) {
/** @var \App\Entity\Interfaces\PathAwareInterface $record */
/** @var Entity\Interfaces\PathAwareInterface $record */
$oldPath = $record->getPath();
$newPath = File::renameDirectoryInPath($oldPath, $from, $to);
@ -231,7 +231,7 @@ class BatchAction
foreach ($toMove as $iterator) {
foreach ($iterator as $record) {
/** @var \App\Entity\Interfaces\PathAwareInterface $record */
/** @var Entity\Interfaces\PathAwareInterface $record */
try {
$record->setPath(
File::renameDirectoryInPath($record->getPath(), $from, $to)

View File

@ -11,6 +11,7 @@ use App\Flysystem\StationFilesystems;
use App\Http\Response;
use App\Http\ServerRequest;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UploadedFileInterface;
use Symfony\Component\Serializer\Serializer;
@ -266,7 +267,7 @@ class PodcastEpisodesController extends AbstractApiCrudController
protected function viewRecord(object $record, ServerRequest $request): mixed
{
if (!($record instanceof Entity\PodcastEpisode)) {
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
throw new InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
}
$isInternal = ('true' === $request->getParam('internal', 'false'));

View File

@ -11,6 +11,7 @@ use App\Flysystem\StationFilesystems;
use App\Http\Response;
use App\Http\ServerRequest;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UploadedFileInterface;
@ -221,7 +222,7 @@ class PodcastsController extends AbstractApiCrudController
protected function viewRecord(object $record, ServerRequest $request): mixed
{
if (!($record instanceof Entity\Podcast)) {
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
throw new InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
}
$isInternal = ('true' === $request->getParam('internal', 'false'));

View File

@ -7,6 +7,7 @@ use App\Http\Response;
use App\Http\ServerRequest;
use Carbon\CarbonImmutable;
use Psr\Http\Message\ResponseInterface;
use stdClass;
class ChartsAction
{
@ -38,7 +39,7 @@ class ChartsAction
$statisticsThreshold
);
$daily_chart = new \stdClass();
$daily_chart = new stdClass();
$daily_chart->label = __('Listeners by Day');
$daily_chart->type = 'line';
$daily_chart->fill = false;
@ -56,7 +57,7 @@ class ChartsAction
$statTime = $stat['moment'];
$statTime = $statTime->shiftTimezone($station_tz);
$avg_row = new \stdClass();
$avg_row = new stdClass();
$avg_row->t = $statTime->getTimestamp() * 1000;
$avg_row->y = round($stat['number_avg'], 2);
$daily_averages[] = $avg_row;
@ -79,7 +80,7 @@ class ChartsAction
'alt' => implode('', $daily_alt),
];
$day_of_week_chart = new \stdClass();
$day_of_week_chart = new stdClass();
$day_of_week_chart->label = __('Listeners by Day of Week');
$day_of_week_alt = [
@ -134,12 +135,12 @@ class ChartsAction
$statTime = $stat['moment'];
$statTime = $statTime->shiftTimezone($station_tz);
$hour = (int)$statTime->hour;
$hour = $statTime->hour;
$totals_by_hour[$hour][] = $stat['number_avg'];
}
$hourly_labels = [];
$hourly_chart = new \stdClass();
$hourly_chart = new stdClass();
$hourly_chart->label = __('Listeners by Hour');
$hourly_rows = [];

View File

@ -52,7 +52,7 @@ class PodcastEpisodesController
}
);
$podcastsLink = (string)$router->fromHere(
$podcastsLink = $router->fromHere(
'public:podcasts',
[
'station_id' => $station->getId(),

View File

@ -16,6 +16,7 @@ use App\Flysystem\StationFilesystems;
use App\Http\Response;
use App\Http\RouterInterface;
use App\Http\ServerRequest;
use DateTime;
use GuzzleHttp\Psr7\UriResolver;
use MarcW\RssWriter\Extension\Atom\AtomLink;
use MarcW\RssWriter\Extension\Atom\AtomWriter;
@ -124,7 +125,7 @@ class PodcastFeedController
$channel = new RssChannel();
$channel->setTtl(5);
$channel->setLastBuildDate(new \DateTime());
$channel->setLastBuildDate(new DateTime());
$channel->setTitle($podcast->getTitle());
$channel->setDescription($podcast->getDescription());
@ -265,10 +266,10 @@ class PodcastFeedController
$rssItem->setLink($episodeLink);
$publishAtDateTime = (new \DateTime())->setTimestamp($episode->getCreatedAt());
$publishAtDateTime = (new DateTime())->setTimestamp($episode->getCreatedAt());
if ($episode->getPublishAt() !== null) {
$publishAtDateTime = (new \DateTime())->setTimestamp($episode->getPublishAt());
$publishAtDateTime = (new DateTime())->setTimestamp($episode->getPublishAt());
}
$rssItem->setPubDate($publishAtDateTime);

View File

@ -13,9 +13,11 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Proxy\Proxy;
use Doctrine\ORM\UnitOfWork;
use JetBrains\PhpStorm\Pure;
use ProxyManager\Proxy\GhostObjectInterface;
use ReflectionClass;
use ReflectionObject;
use Stringable;
/**
* A hook into Doctrine's event listener to write changes to "Auditable"
@ -247,7 +249,7 @@ class AuditLog implements EventSubscriber
return !$em->getMetadataFactory()->isTransient($class);
}
protected function isAuditable(ReflectionClass $refl): bool
#[Pure] protected function isAuditable(ReflectionClass $refl): bool
{
$auditable = $refl->getAttributes(Auditable::class);
return !empty($auditable);
@ -260,7 +262,7 @@ class AuditLog implements EventSubscriber
*/
protected function getIdentifier(object $entity): ?string
{
if ($entity instanceof \Stringable) {
if ($entity instanceof Stringable) {
return (string)$entity;
}

View File

@ -66,7 +66,7 @@ class Error
public static function fromException(Throwable $e, bool $includeTrace = false): self
{
$code = (int)$e->getCode();
$code = $e->getCode();
if (0 === $code) {
$code = 500;
}

View File

@ -56,27 +56,27 @@ class Station implements ResolvableUrlInterface
/**
* The public URL of the station.
* @OA\Property(example="http://example.com/")
* @OA\Property(example="https://example.com/")
*/
public ?string $url = null;
/**
* The public player URL for the station.
* @OA\Property(example="http://example.com/public/example_station")
* @OA\Property(example="https://example.com/public/example_station")
* @var string|UriInterface
*/
public $public_player_url;
/**
* The playlist download URL in PLS format.
* @OA\Property(example="http://example.com/public/example_station/playlist.pls")
* @OA\Property(example="https://example.com/public/example_station/playlist.pls")
* @var string|UriInterface
*/
public $playlist_pls_url;
/**
* The playlist download URL in M3U format.
* @OA\Property(example="http://example.com/public/example_station/playlist.m3u")
* @OA\Property(example="https://example.com/public/example_station/playlist.m3u")
* @var string|UriInterface
*/
public $playlist_m3u_url;

View File

@ -6,6 +6,7 @@ namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use OpenApi\Annotations as OA;
use Stringable;
use Symfony\Component\Validator\Constraints as Assert;
/** @OA\Schema(type="object") */
@ -14,7 +15,7 @@ use Symfony\Component\Validator\Constraints as Assert;
ORM\Table(name: 'custom_field'),
Attributes\Auditable
]
class CustomField implements \Stringable
class CustomField implements Stringable
{
use Traits\HasAutoIncrementId;
use Traits\TruncateStrings;

View File

@ -10,9 +10,9 @@ use Doctrine\Persistence\ObjectManager;
class Analytics extends AbstractFixture implements DependentFixtureInterface
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
$stations = $em->getRepository(Entity\Station::class)->findAll();
$stations = $manager->getRepository(Entity\Station::class)->findAll();
$midnight_utc = CarbonImmutable::now('UTC')->setTime(0, 0);
@ -46,7 +46,7 @@ class Analytics extends AbstractFixture implements DependentFixtureInterface
$station_listeners,
$station_unique
);
$em->persist($stationPoint);
$manager->persist($stationPoint);
}
$totalPoint = new Entity\Analytics(
@ -58,10 +58,10 @@ class Analytics extends AbstractFixture implements DependentFixtureInterface
$day_listeners,
$day_unique
);
$em->persist($totalPoint);
$manager->persist($totalPoint);
}
$em->flush();
$manager->flush();
}
/**

View File

@ -10,7 +10,7 @@ use Doctrine\Persistence\ObjectManager;
class ApiKey extends AbstractFixture implements DependentFixtureInterface
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
$demo_api_key = getenv('INIT_DEMO_API_KEY');
@ -21,7 +21,7 @@ class ApiKey extends AbstractFixture implements DependentFixtureInterface
$api_key = new Entity\ApiKey($demo_user, SplitToken::fromKeyString($demo_api_key));
$api_key->setComment('Demo User');
$em->persist($api_key);
$manager->persist($api_key);
}
$admin_api_key = getenv('INIT_ADMIN_API_KEY');
@ -33,10 +33,10 @@ class ApiKey extends AbstractFixture implements DependentFixtureInterface
$api_key = new Entity\ApiKey($admin_user, SplitToken::fromKeyString($admin_api_key));
$api_key->setComment('Administrator');
$em->persist($api_key);
$manager->persist($api_key);
}
$em->flush();
$manager->flush();
}
/**

View File

@ -9,7 +9,7 @@ use Doctrine\Persistence\ObjectManager;
class Podcast extends AbstractFixture implements DependentFixtureInterface
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
/** @var Entity\Station $station */
$station = $this->getReference('station');
@ -22,12 +22,12 @@ class Podcast extends AbstractFixture implements DependentFixtureInterface
$podcast->setLink('https://demo.azuracast.com');
$podcast->setLanguage('en');
$podcast->setDescription('The unofficial testing podcast for the AzuraCast development team.');
$em->persist($podcast);
$manager->persist($podcast);
$category = new Entity\PodcastCategory($podcast, 'Technology');
$em->persist($category);
$manager->persist($category);
$em->flush();
$manager->flush();
$this->setReference('podcast', $podcast);
}

View File

@ -17,7 +17,7 @@ class PodcastEpisode extends AbstractFixture implements DependentFixtureInterfac
$this->mediaRepo = $mediaRepo;
}
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
$podcastsSkeletonDir = getenv('INIT_PODCASTS_PATH');
@ -68,8 +68,8 @@ class PodcastEpisode extends AbstractFixture implements DependentFixtureInterfac
$episode->setDescription('Another great episode!');
$episode->setExplicit(false);
$em->persist($episode);
$em->flush();
$manager->persist($episode);
$manager->flush();
$this->mediaRepo->upload(
$episode,

View File

@ -8,7 +8,7 @@ use Doctrine\Persistence\ObjectManager;
class Role extends AbstractFixture
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
$admin_role = new Entity\Role();
$admin_role->setName('Super Administrator');
@ -16,9 +16,9 @@ class Role extends AbstractFixture
$demo_role = new Entity\Role();
$demo_role->setName('Demo Account');
$em->persist($admin_role);
$em->persist($demo_role);
$em->flush();
$manager->persist($admin_role);
$manager->persist($demo_role);
$manager->flush();
$this->addReference('admin_role', $admin_role);
$this->addReference('demo_role', $demo_role);

View File

@ -10,7 +10,7 @@ use Doctrine\Persistence\ObjectManager;
class RolePermission extends AbstractFixture implements DependentFixtureInterface
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
/** @var Entity\Station $station */
$station = $this->getReference('station');
@ -38,11 +38,11 @@ class RolePermission extends AbstractFixture implements DependentFixtureInterfac
foreach ($perm_names as $perm_name) {
$rp = new Entity\RolePermission($role, $perm_name[1], $perm_name[0]);
$em->persist($rp);
$manager->persist($rp);
}
}
$em->flush();
$manager->flush();
}
/**

View File

@ -8,10 +8,10 @@ use Doctrine\Persistence\ObjectManager;
class Settings extends AbstractFixture
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
foreach ($em->getRepository(Entity\Settings::class)->findAll() as $row) {
$em->remove($row);
foreach ($manager->getRepository(Entity\Settings::class)->findAll() as $row) {
$manager->remove($row);
}
$settings = new Entity\Settings();
@ -43,7 +43,7 @@ class Settings extends AbstractFixture
);
}
$em->persist($settings);
$em->flush();
$manager->persist($settings);
$manager->flush();
}
}

View File

@ -9,7 +9,7 @@ use Doctrine\Persistence\ObjectManager;
class Station extends AbstractFixture
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
$station = new Entity\Station();
$station->setName('AzuraTest Radio');
@ -32,12 +32,12 @@ class Station extends AbstractFixture
$podcastsStorage->setStorageQuota($stationQuota);
}
$em->persist($station);
$em->persist($mediaStorage);
$em->persist($recordingsStorage);
$em->persist($podcastsStorage);
$manager->persist($station);
$manager->persist($mediaStorage);
$manager->persist($recordingsStorage);
$manager->persist($podcastsStorage);
$em->flush();
$manager->flush();
$this->addReference('station', $station);
}

View File

@ -17,7 +17,7 @@ class StationMedia extends AbstractFixture implements DependentFixtureInterface
$this->mediaRepo = $mediaRepo;
}
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
$musicSkeletonDir = getenv('INIT_MUSIC_PATH');
@ -47,15 +47,15 @@ class StationMedia extends AbstractFixture implements DependentFixtureInterface
$fs->upload($filePath, '/' . $fileBaseName);
$mediaRow = $this->mediaRepo->getOrCreate($mediaStorage, $fileBaseName);
$em->persist($mediaRow);
$manager->persist($mediaRow);
// Add the file to the playlist.
$spmRow = new Entity\StationPlaylistMedia($playlist, $mediaRow);
$spmRow->setWeight(1);
$em->persist($spmRow);
$manager->persist($spmRow);
}
$em->flush();
$manager->flush();
}
/**

View File

@ -9,7 +9,7 @@ use Doctrine\Persistence\ObjectManager;
class StationMount extends AbstractFixture implements DependentFixtureInterface
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
/** @var Entity\Station $station */
$station = $this->getReference('station');
@ -17,14 +17,14 @@ class StationMount extends AbstractFixture implements DependentFixtureInterface
$mount_radio = new Entity\StationMount($station);
$mount_radio->setName('/radio.mp3');
$mount_radio->setIsDefault(true);
$em->persist($mount_radio);
$manager->persist($mount_radio);
$mount_mobile = new Entity\StationMount($station);
$mount_mobile->setName('/mobile.mp3');
$mount_mobile->setAutodjBitrate(64);
$em->persist($mount_mobile);
$manager->persist($mount_mobile);
$em->flush();
$manager->flush();
}
/**

View File

@ -9,15 +9,15 @@ use Doctrine\Persistence\ObjectManager;
class StationPlaylist extends AbstractFixture implements DependentFixtureInterface
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
/** @var Entity\Station $station */
$station = $this->getReference('station');
$playlist = new Entity\StationPlaylist($station);
$playlist->setName('default');
$em->persist($playlist);
$em->flush();
$manager->persist($playlist);
$manager->flush();
$this->addReference('station_playlist', $playlist);
}

View File

@ -9,14 +9,14 @@ use Doctrine\Persistence\ObjectManager;
class User extends AbstractFixture implements DependentFixtureInterface
{
public function load(ObjectManager $em): void
public function load(ObjectManager $manager): void
{
$demo_user = new Entity\User();
$demo_user->setEmail('demo@azuracast.com');
$demo_user->setNewPassword('demo');
$demo_user->setName('AzuraCast Demo User');
$demo_user->getRoles()->add($this->getReference('demo_role'));
$em->persist($demo_user);
$manager->persist($demo_user);
$this->addReference('demo_user', $demo_user);
@ -37,12 +37,12 @@ class User extends AbstractFixture implements DependentFixtureInterface
$admin_user->setTwoFactorSecret($admin_2fa_secret);
}
$em->persist($admin_user);
$manager->persist($admin_user);
$this->addReference('admin_user', $admin_user);
}
$em->flush();
$manager->flush();
}
/**

View File

@ -18,7 +18,7 @@ final class Version20170829030442 extends AbstractMigration
$this->changeCharset('utf8mb4', 'utf8mb4_unicode_ci');
}
protected function changeCharset($charset, $collate): void
private function changeCharset($charset, $collate): void
{
$db_name = $this->connection->getDatabase();

View File

@ -20,7 +20,7 @@ final class Version20180425050351 extends AbstractMigration
$this->changeCharset('utf8mb4', 'utf8mb4_bin');
}
protected function changeCharset($charset, $collate): void
private function changeCharset($charset, $collate): void
{
$sqlLines = [
'ALTER TABLE `station_media` DROP FOREIGN KEY FK_32AADE3AA0BDB2F3',

View File

@ -20,7 +20,7 @@ final class Version20180826043500 extends AbstractMigration
$this->changeCharset('utf8mb4', 'utf8mb4_general_ci');
}
protected function changeCharset($charset, $collate): void
private function changeCharset($charset, $collate): void
{
$db_name = $this->connection->getDatabase();

View File

@ -77,7 +77,7 @@ final class Version20190513163051 extends AbstractMigration
* @return int
* @noinspection SummerTimeUnsafeTimeManipulationInspection
*/
protected function applyOffset(mixed $time_code, int $offset_hours): int
private function applyOffset(mixed $time_code, int $offset_hours): int
{
$hours = (int)floor($time_code / 100);
$mins = $time_code % 100;

View File

@ -84,12 +84,12 @@ final class Version20201204043539 extends AbstractMigration
}
}
protected function toInt($value): ?int
private function toInt($value): ?int
{
return (null === $value) ? null : (int)$value;
}
protected function toBool($value): ?bool
private function toBool($value): ?bool
{
return (null === $value) ? null : (bool)$value;
}

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Entity;
use App\Annotations\AuditLog;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Entity;
use App\Annotations\AuditLog;
use App\Entity\Traits;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Entity;
use App\Annotations\AuditLog;
use App\Entity\Traits;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

View File

@ -20,7 +20,7 @@ class Relay
use Traits\HasAutoIncrementId;
use Traits\TruncateStrings;
/** @OA\Property(example="http://custom-url.example.com") */
/** @OA\Property(example="https://custom-url.example.com") */
#[ORM\Column(length: 255)]
protected string $base_url;

View File

@ -72,7 +72,7 @@ class SongHistoryRepository extends Repository
// Pull the most recent history item for this station.
$last_sh = $this->getCurrent($station);
$listeners = (int)$np->listeners->current;
$listeners = $np->listeners->current;
if ($last_sh instanceof Entity\SongHistory) {
if ($last_sh->getSongId() === $song->getSongId()) {

View File

@ -26,6 +26,7 @@ class StationStreamerBroadcastRepository extends Repository
->setParameter('streamer', $currentStreamer)
->setMaxResults(1)
->getSingleResult();
return $latestBroadcast;
}

View File

@ -90,8 +90,8 @@ class StationStreamerRepository extends Repository
$this->em->persist($record);
$this->em->flush();
$fsStations = new StationFilesystems($station);
return $fsStations->getTempFilesystem()->getLocalPath($recordingPath);
return (new StationFilesystems($station))->getTempFilesystem()
->getLocalPath($recordingPath);
}
}

View File

@ -2,7 +2,6 @@
namespace App\Entity;
use App\Annotations\AuditLog;
use App\Customization;
use App\Doctrine\Generator\UuidV6Generator;
use App\Entity;

View File

@ -13,6 +13,7 @@ use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use OpenApi\Annotations as OA;
use RuntimeException;
use Symfony\Component\Serializer\Annotation as Serializer;
/** @OA\Schema(type="object") */
@ -207,7 +208,7 @@ class StationMedia implements SongInterface, ProcessableMediaInterface, PathAwar
public function getUniqueId(): string
{
if (!isset($this->unique_id)) {
throw new \RuntimeException('Unique ID has not been generated yet.');
throw new RuntimeException('Unique ID has not been generated yet.');
}
return $this->unique_id;

View File

@ -10,6 +10,7 @@ use App\Radio\Frontend\AbstractFrontend;
use Doctrine\ORM\Mapping as ORM;
use OpenApi\Annotations as OA;
use Psr\Http\Message\UriInterface;
use Stringable;
use Symfony\Component\Validator\Constraints as Assert;
/** @OA\Schema(type="object") */
@ -18,7 +19,7 @@ use Symfony\Component\Validator\Constraints as Assert;
ORM\Table(name: 'station_mounts'),
Attributes\Auditable
]
class StationMount implements \Stringable, Interfaces\StationMountInterface, Interfaces\StationCloneAwareInterface
class StationMount implements Stringable, Interfaces\StationMountInterface, Interfaces\StationCloneAwareInterface
{
use Traits\HasAutoIncrementId;
use Traits\TruncateStrings;
@ -55,7 +56,7 @@ class StationMount implements \Stringable, Interfaces\StationMountInterface, Int
#[ORM\Column(length: 100, nullable: true)]
protected ?string $fallback_mount = null;
/** @OA\Property(example="http://radio.example.com:8000/radio.mp3") */
/** @OA\Property(example="https://radio.example.com:8000/radio.mp3") */
#[ORM\Column(length: 255, nullable: true)]
protected ?string $relay_url = null;
@ -335,7 +336,7 @@ class StationMount implements \Stringable, Interfaces\StationMountInterface, Int
$response->id = $this->id;
$response->name = $this->getDisplayName();
$response->path = $this->getName();
$response->is_default = (bool)$this->is_default;
$response->is_default = $this->is_default;
$response->url = $fa->getUrlForMount($this->station, $this, $base_url);
$response->listeners = new Api\NowPlayingListeners(

View File

@ -82,7 +82,7 @@ class StationPlaylist implements Stringable, Interfaces\StationCloneAwareInterfa
#[Assert\Choice(choices: [self::ORDER_RANDOM, self::ORDER_SHUFFLE, self::ORDER_SEQUENTIAL])]
protected string $order = self::ORDER_SHUFFLE;
/** @OA\Property(example="http://remote-url.example.com/stream.mp3") */
/** @OA\Property(example="https://remote-url.example.com/stream.mp3") */
#[ORM\Column(length: 255, nullable: true)]
protected ?string $remote_url = null;

View File

@ -88,7 +88,7 @@ class StationPlaylistMedia implements JsonSerializable
return [
'id' => $this->playlist->getId(),
'name' => $this->playlist->getName(),
'weight' => (int)$this->weight,
'weight' => $this->weight,
];
}

View File

@ -69,7 +69,7 @@ class StationRemote implements Stringable, Interfaces\StationMountInterface, Int
#[ORM\Column(length: 255, nullable: true)]
protected ?string $custom_listen_url = null;
/** @OA\Property(example="http://custom-url.example.com") */
/** @OA\Property(example="https://custom-url.example.com") */
#[ORM\Column(length: 255, nullable: true)]
protected ?string $url = null;
@ -310,6 +310,7 @@ class StationRemote implements Stringable, Interfaces\StationMountInterface, Int
public function setUrl(?string $url): void
{
if (!empty($url) && !str_starts_with($url, 'http')) {
/** @noinspection HttpUrlsUsage */
$url = 'http://' . $url;
}

View File

@ -75,7 +75,7 @@ class StationSchedule
public function getStartTime(): int
{
return (int)$this->start_time;
return $this->start_time;
}
public function setStartTime(int $start_time): void
@ -85,7 +85,7 @@ class StationSchedule
public function getEndTime(): int
{
return (int)$this->end_time;
return $this->end_time;
}
public function setEndTime(int $end_time): void

View File

@ -11,6 +11,7 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use OpenApi\Annotations as OA;
use Stringable;
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
@ -29,7 +30,7 @@ use const PASSWORD_ARGON2ID;
UniqueEntity(fields: ['station', 'streamer_username']),
Attributes\Auditable
]
class StationStreamer implements \Stringable, Interfaces\StationCloneAwareInterface
class StationStreamer implements Stringable, Interfaces\StationCloneAwareInterface
{
use Traits\HasAutoIncrementId;
use Traits\TruncateStrings;
@ -79,7 +80,7 @@ class StationStreamer implements \Stringable, Interfaces\StationCloneAwareInterf
* @OA\Items()
* )
*/
#[ORM\OneToMany(targetEntity: StationSchedule::class, mappedBy: 'streamer')]
#[ORM\OneToMany(mappedBy: 'streamer', targetEntity: StationSchedule::class)]
#[DeepNormalize(true)]
#[Serializer\MaxDepth(1)]
protected Collection $schedule_items;

View File

@ -4,7 +4,6 @@
namespace App\Entity;
use App\Annotations\AuditLog;
use Doctrine\ORM\Mapping as ORM;
use OpenApi\Annotations as OA;
use Stringable;

View File

@ -4,7 +4,6 @@
namespace App\Entity;
use App\Annotations\AuditLog;
use App\Radio\Quota;
use App\Validator\Constraints as AppAssert;
use Aws\S3\S3Client;

View File

@ -2,7 +2,7 @@
namespace App\Entity\Traits;
use App\Annotations\AuditLog;
use App\Entity;
use App\Security\SplitToken;
use Doctrine\ORM\Mapping as ORM;
@ -13,7 +13,7 @@ trait HasSplitTokenFields
protected string $id;
#[ORM\Column(length: 128)]
#[\App\Entity\Attributes\AuditIgnore]
#[Entity\Attributes\AuditIgnore]
protected string $verifier;
protected function setFromToken(SplitToken $token): void

View File

@ -4,7 +4,6 @@
namespace App\Entity;
use App\Annotations\AuditLog;
use App\Auth;
use App\Normalizer\Attributes\DeepNormalize;
use App\Validator\Constraints\UniqueEntity;

View File

@ -4,7 +4,6 @@ namespace App\Http;
use Azura\Files\Adapter\LocalAdapterInterface;
use Azura\Files\ExtendedFilesystemInterface;
use Azura\Files\FilesystemInterface;
use InvalidArgumentException;
use League\Flysystem\FileAttributes;
use Psr\Http\Message\ResponseInterface;

View File

@ -42,6 +42,7 @@ class Router implements RouterInterface
$settingsBaseUrl = $settings->getBaseUrl();
if (!empty($settingsBaseUrl)) {
if (!str_starts_with($settingsBaseUrl, 'http')) {
/** @noinspection HttpUrlsUsage */
$settingsBaseUrl = 'http://' . $settingsBaseUrl;
}

View File

@ -126,7 +126,7 @@ final class ServerRequest extends \Slim\Http\ServerRequest
*
* @throws Exception\InvalidRequestAttribute
*/
protected function getAttributeOfClass(string $attr, string $class_name): mixed
private function getAttributeOfClass(string $attr, string $class_name): mixed
{
$object = $this->serverRequest->getAttribute($attr);

View File

@ -7,6 +7,7 @@ use App\Entity;
use App\Utilities\File;
use Azura\Files\ExtendedFilesystemInterface;
use Doctrine\ORM\EntityManagerInterface;
use Throwable;
class BatchUtilities
{
@ -35,7 +36,7 @@ class BatchUtilities
foreach ($toRename as $iterator) {
foreach ($iterator as $record) {
/** @var \App\Entity\Interfaces\PathAwareInterface $record */
/** @var Entity\Interfaces\PathAwareInterface $record */
$record->setPath(
File::renameDirectoryInPath($record->getPath(), $from, $to)
);
@ -88,7 +89,7 @@ class BatchUtilities
$affectedPlaylists[$playlistId] = $playlist;
}
}
} catch (\Throwable) {
} catch (Throwable) {
}
}

View File

@ -7,6 +7,8 @@ use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use const JSON_THROW_ON_ERROR;
/**
* When sending data using multipart forms (that also include uploaded files, for example),
* it isn't possible to encode JSON values (i.e. booleans) in the other submitted values.
@ -34,7 +36,7 @@ class HandleMultipartJson implements MiddlewareInterface
if (1 === count($parsedBody)) {
$bodyField = current($parsedBody);
if (is_string($bodyField)) {
$parsedBody = json_decode($bodyField, true, 512, \JSON_THROW_ON_ERROR);
$parsedBody = json_decode($bodyField, true, 512, JSON_THROW_ON_ERROR);
$request = $request->withParsedBody($parsedBody);
}

View File

@ -113,17 +113,17 @@ class DoctrineEntityNormalizer extends AbstractNormalizer
* Replicates the "fromArray" functionality previously present in Doctrine 1.
*
* @param mixed $data
* @param string $class
* @param string $type
* @param string|null $format
* @param array $context
*/
public function denormalize($data, string $class, string $format = null, array $context = []): object
public function denormalize($data, string $type, string $format = null, array $context = []): object
{
$object = $this->instantiateObject($data, $class, $context, new ReflectionClass($class), false, $format);
$object = $this->instantiateObject($data, $type, $context, new ReflectionClass($type), false, $format);
$class = get_class($object);
$type = get_class($object);
$context[self::CLASS_METADATA] = $this->em->getMetadataFactory()->getMetadataFor($class);
$context[self::CLASS_METADATA] = $this->em->getMetadataFactory()->getMetadataFor($type);
$context[self::ASSOCIATION_MAPPINGS] = [];
if ($context[self::CLASS_METADATA]->associationMappings) {

View File

@ -6,9 +6,11 @@ use App\Http\Response;
use App\Http\Router;
use App\Http\RouterInterface;
use App\Http\ServerRequest;
use Countable;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use IteratorAggregate;
use Pagerfanta\Adapter\ArrayAdapter;
use Pagerfanta\Doctrine\Collections\CollectionAdapter;
use Pagerfanta\Doctrine\ORM\QueryAdapter;
@ -17,7 +19,7 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Traversable;
class Paginator implements \IteratorAggregate, \Countable
class Paginator implements IteratorAggregate, Countable
{
protected RouterInterface $router;

View File

@ -104,7 +104,7 @@ class Scheduler
Entity\StationPlaylist $playlist,
CarbonInterface $now
): bool {
$current_minute = (int)$now->minute;
$current_minute = $now->minute;
$target_minute = $playlist->getPlayPerHourMinute();
if ($current_minute < $target_minute) {

View File

@ -4,6 +4,7 @@ namespace App\Radio\Backend;
use App\Entity;
use App\Radio\AbstractAdapter;
use JetBrains\PhpStorm\Pure;
abstract class AbstractBackend extends AbstractAdapter
{
@ -42,7 +43,7 @@ abstract class AbstractBackend extends AbstractAdapter
return [];
}
public function getProgramName(Entity\Station $station): string
#[Pure] public function getProgramName(Entity\Station $station): string
{
return 'station_' . $station->getId() . ':station_' . $station->getId() . '_backend';
}

View File

@ -683,6 +683,8 @@ class ConfigWriter implements EventSubscriberInterface
$params['api_auth'] = '!azuracast_api_auth';
$service_uri = ($this->environment->isDockerRevisionAtLeast(5)) ? 'web' : 'nginx';
/** @noinspection HttpUrlsUsage */
$api_url = 'http://' . $service_uri . '/api/internal/' . $station->getId() . '/' . $endpoint;
$command = 'curl -s --request POST --url ' . $api_url;
foreach ($params as $paramKey => $paramVal) {
@ -991,11 +993,6 @@ class ConfigWriter implements EventSubscriberInterface
/**
* Given outbound broadcast information, produce a suitable LiquidSoap configuration line for the stream.
*
* @param Entity\Station $station
* @param \App\Entity\Interfaces\StationMountInterface $mount
* @param string $idPrefix
* @param int $id
*/
protected function getOutputString(
Entity\Station $station,

View File

@ -9,6 +9,7 @@ use App\Http\Router;
use App\Radio\AbstractAdapter;
use App\Xml\Reader;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Uri;
use InvalidArgumentException;
@ -177,7 +178,7 @@ abstract class AbstractFrontend extends AbstractAdapter
if (str_starts_with($custom_config_raw, '<')) {
return (new Reader())->fromString('<custom_config>' . $custom_config_raw . '</custom_config>');
}
} catch (\Exception $e) {
} catch (Exception $e) {
$this->logger->error(
'Could not parse custom configuration.',
[

View File

@ -33,6 +33,7 @@ class Icecast extends AbstractFrontend
$feConfig = $station->getFrontendConfig();
$radioPort = $feConfig->getPort();
/** @noinspection HttpUrlsUsage */
$baseUrl = 'http://' . ($this->environment->isDocker() ? 'stations' : 'localhost') . ':' . $radioPort;
$npAdapter = $this->adapterFactory->getIcecastAdapter($baseUrl);
@ -91,6 +92,7 @@ class Icecast extends AbstractFrontend
$settingsBaseUrl = $settings->getBaseUrl() ?: 'http://localhost';
if (!str_starts_with($settingsBaseUrl, 'http')) {
/** @noinspection HttpUrlsUsage */
$settingsBaseUrl = 'http://' . $settingsBaseUrl;
}
$baseUrl = new Uri($settingsBaseUrl);

View File

@ -59,6 +59,8 @@ class SHOUTcast extends AbstractFrontend
{
$feConfig = $station->getFrontendConfig();
$radioPort = $feConfig->getPort();
/** @noinspection HttpUrlsUsage */
$baseUrl = 'http://' . ($this->environment->isDocker() ? 'stations' : 'localhost') . ':' . $radioPort;
$npAdapter = $this->adapterFactory->getShoutcast2Adapter($baseUrl);

View File

@ -44,8 +44,8 @@ class NChan
{
$vars = [];
if (0 === stripos(PHP_OS, 'linux')) {
foreach (glob('/etc/*-release') as $file) {
if ('Linux' === PHP_OS_FAMILY) {
foreach (glob(' /etc/*-release', GLOB_NOSORT) as $file) {
$lines = array_filter(
array_map(
static function ($line) {

View File

@ -9,6 +9,7 @@ use App\EventDispatcher;
use App\LockFactory;
use App\Message;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use InvalidArgumentException;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
@ -92,7 +93,7 @@ class Runner
foreach ($event->getTasks() as $taskClass => $task) {
try {
$lock->refresh($syncInfo['timeout']);
} catch (\Exception) {
} catch (Exception) {
// Noop
}

View File

@ -19,8 +19,7 @@ class File
*/
public static function sanitizePathPrefix(string $path): string
{
$pattern = '/.*:\/\//i';
$pattern = '/:\/\//';
$path = preg_replace($pattern, '', $path);
if (preg_match($pattern, $path)) {

View File

@ -104,6 +104,7 @@ class Strings
*/
public static function truncateUrl(string $url, $length = 40): string
{
/** @noinspection HttpUrlsUsage */
$url = str_replace(['http://', 'https://', 'www.'], '', $url);
return self::truncateText(rtrim($url, '/'), $length);

View File

@ -17,17 +17,17 @@ class StationPortCheckerValidator extends ConstraintValidator
$this->configuration = $configuration;
}
public function validate($station, Constraint $constraint): void
public function validate($value, Constraint $constraint): void
{
if (!$constraint instanceof StationPortChecker) {
throw new UnexpectedTypeException($constraint, StationPortChecker::class);
}
if (!$station instanceof Entity\Station) {
throw new UnexpectedTypeException($station, Entity\Station::class);
if (!$value instanceof Entity\Station) {
throw new UnexpectedTypeException($value, Entity\Station::class);
}
$frontend_config = $station->getFrontendConfig();
$backend_config = $station->getBackendConfig();
$frontend_config = $value->getFrontendConfig();
$backend_config = $value->getBackendConfig();
$ports_to_check = [
'frontend_config_port' => $frontend_config->getPort(),
@ -35,16 +35,16 @@ class StationPortCheckerValidator extends ConstraintValidator
'backend_config_telnet_port' => $backend_config->getTelnetPort(),
];
$used_ports = $this->configuration->getUsedPorts($station);
$used_ports = $this->configuration->getUsedPorts($value);
$message = __('The port %s is in use by another station.', '{{ port }}');
foreach ($ports_to_check as $port_path => $value) {
if (null === $value) {
foreach ($ports_to_check as $port_path => $port) {
if (null === $port) {
continue;
}
$port = (int)$value;
$port = (int)$port;
if (isset($used_ports[$port])) {
$this->context->buildViolation($message)
->setParameter('{{ port }}', (string)$port)

View File

@ -18,19 +18,19 @@ class StorageLocationValidator extends ConstraintValidator
) {
}
public function validate($storageLocation, Constraint $constraint): void
public function validate($value, Constraint $constraint): void
{
if (!$constraint instanceof StorageLocation) {
throw new UnexpectedTypeException($constraint, StorageLocation::class);
}
if (!($storageLocation instanceof Entity\StorageLocation)) {
throw new UnexpectedTypeException($storageLocation, Entity\StorageLocation::class);
if (!($value instanceof Entity\StorageLocation)) {
throw new UnexpectedTypeException($value, Entity\StorageLocation::class);
}
// Ensure this storage location validates.
try {
$storageLocation->validate();
$value->validate();
} catch (Exception $e) {
$message = __(
'Storage location %s could not be validated: %s',
@ -39,7 +39,7 @@ class StorageLocationValidator extends ConstraintValidator
);
$this->context->buildViolation($message)
->setParameter('{{ storageLocation }}', (string)$storageLocation)
->setParameter('{{ storageLocation }}', (string)$value)
->setParameter('{{ error }}', $e->getMessage())
->addViolation();
}
@ -49,16 +49,16 @@ class StorageLocationValidator extends ConstraintValidator
->select('sl')
->from(Entity\StorageLocation::class, 'sl')
->where('sl.type = :type')
->setParameter('type', $storageLocation->getType())
->setParameter('type', $value->getType())
->andWhere('sl.adapter = :adapter')
->setParameter('adapter', $storageLocation->getAdapter());
->setParameter('adapter', $value->getAdapter());
if (null !== $storageLocation->getId()) {
if (null !== $value->getId()) {
$qb->andWhere('sl.id != :id')
->setParameter('id', $storageLocation->getId());
->setParameter('id', $value->getId());
}
$storageLocationUri = $storageLocation->getUri();
$storageLocationUri = $value->getUri();
/** @var Entity\StorageLocation $row */
foreach ($qb->getQuery()->toIterable() as $row) {
@ -69,7 +69,7 @@ class StorageLocationValidator extends ConstraintValidator
);
$this->context->buildViolation($message)
->setParameter('{{ storageLocation }}', (string)$storageLocation)
->setParameter('{{ storageLocation }}', (string)$value)
->addViolation();
break;

View File

@ -42,12 +42,12 @@ class UniqueEntityValidator extends ConstraintValidator
}
/**
* @param object $entity
* @param object $value
*
* @throws UnexpectedTypeException
* @throws ConstraintDefinitionException
*/
public function validate($entity, Constraint $constraint): void
public function validate($value, Constraint $constraint): void
{
if (!$constraint instanceof UniqueEntity) {
throw new UnexpectedTypeException($constraint, UniqueEntity::class);
@ -67,11 +67,11 @@ class UniqueEntityValidator extends ConstraintValidator
throw new ConstraintDefinitionException('At least one field has to be specified.');
}
if (null === $entity) {
if (null === $value) {
return;
}
$class = $this->em->getClassMetadata(get_class($entity));
$class = $this->em->getClassMetadata(get_class($value));
$criteria = [];
$hasNullValue = false;
@ -86,7 +86,7 @@ class UniqueEntityValidator extends ConstraintValidator
);
}
$fieldValue = $class->reflFields[$fieldName]->getValue($entity);
$fieldValue = $class->reflFields[$fieldName]->getValue($value);
if (null === $fieldValue) {
$hasNullValue = true;
@ -126,7 +126,7 @@ class UniqueEntityValidator extends ConstraintValidator
$repository = $this->em->getRepository($constraint->entityClass);
$supportedClass = $repository->getClassName();
if (!$entity instanceof $supportedClass) {
if (!$value instanceof $supportedClass) {
throw new ConstraintDefinitionException(
sprintf(
'The "%s" entity repository does not support the "%s" entity. The entity should be '
@ -138,7 +138,7 @@ class UniqueEntityValidator extends ConstraintValidator
);
}
} else {
$repository = $this->em->getRepository(get_class($entity));
$repository = $this->em->getRepository(get_class($value));
}
$result = $repository->{$constraint->repositoryMethod}($criteria);
@ -168,7 +168,7 @@ class UniqueEntityValidator extends ConstraintValidator
* which is the same as the entity being validated, the criteria is
* unique.
*/
if (!$result || (1 === count($result) && current($result) === $entity)) {
if (!$result || (1 === count($result) && current($result) === $value)) {
return;
}

View File

@ -5,6 +5,7 @@ namespace App\Webhook\Connector;
use App\Entity;
use App\Utilities;
use GuzzleHttp\Client;
use JetBrains\PhpStorm\Pure;
use Monolog\Logger;
use Symfony\Component\Validator\Constraints\UrlValidator;
@ -48,7 +49,7 @@ abstract class AbstractConnector implements ConnectorInterface
return true;
}
protected function webhookShouldTrigger(Entity\StationWebhook $webhook, array $triggers = []): bool
#[Pure] protected function webhookShouldTrigger(Entity\StationWebhook $webhook, array $triggers = []): bool
{
$webhookTriggers = $webhook->getTriggers();
if (empty($webhookTriggers)) {
@ -105,7 +106,7 @@ abstract class AbstractConnector implements ConnectorInterface
protected function getValidUrl(?string $url_string = null): ?string
{
$url = trim($url_string);
$pattern = sprintf(UrlValidator::PATTERN, implode('|', ['http', 'https']));
$pattern = sprintf(UrlValidator::PATTERN, 'http|https');
return (preg_match($pattern, $url)) ? $url : null;
}
}

View File

@ -3,7 +3,6 @@
namespace App\Webhook\Connector;
use App\Entity;
use App\Event\SendWebhooks;
interface ConnectorInterface
{

View File

@ -152,6 +152,7 @@ class Discord extends AbstractConnector
return true;
}
/** @noinspection HttpUrlsUsage */
protected function getImageUrl(?string $url = null): ?string
{
$url = $this->getValidUrl($url);

View File

@ -3,7 +3,6 @@
namespace App\Webhook\Connector;
use App\Entity;
use App\Event\SendWebhooks;
use App\Radio\Adapters;
use Doctrine\ORM\EntityManagerInterface;
use GuzzleHttp\Client;

View File

@ -3,7 +3,6 @@
namespace App\Webhook\Connector;
use App\Entity;
use App\Event\SendWebhooks;
use GuzzleHttp\Exception\TransferException;
/**

View File

@ -3,7 +3,6 @@
namespace App\Webhook\Connector;
use App\Entity;
use App\Event\SendWebhooks;
use GuzzleHttp\Exception\TransferException;
class TuneIn extends AbstractConnector

View File

@ -3,7 +3,6 @@
namespace App\Webhook\Connector;
use App\Entity;
use App\Event\SendWebhooks;
use Doctrine\ORM\EntityManagerInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\TransferException;