Toolvana: production-ready media tools platform (CodeIgniter 4)

- 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
This commit is contained in:
deepseek
2026-08-23 07:10:30 +00:00
commit beaf0e1f37
217 changed files with 19619 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
<?= view('partials/admin_nav') ?>
<h1 style="font-size:1.7rem;margin-bottom:1rem"><?= $tool ? 'Edit tool' : 'New tool' ?></h1>
<?php if ($e = session()->getFlashdata('error')): ?><p class="notice error"><?= esc($e) ?></p><?php endif ?>
<form method="post" action="/admin/tools<?= $tool ? '/' . (int)$tool['id'] : '' ?>" class="tool-panel" style="max-width:760px">
<?= csrf_field() ?>
<input type="hidden" name="_method" value="">
<div class="opt-grid" style="padding-top:0">
<div><label>Name *</label><input type="text" name="name" required value="<?= esc($tool['name'] ?? '') ?>"></div>
<div><label>Slug *</label><input type="text" name="slug" required pattern="[a-z0-9-]+" value="<?= esc($tool['slug'] ?? '') ?>"></div>
<div><label>Category</label>
<select name="category_id"><?php foreach ($categories as $c): ?><option value="<?= (int)$c['id'] ?>" <?= ($tool && (int)$tool['category_id']===(int)$c['id'])?'selected':'' ?>><?= esc($c['name']) ?></option><?php endforeach ?></select></div>
<div><label>Kind</label>
<select name="kind"><?php foreach (['upload','url','text'] as $k): ?><option value="<?= $k ?>" <?= ($tool['kind'] ?? '')===$k?'selected':'' ?>><?= $k ?></option><?php endforeach ?></select></div>
<div><label>Operation</label><input type="text" name="operation" value="<?= esc($tool['operation'] ?? 'convert') ?>" placeholder="convert / compress / trim …"></div>
<div><label>Primary format in</label><input type="text" name="format_in" value="" placeholder="mp4"></div>
<div><label>Primary format out</label><input type="text" name="format_out" value="" placeholder="mp3"></div>
<div><label>Status</label>
<select name="status"><?php foreach (['active','draft','inactive'] as $st): ?><option value="<?= $st ?>" <?= ($tool['status'] ?? 'active')===$st?'selected':'' ?>><?= $st ?></option><?php endforeach ?></select></div>
</div>
<div style="margin-top:1rem"><label>Short description</label>
<textarea name="short_description" class="tool-area" style="min-height:60px"><?= esc($tool['short_description'] ?? '') ?></textarea></div>
<div class="opt-grid" style="margin-top:1rem">
<div><label>SEO title</label><input type="text" name="seo_title" value="<?= esc($tool['seo_title'] ?? '') ?>"></div>
<div><label>H1</label><input type="text" name="h1" value="<?= esc($tool['h1'] ?? '') ?>"></div>
<div><label>Aliases (comma separated)</label><input type="text" name="aliases" value=""></div>
<div><label>Popularity</label><input type="number" name="popularity" value="<?= (int)($tool['popularity'] ?? 1000) ?>"></div>
</div>
<div style="margin-top:1rem"><label>Meta description</label>
<textarea name="seo_description" class="tool-area" style="min-height:60px"><?= esc($tool['seo_description'] ?? '') ?></textarea></div>
<div style="margin-top:1rem"><label>Intro paragraph</label>
<textarea name="intro" class="tool-area" style="min-height:80px"><?= esc($tool['intro'] ?? '') ?></textarea></div>
<p class="hint" style="margin-top:.8rem">Leave format fields blank for non-converter tools — SEO copy is auto-generated from the format pair where possible. Critical SEO checks block publishing.</p>
<button class="btn-primary" type="submit" style="margin-top:1rem"><?= $tool ? 'Save changes' : 'Create tool' ?></button>
</form>