<?php
use App\Facades\License;
use App\Services\SettingService;
use App\Values\Branding;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Webmozart\Assert\Assert;
/**
* Get a URL for static file requests.
* If this installation of Koel has a CDN_URL configured, use it as the base.
* Otherwise, just use a full URL to the asset.
*
* @param string|null $name The optional resource name/path
*/
function static_url(?string $name = null): string
{
$cdnUrl = trim(config('koel.cdn.url'), '/ ');
return $cdnUrl ? $cdnUrl . '/' . trim(ltrim($name, '/')) : trim(asset($name));
}
function base_url(): string
{
return app()->runningUnitTests() ? config('app.url') : asset('');
}
function image_storage_path(?string $fileName, ?string $default = null): ?string
{
return $fileName ? public_path(config('koel.image_storage_dir') . $fileName) : $default;
}
function image_storage_url(?string $fileName, ?string $default = null): ?string
{
return $fileName ? static_url(config('koel.image_storage_dir') . $fileName) : $default;
}
function artifact_path(?string $subPath = null, $ensureDirectoryExists = true): string
{
$path = Str::finish(config('koel.artifacts_path'), DIRECTORY_SEPARATOR);
if ($subPath) {
$path .= ltrim($subPath, DIRECTORY_SEPARATOR);
}
if ($ensureDirectoryExists) {
File::ensureDirectoryExists(Str::endsWith($path, DIRECTORY_SEPARATOR) ? $path : dirname($path));
}
return $path;
}
function koel_version(): string
{
return trim(File::get(base_path('.version')));
}
function rescue_if($condition, callable $callback, $default = null): mixed
{
return value($condition) ? rescue($callback, $default) : $default;
}
function rescue_unless($condition, callable $callback, $default = null): mixed
{
return rescue_if(!$condition, $callback, $default);
}
function gravatar(string $email, int $size = 192): string
{
$url = config('services.gravatar.url');
$default = config('services.gravatar.default');
return sprintf("%s/%s?s=$size&d=$default", $url, md5(Str::lower($email)));
}
function avatar_or_gravatar(?string $avatar, string $email): string
{
if (!$avatar) {
return gravatar($email);
}
if (Str::startsWith($avatar, ['http://', 'https://'])) {
return $avatar;
}
return image_storage_url($avatar);
}
/**
* A quick check to determine if a mailer is configured.
* This is not bulletproof but should work in most cases.
*/
function mailer_configured(): bool
{
return config('mail.default') && !in_array(config('mail.default'), ['log', 'array'], true);
}
/** @return array<string> */
function collect_sso_providers(): array
{
if (License::isCommunity()) {
return [];
}
$providers = [];
if (
config('services.google.client_id')
&& config('services.google.client_secret')
&& config('services.google.hd')
) {
$providers[] = 'Google';
}
return $providers;
}
function get_mtime(string|SplFileInfo $path): int
{
$path = is_string($path) ? $path : $path->getPathname();
// Workaround for #344, where getMTime() fails for certain files with Unicode names on Windows.
return rescue(static fn () => File::lastModified($path)) ?? time();
}
/**
* Simple, non-cryptographically secure hash function for strings.
* This is used for generating hashes for identifiers that do not require high security.
*/
function simple_hash(?string $string): string
{
return md5("koel-hash:$string");
}
function is_image(string $path): bool
{
return rescue(static fn () => (bool) exif_imagetype($path)) ?? false;
}
/**
* @param string|int ...$parts
*/
function cache_key(...$parts): string
{
return simple_hash(implode('.', $parts));
}
/**
* @return array<string>
*/
function collect_accepted_audio_extensions(): array
{
return array_values(
collect(array_values(config('koel.streaming.supported_mime_types')))
->flatten()
->unique()
->map(static fn (string $ext) => Str::lower($ext))
->toArray()
);
}
function find_ffmpeg_path(): ?string
{
// for Unix-like systems, we can use the `which` command
if (PHP_OS_FAMILY !== 'Windows') {
$path = trim(shell_exec('which ffmpeg') ?: '');
return $path && is_executable($path) ? $path : null;
}
// for Windows, we can check `where` command
$path = trim(shell_exec('where ffmpeg') ?: '');
if ($path && is_executable($path)) {
return $path;
}
// finally, check the PATH environment variable
$path = getenv('PATH');
if ($path) {
$paths = explode(PATH_SEPARATOR, $path);
foreach ($paths as $dir) {
$ffmpegPath = rtrim($dir, '\\/') . DIRECTORY_SEPARATOR . 'ffmpeg.exe';
if (is_executable($ffmpegPath)) {
return $ffmpegPath;
}
}
}
return null;
}
function koel_branding(?string $key = null): Branding|string|null
{
Assert::inArray($key, [null, 'name', 'logo', 'cover']);
$branding = once(static function (): Branding {
/** @var SettingService $service */
$service = app(SettingService::class);
return $service->getBranding();
});
if (!$key) {
return $branding;
}
return Arr::get($branding->toArray(), $key);
}