1*1729dd47SHenrik Yllemo<?php 2*1729dd47SHenrik Yllemoif (!defined('DOKU_INC')) die(); 3*1729dd47SHenrik Yllemo 4*1729dd47SHenrik Yllemoclass admin_plugin_skillforge extends DokuWiki_Admin_Plugin { 5*1729dd47SHenrik Yllemo private $message = ''; 6*1729dd47SHenrik Yllemo private $download = ''; 7*1729dd47SHenrik Yllemo 8*1729dd47SHenrik Yllemo public function forAdminOnly() { return true; } 9*1729dd47SHenrik Yllemo public function getMenuSort() { return 250; } 10*1729dd47SHenrik Yllemo 11*1729dd47SHenrik Yllemo public function handle() { 12*1729dd47SHenrik Yllemo if ($_SERVER['REQUEST_METHOD'] === 'POST' && checkSecurityToken()) { 13*1729dd47SHenrik Yllemo try { 14*1729dd47SHenrik Yllemo /** @var helper_plugin_skillforge $helper */ 15*1729dd47SHenrik Yllemo $helper = plugin_load('helper', 'skillforge'); 16*1729dd47SHenrik Yllemo $result = $helper->exportNamespace( 17*1729dd47SHenrik Yllemo $_POST['sf_namespace'], 18*1729dd47SHenrik Yllemo null, 19*1729dd47SHenrik Yllemo array( 20*1729dd47SHenrik Yllemo 'recursive' => !empty($_POST['sf_recursive']), 21*1729dd47SHenrik Yllemo 'include_media' => !empty($_POST['sf_include_media']) 22*1729dd47SHenrik Yllemo ) 23*1729dd47SHenrik Yllemo ); 24*1729dd47SHenrik Yllemo $this->message = 'Export created: ' . hsc($result['name']) . ' (' . (int)$result['count'] . ' pages).'; 25*1729dd47SHenrik Yllemo $this->download = $result['name']; 26*1729dd47SHenrik Yllemo } catch (Exception $e) { 27*1729dd47SHenrik Yllemo $this->message = 'SkillForge export failed: ' . hsc($e->getMessage()); 28*1729dd47SHenrik Yllemo } 29*1729dd47SHenrik Yllemo } 30*1729dd47SHenrik Yllemo } 31*1729dd47SHenrik Yllemo 32*1729dd47SHenrik Yllemo public function html() { 33*1729dd47SHenrik Yllemo /** @var helper_plugin_skillforge $helper */ 34*1729dd47SHenrik Yllemo $helper = plugin_load('helper', 'skillforge'); 35*1729dd47SHenrik Yllemo $namespaces = $helper ? $helper->listNamespaces() : array(); 36*1729dd47SHenrik Yllemo $selectedNamespace = isset($_POST['sf_namespace']) ? $_POST['sf_namespace'] : ''; 37*1729dd47SHenrik Yllemo 38*1729dd47SHenrik Yllemo ptln('<h1>SkillForge</h1>'); 39*1729dd47SHenrik Yllemo ptln('<p>Export a DokuWiki namespace as an AI-ready Markdown package with SKILL.md, index.md, skill.json and optional media. ZIP creation uses an internal ZIP writer and does not require PHP ZipArchive.</p>'); 40*1729dd47SHenrik Yllemo if ($this->message) ptln('<div class="info">' . $this->message . '</div>'); 41*1729dd47SHenrik Yllemo if ($this->download) { 42*1729dd47SHenrik Yllemo global $ID; 43*1729dd47SHenrik Yllemo $url = wl($ID ?: 'start', array( 44*1729dd47SHenrik Yllemo 'do' => 'skillforge_download', 45*1729dd47SHenrik Yllemo 'sf_file' => $this->download, 46*1729dd47SHenrik Yllemo 'sectok' => getSecurityToken() 47*1729dd47SHenrik Yllemo ), false, '&'); 48*1729dd47SHenrik Yllemo ptln('<p><a class="button" href="' . hsc($url) . '">Download ZIP</a></p>'); 49*1729dd47SHenrik Yllemo ptln('<p><small>If the button does not start a download, copy/open this link in a new tab: <code>' . hsc($url) . '</code></small></p>'); 50*1729dd47SHenrik Yllemo } 51*1729dd47SHenrik Yllemo ptln('<form method="post">'); 52*1729dd47SHenrik Yllemo formSecurityToken(); 53*1729dd47SHenrik Yllemo ptln('<table class="inline">'); 54*1729dd47SHenrik Yllemo ptln('<tr><th>Namespace</th><td>'); 55*1729dd47SHenrik Yllemo if ($namespaces) { 56*1729dd47SHenrik Yllemo ptln('<select name="sf_namespace" required>'); 57*1729dd47SHenrik Yllemo ptln('<option value="">-- Select namespace --</option>'); 58*1729dd47SHenrik Yllemo foreach ($namespaces as $ns) { 59*1729dd47SHenrik Yllemo $sel = ($ns === $selectedNamespace) ? ' selected' : ''; 60*1729dd47SHenrik Yllemo ptln('<option value="' . hsc($ns) . '"' . $sel . '>' . hsc($ns) . '</option>'); 61*1729dd47SHenrik Yllemo } 62*1729dd47SHenrik Yllemo ptln('</select>'); 63*1729dd47SHenrik Yllemo } else { 64*1729dd47SHenrik Yllemo ptln('<input type="text" name="sf_namespace" value="" placeholder="ai:prompting" required>'); 65*1729dd47SHenrik Yllemo ptln('<br><small>No namespaces were found automatically. Enter a namespace manually.</small>'); 66*1729dd47SHenrik Yllemo } 67*1729dd47SHenrik Yllemo ptln('</td></tr>'); 68*1729dd47SHenrik Yllemo ptln('<tr><th>SKILL source page</th><td><code>' . hsc($this->getConf('default_skill_source')) . '</code> <small>Configured in plugin settings.</small></td></tr>'); 69*1729dd47SHenrik Yllemo ptln('<tr><th>Recursive</th><td><label><input type="checkbox" name="sf_recursive" value="1" checked> Include subnamespaces</label></td></tr>'); 70*1729dd47SHenrik Yllemo ptln('<tr><th>Media</th><td><label><input type="checkbox" name="sf_include_media" value="1" checked> Include media namespace files</label></td></tr>'); 71*1729dd47SHenrik Yllemo ptln('</table>'); 72*1729dd47SHenrik Yllemo ptln('<p><button type="submit">Forge Package</button></p>'); 73*1729dd47SHenrik Yllemo ptln('</form>'); 74*1729dd47SHenrik Yllemo ptln('<h2>Metadata in configured source page</h2>'); 75*1729dd47SHenrik Yllemo ptln('<pre><frontmatter>\nname: my-skill\ndescription: What this skill helps the AI do.\nversion: 1.0.0\ntags:\n - ai\n - dokuwiki\n</frontmatter></pre>'); 76*1729dd47SHenrik Yllemo } 77*1729dd47SHenrik Yllemo} 78