438 lines
20 KiB
PHP
438 lines
20 KiB
PHP
<?php
|
|
/**
|
|
* Posts Management Tab
|
|
*
|
|
* @package Instagram_Gallery_Sync_Pro
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
$database = new IGSP_Database();
|
|
$image_handler = new IGSP_Image_Handler();
|
|
|
|
// Pagination
|
|
$per_page = 20;
|
|
$current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1;
|
|
$search = isset($_GET['s']) ? sanitize_text_field($_GET['s']) : '';
|
|
$offset = ($current_page - 1) * $per_page;
|
|
|
|
// Get posts
|
|
$total_posts = $database->count_posts_filtered(array(
|
|
'active' => null,
|
|
'search' => $search,
|
|
));
|
|
|
|
$posts = $database->get_posts(array(
|
|
'limit' => $per_page,
|
|
'offset' => $offset,
|
|
'order' => 'newest',
|
|
'active' => false, // Show all posts (active + inactive)
|
|
'search' => $search,
|
|
));
|
|
|
|
$total_pages = ceil($total_posts / $per_page);
|
|
?>
|
|
|
|
<!-- Manual Post Form -->
|
|
<div class="igsp-section">
|
|
<h2>
|
|
<?php esc_html_e('Post manuell hinzufügen', 'instagram-gallery-sync-pro'); ?>
|
|
</h2>
|
|
<p class="description">
|
|
<?php esc_html_e('Füge manuell ein Bild/Post hinzu, z.B. wenn Instagram ein Rate-Limit verhängt hat.', 'instagram-gallery-sync-pro'); ?>
|
|
</p>
|
|
|
|
<div class="igsp-manual-post-form" id="igsp-manual-post-form">
|
|
<div class="igsp-manual-post-fields">
|
|
<div class="igsp-manual-field igsp-manual-image-field">
|
|
<label>
|
|
<?php esc_html_e('Bild', 'instagram-gallery-sync-pro'); ?> <span class="required">*</span>
|
|
</label>
|
|
<div class="igsp-image-upload-area" id="igsp-image-upload-area">
|
|
<div class="igsp-image-preview" id="igsp-image-preview" style="display: none;">
|
|
<img src="" alt="" id="igsp-preview-img">
|
|
<button type="button" class="igsp-remove-image" id="igsp-remove-image"
|
|
title="<?php esc_attr_e('Bild entfernen', 'instagram-gallery-sync-pro'); ?>">
|
|
<span class="dashicons dashicons-no-alt"></span>
|
|
</button>
|
|
</div>
|
|
<div class="igsp-upload-placeholder" id="igsp-upload-placeholder">
|
|
<span class="dashicons dashicons-format-image"></span>
|
|
<span><?php esc_html_e('Klicke auf den Button unten', 'instagram-gallery-sync-pro'); ?></span>
|
|
</div>
|
|
<input type="hidden" id="igsp-attachment-id" value="">
|
|
</div>
|
|
<button type="button" class="button" id="igsp-select-image-btn">
|
|
<span class="dashicons dashicons-format-image"></span>
|
|
<?php esc_html_e('Bild auswählen', 'instagram-gallery-sync-pro'); ?>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="igsp-manual-field">
|
|
<label for="igsp-manual-url">
|
|
<?php esc_html_e('Instagram URL', 'instagram-gallery-sync-pro'); ?>
|
|
</label>
|
|
<input type="url" id="igsp-manual-url" placeholder="https://www.instagram.com/p/..."
|
|
class="regular-text">
|
|
<p class="description">
|
|
<?php esc_html_e('Link zum Instagram-Post (optional).', 'instagram-gallery-sync-pro'); ?>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="igsp-manual-field">
|
|
<label for="igsp-manual-caption">
|
|
<?php esc_html_e('Caption', 'instagram-gallery-sync-pro'); ?>
|
|
</label>
|
|
<textarea id="igsp-manual-caption" rows="3" class="large-text"
|
|
placeholder="<?php esc_attr_e('Beschreibung des Posts...', 'instagram-gallery-sync-pro'); ?>"></textarea>
|
|
</div>
|
|
|
|
<div class="igsp-manual-field">
|
|
<label for="igsp-manual-date">
|
|
<?php esc_html_e('Datum', 'instagram-gallery-sync-pro'); ?>
|
|
</label>
|
|
<input type="datetime-local" id="igsp-manual-date" class="regular-text">
|
|
<p class="description">
|
|
<?php esc_html_e('Veröffentlichungsdatum (optional, Standard: jetzt).', 'instagram-gallery-sync-pro'); ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="igsp-manual-post-actions">
|
|
<button type="button" id="igsp-add-manual-post" class="button button-primary">
|
|
<span class="dashicons dashicons-plus-alt2"></span>
|
|
<?php esc_html_e('Post hinzufügen', 'instagram-gallery-sync-pro'); ?>
|
|
</button>
|
|
<div id="igsp-manual-post-result" class="igsp-sync-result" style="display: none;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Posts Table -->
|
|
<div class="igsp-section">
|
|
<div class="igsp-posts-header">
|
|
<h2>
|
|
<?php esc_html_e('Alle Posts', 'instagram-gallery-sync-pro'); ?>
|
|
<span class="igsp-post-count">(
|
|
<?php echo esc_html($total_posts); ?>)
|
|
</span>
|
|
</h2>
|
|
|
|
<form method="get" class="igsp-search-form">
|
|
<input type="hidden" name="page" value="<?php echo esc_attr(IGSP_Admin::PAGE_SLUG); ?>">
|
|
<input type="hidden" name="tab" value="posts">
|
|
<div class="igsp-search-wrapper">
|
|
<input type="search" name="s" value="<?php echo esc_attr($search); ?>"
|
|
placeholder="<?php esc_attr_e('Posts durchsuchen...', 'instagram-gallery-sync-pro'); ?>"
|
|
class="igsp-search-input">
|
|
<button type="submit" class="button">
|
|
<span class="dashicons dashicons-search"></span>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<?php if (empty($posts)): ?>
|
|
<div class="igsp-no-posts">
|
|
<?php if (!empty($search)): ?>
|
|
<p>
|
|
<?php printf(esc_html__('Keine Posts gefunden für "%s".', 'instagram-gallery-sync-pro'), esc_html($search)); ?>
|
|
</p>
|
|
<?php else: ?>
|
|
<p>
|
|
<?php esc_html_e('Noch keine Posts vorhanden. Synchronisiere dein Instagram-Konto oder füge manuell Posts hinzu.', 'instagram-gallery-sync-pro'); ?>
|
|
</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="igsp-posts-table-wrapper">
|
|
<table class="igsp-posts-table widefat striped">
|
|
<thead>
|
|
<tr>
|
|
<th class="igsp-col-thumb">
|
|
<?php esc_html_e('Bild', 'instagram-gallery-sync-pro'); ?>
|
|
</th>
|
|
<th class="igsp-col-caption">
|
|
<?php esc_html_e('Caption', 'instagram-gallery-sync-pro'); ?>
|
|
</th>
|
|
<th class="igsp-col-link">
|
|
<?php esc_html_e('Link', 'instagram-gallery-sync-pro'); ?>
|
|
</th>
|
|
<th class="igsp-col-type">
|
|
<?php esc_html_e('Typ', 'instagram-gallery-sync-pro'); ?>
|
|
</th>
|
|
<th class="igsp-col-status">
|
|
<?php esc_html_e('Status', 'instagram-gallery-sync-pro'); ?>
|
|
</th>
|
|
<th class="igsp-col-date">
|
|
<?php esc_html_e('Datum', 'instagram-gallery-sync-pro'); ?>
|
|
</th>
|
|
<th class="igsp-col-actions">
|
|
<?php esc_html_e('Aktionen', 'instagram-gallery-sync-pro'); ?>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($posts as $post):
|
|
// Get image URL
|
|
$thumb_url = '';
|
|
if (!empty($post->image_thumbnail_path)) {
|
|
$thumb_url = $image_handler->get_image_url($post->image_thumbnail_path);
|
|
} elseif (!empty($post->image_local_path)) {
|
|
$thumb_url = $image_handler->get_image_url($post->image_local_path);
|
|
}
|
|
|
|
$is_manual = !empty($post->is_manual);
|
|
$is_active = !empty($post->is_active);
|
|
$caption_short = !empty($post->caption) ? wp_trim_words($post->caption, 12, '...') : '—';
|
|
$posted_date = !empty($post->posted_at) ? date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($post->posted_at)) : '—';
|
|
?>
|
|
<tr class="igsp-post-row <?php echo !$is_active ? 'igsp-post-inactive' : ''; ?>"
|
|
data-post-id="<?php echo esc_attr($post->id); ?>">
|
|
<td class="igsp-col-thumb">
|
|
<?php if ($thumb_url): ?>
|
|
<img src="<?php echo esc_url($thumb_url); ?>" alt="" class="igsp-post-thumb">
|
|
<?php else: ?>
|
|
<div class="igsp-post-thumb-placeholder">
|
|
<span class="dashicons dashicons-format-image"></span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="igsp-col-caption">
|
|
<span class="igsp-caption-text">
|
|
<?php echo esc_html($caption_short); ?>
|
|
</span>
|
|
</td>
|
|
<td class="igsp-col-link">
|
|
<?php if (!empty($post->post_url)): ?>
|
|
<a href="<?php echo esc_url($post->post_url); ?>" target="_blank" rel="noopener noreferrer"
|
|
class="igsp-post-link" title="<?php echo esc_attr($post->post_url); ?>">
|
|
<span class="dashicons dashicons-external"></span>
|
|
</a>
|
|
<?php else: ?>
|
|
<span class="igsp-no-link">—</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="igsp-col-type">
|
|
<?php if ($is_manual): ?>
|
|
<span class="igsp-type-badge igsp-type-manual">
|
|
<?php esc_html_e('Manual', 'instagram-gallery-sync-pro'); ?>
|
|
</span>
|
|
<?php else: ?>
|
|
<span class="igsp-type-badge igsp-type-synced">
|
|
<?php esc_html_e('Synced', 'instagram-gallery-sync-pro'); ?>
|
|
</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="igsp-col-status">
|
|
<span
|
|
class="igsp-status-badge <?php echo $is_active ? 'igsp-status-active' : 'igsp-status-inactive'; ?>">
|
|
<?php echo $is_active ? esc_html__('Aktiv', 'instagram-gallery-sync-pro') : esc_html__('Inaktiv', 'instagram-gallery-sync-pro'); ?>
|
|
</span>
|
|
</td>
|
|
<td class="igsp-col-date">
|
|
<span class="igsp-post-date">
|
|
<?php echo esc_html($posted_date); ?>
|
|
</span>
|
|
</td>
|
|
<td class="igsp-col-actions">
|
|
<div class="igsp-action-buttons">
|
|
<button type="button" class="button button-small igsp-toggle-post"
|
|
data-post-id="<?php echo esc_attr($post->id); ?>"
|
|
title="<?php echo $is_active ? esc_attr__('Deaktivieren', 'instagram-gallery-sync-pro') : esc_attr__('Aktivieren', 'instagram-gallery-sync-pro'); ?>">
|
|
<span
|
|
class="dashicons <?php echo $is_active ? 'dashicons-hidden' : 'dashicons-visibility'; ?>"></span>
|
|
</button>
|
|
<button type="button" class="button button-small igsp-delete-post"
|
|
data-post-id="<?php echo esc_attr($post->id); ?>"
|
|
title="<?php esc_attr_e('Löschen', 'instagram-gallery-sync-pro'); ?>">
|
|
<span class="dashicons dashicons-trash"></span>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<?php if ($total_pages > 1): ?>
|
|
<div class="igsp-pagination">
|
|
<?php
|
|
$base_url = admin_url('admin.php?page=' . IGSP_Admin::PAGE_SLUG . '&tab=posts');
|
|
if (!empty($search)) {
|
|
$base_url .= '&s=' . urlencode($search);
|
|
}
|
|
|
|
for ($i = 1; $i <= $total_pages; $i++):
|
|
$page_url = $base_url . '&paged=' . $i;
|
|
?>
|
|
<a href="<?php echo esc_url($page_url); ?>"
|
|
class="button <?php echo $current_page === $i ? 'button-primary' : ''; ?>">
|
|
<?php echo esc_html($i); ?>
|
|
</a>
|
|
<?php endfor; ?>
|
|
|
|
<span class="igsp-pagination-info">
|
|
<?php printf(
|
|
esc_html__('Seite %1$d von %2$d (%3$d Posts)', 'instagram-gallery-sync-pro'),
|
|
$current_page,
|
|
$total_pages,
|
|
$total_posts
|
|
); ?>
|
|
</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
jQuery(document).ready(function ($) {
|
|
// === Media Library Image Upload ===
|
|
var igspMediaFrame = null;
|
|
|
|
$('#igsp-select-image-btn').on('click', function (e) {
|
|
e.preventDefault();
|
|
|
|
if (typeof wp === 'undefined' || typeof wp.media !== 'function') {
|
|
alert('WordPress Media Library konnte nicht geladen werden. Bitte lade die Seite neu.');
|
|
return;
|
|
}
|
|
|
|
if (igspMediaFrame) {
|
|
igspMediaFrame.open();
|
|
return;
|
|
}
|
|
|
|
igspMediaFrame = wp.media({
|
|
title: '<?php echo esc_js(__('Bild auswählen', 'instagram-gallery-sync-pro')); ?>',
|
|
button: { text: '<?php echo esc_js(__('Bild verwenden', 'instagram-gallery-sync-pro')); ?>' },
|
|
multiple: false,
|
|
library: { type: 'image' }
|
|
});
|
|
|
|
igspMediaFrame.on('select', function () {
|
|
var attachment = igspMediaFrame.state().get('selection').first().toJSON();
|
|
$('#igsp-attachment-id').val(attachment.id);
|
|
var previewUrl = (attachment.sizes && attachment.sizes.medium) ? attachment.sizes.medium.url : attachment.url;
|
|
$('#igsp-preview-img').attr('src', previewUrl);
|
|
$('#igsp-image-preview').show();
|
|
$('#igsp-upload-placeholder').hide();
|
|
});
|
|
|
|
igspMediaFrame.open();
|
|
});
|
|
|
|
// Remove image
|
|
$('#igsp-remove-image').on('click', function (e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
$('#igsp-attachment-id').val('');
|
|
$('#igsp-preview-img').attr('src', '');
|
|
$('#igsp-image-preview').hide();
|
|
$('#igsp-upload-placeholder').show();
|
|
});
|
|
|
|
// === Submit Manual Post ===
|
|
$('#igsp-add-manual-post').on('click', function () {
|
|
var $btn = $(this);
|
|
var $result = $('#igsp-manual-post-result');
|
|
var attachmentId = $('#igsp-attachment-id').val();
|
|
|
|
if (!attachmentId) {
|
|
$result.removeClass('success').addClass('error').text('Bitte wähle ein Bild aus.').show();
|
|
return;
|
|
}
|
|
|
|
$btn.prop('disabled', true);
|
|
$result.hide();
|
|
|
|
var postedAt = $('#igsp-manual-date').val();
|
|
if (postedAt) {
|
|
postedAt = postedAt.replace('T', ' ') + ':00';
|
|
}
|
|
|
|
$.post(igspAdmin.ajaxUrl, {
|
|
action: 'igsp_add_manual_post',
|
|
nonce: igspAdmin.nonce,
|
|
attachment_id: attachmentId,
|
|
post_url: $('#igsp-manual-url').val(),
|
|
caption: $('#igsp-manual-caption').val(),
|
|
posted_at: postedAt
|
|
}, function (response) {
|
|
$result.removeClass('success error');
|
|
if (response.success) {
|
|
$result.addClass('success').text(response.data.message).show();
|
|
// Reset form
|
|
$('#igsp-attachment-id').val('');
|
|
$('#igsp-preview-img').attr('src', '');
|
|
$('#igsp-image-preview').hide();
|
|
$('#igsp-upload-placeholder').show();
|
|
$('#igsp-manual-url').val('');
|
|
$('#igsp-manual-caption').val('');
|
|
$('#igsp-manual-date').val('');
|
|
setTimeout(function () { location.reload(); }, 1500);
|
|
} else {
|
|
$result.addClass('error').text(response.data.message).show();
|
|
}
|
|
$btn.prop('disabled', false);
|
|
}).fail(function () {
|
|
$result.addClass('error').text('Ein Fehler ist aufgetreten.').show();
|
|
$btn.prop('disabled', false);
|
|
});
|
|
});
|
|
|
|
// === Toggle Post Status ===
|
|
$(document).on('click', '.igsp-toggle-post', function () {
|
|
var $btn = $(this);
|
|
var postId = $btn.data('post-id');
|
|
var $row = $btn.closest('.igsp-post-row');
|
|
$btn.prop('disabled', true);
|
|
|
|
$.post(igspAdmin.ajaxUrl, {
|
|
action: 'igsp_toggle_post',
|
|
nonce: igspAdmin.nonce,
|
|
post_id: postId
|
|
}, function (response) {
|
|
if (response.success) {
|
|
var $icon = $btn.find('.dashicons');
|
|
var $badge = $row.find('.igsp-status-badge');
|
|
if (response.data.is_active) {
|
|
$row.removeClass('igsp-post-inactive');
|
|
$icon.removeClass('dashicons-visibility').addClass('dashicons-hidden');
|
|
$badge.removeClass('igsp-status-inactive').addClass('igsp-status-active').text('Aktiv');
|
|
} else {
|
|
$row.addClass('igsp-post-inactive');
|
|
$icon.removeClass('dashicons-hidden').addClass('dashicons-visibility');
|
|
$badge.removeClass('igsp-status-active').addClass('igsp-status-inactive').text('Inaktiv');
|
|
}
|
|
}
|
|
$btn.prop('disabled', false);
|
|
}).fail(function () { $btn.prop('disabled', false); });
|
|
});
|
|
|
|
// === Delete Post ===
|
|
$(document).on('click', '.igsp-delete-post', function () {
|
|
if (!confirm('Diesen Post wirklich löschen?')) return;
|
|
var $btn = $(this);
|
|
var postId = $btn.data('post-id');
|
|
var $row = $btn.closest('.igsp-post-row');
|
|
$btn.prop('disabled', true);
|
|
|
|
$.post(igspAdmin.ajaxUrl, {
|
|
action: 'igsp_delete_post',
|
|
nonce: igspAdmin.nonce,
|
|
post_id: postId
|
|
}, function (response) {
|
|
if (response.success) {
|
|
$row.fadeOut(300, function () { $(this).remove(); });
|
|
} else {
|
|
$btn.prop('disabled', false);
|
|
}
|
|
}).fail(function () { $btn.prop('disabled', false); });
|
|
});
|
|
});
|
|
</script>
|