255 lines
14 KiB
PHP
255 lines
14 KiB
PHP
<?php
|
||
/**
|
||
* Admin-Seite: Gitea Wiki Importer
|
||
*/
|
||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||
|
||
$wikis = wmw_get_wikis();
|
||
$result = null;
|
||
$preview = null;
|
||
|
||
// ── Handle Preview ────────────────────────────────────────────────────────────
|
||
if ( isset( $_POST['wmw_gitea_preview'] ) && wp_verify_nonce( $_POST['wmw_gitea_nonce'] ?? '', 'wmw_gitea_import' ) && current_user_can( 'manage_options' ) ) {
|
||
|
||
$gitea_url = esc_url_raw( $_POST['gitea_url'] ?? '' );
|
||
$owner = sanitize_text_field( $_POST['gitea_owner'] ?? '' );
|
||
$repo = sanitize_text_field( $_POST['gitea_repo'] ?? '' );
|
||
$token = sanitize_text_field( $_POST['gitea_token'] ?? '' );
|
||
|
||
if ( $gitea_url && $owner && $repo ) {
|
||
$importer = new WMW_Gitea_Importer( $gitea_url, $owner, $repo, $token );
|
||
$preview = $importer->list_pages();
|
||
}
|
||
}
|
||
|
||
// ── Handle Import ─────────────────────────────────────────────────────────────
|
||
if ( isset( $_POST['wmw_gitea_import'] ) && wp_verify_nonce( $_POST['wmw_gitea_nonce'] ?? '', 'wmw_gitea_import' ) && current_user_can( 'manage_options' ) ) {
|
||
|
||
$gitea_url = esc_url_raw( $_POST['gitea_url'] ?? '' );
|
||
$owner = sanitize_text_field( $_POST['gitea_owner'] ?? '' );
|
||
$repo = sanitize_text_field( $_POST['gitea_repo'] ?? '' );
|
||
$token = sanitize_text_field( $_POST['gitea_token'] ?? '' );
|
||
$wiki_id = absint( $_POST['wmw_wiki_id'] ?? 0 );
|
||
$skip_pages = array_map( 'sanitize_text_field', array_filter( explode( "\n", str_replace( "\r", '', $_POST['skip_pages'] ?? '' ) ) ) );
|
||
$update_exist = isset( $_POST['update_existing'] );
|
||
|
||
if ( $gitea_url && $owner && $repo && $wiki_id ) {
|
||
$importer = new WMW_Gitea_Importer( $gitea_url, $owner, $repo, $token );
|
||
$result = $importer->import_all( $wiki_id, $skip_pages, $update_exist );
|
||
} else {
|
||
$result = array( 'errors' => array( 'Bitte alle Pflichtfelder ausfüllen.' ) );
|
||
}
|
||
}
|
||
?>
|
||
<div class="wrap wmw-admin-wrap">
|
||
|
||
<div class="wmw-admin-header">
|
||
<div class="wmw-admin-header__logo">
|
||
<span class="wmw-admin-header__icon">🐙</span>
|
||
<div>
|
||
<h1>Gitea Wiki Importer</h1>
|
||
<p>Importiere Wiki-Seiten direkt aus deiner Gitea-Instanz in WP Multi Wiki.</p>
|
||
</div>
|
||
</div>
|
||
<a href="<?php echo admin_url('admin.php?page=wp-multi-wiki'); ?>" class="button">← Dashboard</a>
|
||
</div>
|
||
|
||
<?php if ( $result !== null ) : ?>
|
||
<div class="wmw-import-result <?php echo empty($result['errors']) ? 'wmw-import-result--success' : 'wmw-import-result--warn'; ?>">
|
||
<h3>📊 Import-Ergebnis</h3>
|
||
<div class="wmw-import-stats">
|
||
<div class="wmw-import-stat">
|
||
<span class="wmw-import-stat__num"><?php echo $result['imported']; ?></span>
|
||
<span>Neu importiert</span>
|
||
</div>
|
||
<div class="wmw-import-stat">
|
||
<span class="wmw-import-stat__num"><?php echo $result['updated']; ?></span>
|
||
<span>Aktualisiert</span>
|
||
</div>
|
||
<div class="wmw-import-stat">
|
||
<span class="wmw-import-stat__num"><?php echo $result['skipped']; ?></span>
|
||
<span>Übersprungen</span>
|
||
</div>
|
||
</div>
|
||
<?php if ( ! empty( $result['errors'] ) ) : ?>
|
||
<div class="wmw-import-errors">
|
||
<strong>⚠️ Fehler:</strong>
|
||
<ul><?php foreach( $result['errors'] as $e ): ?><li><?php echo esc_html($e); ?></li><?php endforeach; ?></ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php if ( isset($_POST['wmw_wiki_id']) ) : ?>
|
||
<a href="<?php echo admin_url('admin.php?page=wmw-articles&wiki_id='.absint($_POST['wmw_wiki_id'])); ?>" class="button button-primary" style="margin-top:12px">
|
||
📋 Importierte Artikel ansehen
|
||
</a>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="wmw-form-layout">
|
||
<div class="wmw-form-main">
|
||
|
||
<form method="post" id="wmw-gitea-form">
|
||
<?php wp_nonce_field( 'wmw_gitea_import', 'wmw_gitea_nonce' ); ?>
|
||
|
||
<div class="wmw-card">
|
||
<h3 class="wmw-card__title">🔗 Gitea-Quelle</h3>
|
||
|
||
<div class="wmw-field">
|
||
<label class="wmw-label">Gitea-Server URL <span class="required">*</span></label>
|
||
<input type="url" name="gitea_url" class="large-text" required
|
||
value="<?php echo esc_attr( $_POST['gitea_url'] ?? 'https://git.viper.ipv64.net' ); ?>"
|
||
placeholder="https://git.viper.ipv64.net">
|
||
<p class="description">Nur die Basis-URL deiner Gitea-Instanz (ohne /api oder /wiki).</p>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px">
|
||
<div class="wmw-field">
|
||
<label class="wmw-label">Owner / Nutzer <span class="required">*</span></label>
|
||
<input type="text" name="gitea_owner" class="regular-text" required
|
||
value="<?php echo esc_attr( $_POST['gitea_owner'] ?? 'M_Viper' ); ?>"
|
||
placeholder="M_Viper">
|
||
</div>
|
||
<div class="wmw-field">
|
||
<label class="wmw-label">Repository <span class="required">*</span></label>
|
||
<input type="text" name="gitea_repo" class="regular-text" required
|
||
value="<?php echo esc_attr( $_POST['gitea_repo'] ?? 'NexusLobby' ); ?>"
|
||
placeholder="NexusLobby">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wmw-field">
|
||
<label class="wmw-label">Access Token <span class="description">(nur für private Repos nötig)</span></label>
|
||
<input type="password" name="gitea_token" class="regular-text"
|
||
value="<?php echo esc_attr( $_POST['gitea_token'] ?? '' ); ?>"
|
||
placeholder="gitea_token_…">
|
||
<p class="description">Token unter Gitea → Einstellungen → Anwendungen → Access Token erstellen.</p>
|
||
</div>
|
||
|
||
<button type="submit" name="wmw_gitea_preview" class="button button-secondary">
|
||
🔍 Seiten vorab laden
|
||
</button>
|
||
</div>
|
||
|
||
<?php if ( $preview !== null ) : ?>
|
||
<div class="wmw-card">
|
||
<h3 class="wmw-card__title">📋 Gefundene Wiki-Seiten</h3>
|
||
<?php if ( is_wp_error( $preview ) ) : ?>
|
||
<div class="notice notice-error inline"><p>❌ <?php echo esc_html( $preview->get_error_message() ); ?></p></div>
|
||
<?php elseif ( empty( $preview ) ) : ?>
|
||
<p class="description">Keine Seiten gefunden.</p>
|
||
<?php else : ?>
|
||
<div class="wmw-preview-grid">
|
||
<?php foreach( $preview as $p ): ?>
|
||
<div class="wmw-preview-item">
|
||
<span class="wmw-preview-item__icon">📄</span>
|
||
<span class="wmw-preview-item__title"><?php echo esc_html($p['title']); ?></span>
|
||
<span class="wmw-preview-item__date"><?php echo esc_html(substr($p['last_updated'],0,10)); ?></span>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<p class="description" style="margin-top:10px">✅ <?php echo count($preview); ?> Seiten bereit zum Import.</p>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="wmw-card">
|
||
<h3 class="wmw-card__title">🎯 Import-Ziel</h3>
|
||
|
||
<div class="wmw-field">
|
||
<label class="wmw-label">Ziel-Wiki <span class="required">*</span></label>
|
||
<select name="wmw_wiki_id" class="regular-text" required>
|
||
<option value="">— Wiki wählen —</option>
|
||
<?php foreach( $wikis as $w ): ?>
|
||
<option value="<?php echo $w->ID; ?>" <?php selected( absint($_POST['wmw_wiki_id'] ?? 0), $w->ID ); ?>>
|
||
<?php echo wmw_get_wiki_icon($w->ID); ?> <?php echo esc_html($w->post_title); ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<p class="description">Alle Seiten werden als Artikel in diesem Wiki angelegt.</p>
|
||
</div>
|
||
|
||
<div class="wmw-field">
|
||
<label class="wmw-label">Seiten überspringen <span class="description">(eine pro Zeile)</span></label>
|
||
<textarea name="skip_pages" rows="5" class="large-text"><?php
|
||
echo esc_textarea( $_POST['skip_pages'] ?? "Home\n_Sidebar" );
|
||
?></textarea>
|
||
<p class="description">Diese Seiten werden nicht importiert (z.B. Home, _Sidebar).</p>
|
||
</div>
|
||
|
||
<div class="wmw-field">
|
||
<label class="wmw-checkbox">
|
||
<input type="checkbox" name="update_existing" value="1" <?php checked( isset($_POST['update_existing']) ); ?>>
|
||
Bereits vorhandene Artikel aktualisieren
|
||
</label>
|
||
<p class="description" style="margin-left:22px">Wenn deaktiviert, werden bestehende Artikel übersprungen.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wmw-card">
|
||
<button type="submit" name="wmw_gitea_import" class="button button-primary button-large" style="width:100%">
|
||
🚀 Wiki jetzt importieren
|
||
</button>
|
||
<p class="description" style="text-align:center;margin-top:8px">
|
||
Der Import kann je nach Wiki-Größe einige Sekunden dauern.
|
||
</p>
|
||
</div>
|
||
|
||
</form>
|
||
</div>
|
||
|
||
<div class="wmw-form-sidebar">
|
||
<div class="wmw-card">
|
||
<h3 class="wmw-card__title">ℹ️ Wie funktioniert's?</h3>
|
||
<ol style="margin:0;padding-left:18px;font-size:13px;line-height:2">
|
||
<li>Gitea-URL, Owner & Repo eingeben</li>
|
||
<li>Auf <strong>Seiten vorab laden</strong> klicken</li>
|
||
<li>Ziel-Wiki auswählen</li>
|
||
<li>Seiten auswählen die übersprungen werden sollen</li>
|
||
<li><strong>Importieren</strong> klicken</li>
|
||
</ol>
|
||
</div>
|
||
<div class="wmw-card">
|
||
<h3 class="wmw-card__title">🔐 Private Repos</h3>
|
||
<p style="font-size:13px">Für private Repositories brauchst du einen <strong>Access Token</strong>:</p>
|
||
<ol style="margin:0;padding-left:18px;font-size:13px;line-height:2">
|
||
<li>In Gitea anmelden</li>
|
||
<li>Einstellungen → Anwendungen</li>
|
||
<li>„Token generieren" mit <code>read:wiki</code> Scope</li>
|
||
<li>Token oben eintragen</li>
|
||
</ol>
|
||
</div>
|
||
<div class="wmw-card">
|
||
<h3 class="wmw-card__title">📝 Markdown-Konvertierung</h3>
|
||
<p style="font-size:13px">Folgende Elemente werden automatisch konvertiert:</p>
|
||
<ul style="margin:0;padding-left:18px;font-size:13px;line-height:1.8">
|
||
<li>Überschriften H1–H6</li>
|
||
<li>Fett, Kursiv, Durchgestrichen</li>
|
||
<li>Code-Blöcke (mit Syntax-Highlighting)</li>
|
||
<li>Tabellen</li>
|
||
<li>Links & Bilder</li>
|
||
<li>Blockquotes</li>
|
||
<li>Aufzählungslisten</li>
|
||
<li>Gitea-interne <code>[[Links]]</code></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.wmw-preview-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); gap:8px; }
|
||
.wmw-preview-item { display:flex; align-items:center; gap:8px; padding:8px 10px; background:var(--wmw-admin-bg); border-radius:6px; border:1px solid var(--wmw-admin-border); }
|
||
.wmw-preview-item__icon { font-size:16px; }
|
||
.wmw-preview-item__title { font-size:13px; font-weight:600; flex:1; }
|
||
.wmw-preview-item__date { font-size:11px; color:#888; }
|
||
.wmw-import-result { padding:20px 24px; border-radius:8px; margin-bottom:20px; }
|
||
.wmw-import-result--success { background:#e8f5e9; border:1px solid #a5d6a7; }
|
||
.wmw-import-result--warn { background:#fff8e1; border:1px solid #ffe082; }
|
||
.wmw-import-result h3 { margin:0 0 12px; }
|
||
.wmw-import-stats { display:flex; gap:16px; margin-bottom:12px; flex-wrap:wrap; }
|
||
.wmw-import-stat { text-align:center; background:#fff; padding:10px 20px; border-radius:6px; border:1px solid rgba(0,0,0,.08); }
|
||
.wmw-import-stat__num { display:block; font-size:24px; font-weight:700; color:#2e7d32; }
|
||
.wmw-import-errors { background:#fff3e0; border:1px solid #ffcc80; border-radius:6px; padding:10px 14px; margin-top:10px; }
|
||
.wmw-import-errors ul { margin:6px 0 0 18px; font-size:13px; }
|
||
</style>
|