- 134-tool registry with programmatic SEO (unique titles/H1/descriptions, JSON-LD graphs, sitemap index, canonical 301 enforcement via required filter) - DB-backed job queue (SKIP LOCKED) with drivers: Ffmpeg, Images (GD), Pdf (qpdf/gs/poppler), Youtube (thumbnails), Qr (server-side PNG) - Security: SSRF guard, MIME validation, rate limits, API-key auth, bcrypt admin login, security headers - Admin panel: dashboard, tools/categories/guides CRUD, SEO audit, analytics, job inspector with retry, system health, feature flags - Docker deployment (nginx + web/api FPM pools + scalable workers), PHPUnit suite (19 tests / 1139 assertions), PWA manifest + service worker
104 lines
3.6 KiB
PHP
104 lines
3.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Config;
|
|
|
|
use CodeIgniter\Config\BaseConfig;
|
|
|
|
/**
|
|
* Site-wide configuration for Toolvana.
|
|
*
|
|
* Everything an operator is likely to tune lives here or in .env
|
|
* (values in .env override these defaults via the standard
|
|
* `site.*` namespace).
|
|
*/
|
|
class Site extends BaseConfig
|
|
{
|
|
/**
|
|
* -----------------------------------------------------------------
|
|
* Brand / identity
|
|
* -----------------------------------------------------------------
|
|
*/
|
|
public string $name = 'Toolvana';
|
|
public string $tagline = 'Your free online media toolbox.';
|
|
public string $description = 'Fast, simple and free tools for downloading, converting, compressing and editing media online.';
|
|
public string $twitter = '@toolvana';
|
|
|
|
/**
|
|
* -----------------------------------------------------------------
|
|
* Internationalization architecture.
|
|
*
|
|
* English is the primary (default, un-prefixed) locale. Additional
|
|
* locales are only enabled once real localized content exists — the
|
|
* routes layer already supports `{locale}` URL segments and the SEO
|
|
* library emits hreflang/canonical tags for every enabled locale.
|
|
* Never enable a locale whose content has not been human-reviewed.
|
|
*/
|
|
public string $defaultLocale = 'en';
|
|
|
|
/** @var array<string,string> locale => native label */
|
|
public array $locales = [
|
|
'en' => 'English',
|
|
];
|
|
|
|
/**
|
|
* -----------------------------------------------------------------
|
|
* Media processing limits & retention
|
|
* -----------------------------------------------------------------
|
|
*/
|
|
public int $maxUploadMb = 512;
|
|
public int $maxJobsPerHourIp = 20;
|
|
public int $maxJobsPerHourSession = 40;
|
|
public int $maxConcurrentSession = 2;
|
|
public int $retentionHours = 2;
|
|
public int $maxProcessingSeconds = 900;
|
|
public int $queueMaxLength = 500;
|
|
|
|
/**
|
|
* -----------------------------------------------------------------
|
|
* Binary locations. The pipeline refuses to enqueue jobs that need a
|
|
* missing binary and the tool page shows an honest "temporarily
|
|
* unavailable" state instead of failing after upload.
|
|
*/
|
|
public array $binaries = [
|
|
'ffmpeg' => '/usr/bin/ffmpeg',
|
|
'ffprobe' => '/usr/bin/ffprobe',
|
|
'convert' => '/usr/bin/convert',
|
|
'pdftoppm' => '/usr/bin/pdftoppm',
|
|
'pdftotext' => '/usr/bin/pdftotext',
|
|
'qpdf' => '/usr/bin/qpdf',
|
|
'gs' => '/usr/bin/gs',
|
|
'yt-dlp' => '/usr/local/bin/yt-dlp',
|
|
];
|
|
|
|
/**
|
|
* Downloading from YouTube requires yt-dlp AND explicit operator opt-in,
|
|
* both for legal review and because platform terms evolve. When off,
|
|
* affected tools render a clear notice and every other tool keeps
|
|
* working. Thumbnail/metadata/embed tools never require it.
|
|
*/
|
|
public bool $ytDlpEnabled = false;
|
|
|
|
/** Extra hosts allowed for direct media URL fetches (SSRF allowlist). */
|
|
public array $urlFetchAllowlist = [
|
|
'i.ytimg.com', 'img.youtube.com', 'yt3.ggpht.com',
|
|
];
|
|
|
|
/**
|
|
* -----------------------------------------------------------------
|
|
* Monetization (kept modular; disabled by default)
|
|
* -----------------------------------------------------------------
|
|
*/
|
|
public bool $adsEnabled = false;
|
|
|
|
/** @var array<string,string> placement => snippet (loaded by view) */
|
|
public array $adSlots = [];
|
|
|
|
/**
|
|
* -----------------------------------------------------------------
|
|
* Analytics beacon sampling: 100 = record every event.
|
|
*/
|
|
public int $analyticsSampleRate = 100;
|
|
}
|