removed old file

This commit is contained in:
2025-02-08 01:00:58 +01:00
parent 0b21ff0089
commit 31249dc43e

View File

@@ -1,408 +0,0 @@
<?php
ob_start(); // Sofortiges Output Buffering
/**
* Plugin Name: AI Translate
* Description: Plugin zum Verwalten und Übersetzen von Beiträgen, Seiten und Custom Post Types (ohne AJAX, erweiterte Funktionen).
* Version: 1.22
* Author: Dein Name
* License: GPL2
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Verarbeitet Formular- und URL-Anfragen:
* - Werden per POST ausgewählte Beiträge übermittelt, so werden diese (ohne Duplikate) zur bestehenden Auswahl hinzugefügt.
* - Wird per GET der Parameter "remove" übergeben, so wird der entsprechende Eintrag entfernt.
*
* Alle relevanten GET‑Parameter (tab, paged, orderby, order, category) werden übernommen, sodass der Redirect
* den aktuellen Zustand beibehält.
* Falls bereits Output gesendet wurde, erfolgt der Redirect mittels JavaScript und Meta‑Refresh.
*/
function ait_handle_form_submissions() {
$action_taken = false;
$current_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'post';
// Alle relevanten Parameter übernehmen:
$params = array(
'tab' => $current_tab,
'paged' => isset($_GET['paged']) ? intval($_GET['paged']) : 1,
'orderby' => isset($_GET['orderby']) ? sanitize_text_field($_GET['orderby']) : 'modified',
'order' => isset($_GET['order']) ? sanitize_text_field($_GET['order']) : 'desc',
'category'=> isset($_REQUEST['category']) ? intval($_REQUEST['category']) : 0,
);
$redirect_url = add_query_arg( $params, admin_url('admin.php?page=ai-translate') );
// Beiträge hinzufügen (POST)
if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['selected_posts']) && is_array($_POST['selected_posts']) ) {
$new_posts = array_map( 'intval', $_POST['selected_posts'] );
$current = get_option( 'ait_selected_posts', [] );
$merged = array_unique( array_merge( $current, $new_posts ) );
update_option( 'ait_selected_posts', $merged );
$action_taken = true;
}
// Einzelnen Eintrag entfernen (GET)
if ( isset($_GET['remove']) ) {
$remove_id = intval($_GET['remove']);
$current = get_option( 'ait_selected_posts', [] );
if ( ($key = array_search($remove_id, $current)) !== false ) {
unset($current[$key]);
update_option( 'ait_selected_posts', $current );
$action_taken = true;
}
}
if ( $action_taken ) {
if ( headers_sent() ) {
echo '<meta http-equiv="refresh" content="0; url=' . esc_url( $redirect_url ) . '">';
echo '<script type="text/javascript">window.location.href="' . esc_js( $redirect_url ) . '";</script>';
exit;
} else {
if ( ob_get_length() ) {
ob_end_clean();
}
wp_redirect( $redirect_url );
exit;
}
}
}
/**
* Fügt das Admin-Menü hinzu.
*/
function ait_add_admin_menu() {
add_menu_page( 'AI Translate', 'AI Translate', 'manage_options', 'ai-translate', 'ait_admin_page', 'dashicons-translation', 25 );
}
add_action( 'admin_menu', 'ait_add_admin_menu' );
/**
* Zeigt die Admin-Seite an.
* Die Reihenfolge: Zuerst der Titel, dann die "Gespeicherte Auswahl" (direkt darunter), anschließend die Reiter, danach der Rest.
*/
function ait_admin_page() {
ait_handle_form_submissions();
$current_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'post';
?>
<div class="wrap">
<h1>AI Translate</h1>
<style>
.wp-list-table .checkbox-column { width: 40px; }
.selected-posts-box { margin-bottom: 20px; }
.actions { margin-bottom: 20px; }
.sortable a { text-decoration: none; }
.sortable a.sorted-asc::after { content: " ▲"; }
.sortable a.sorted-desc::after { content: " ▼"; }
</style>
<!-- Gespeicherte Auswahl direkt unter dem Titel -->
<div class="selected-posts-box">
<?php echo ait_get_selected_list_html( $current_tab ); ?>
</div>
<!-- Übersetzen-Button nur anzeigen, wenn Auswahl nicht leer ist -->
<?php
$saved = get_option( 'ait_selected_posts', [] );
if ( ! empty( $saved ) ) : ?>
<div class="actions">
<button id="translate-button" class="button button-primary">Übersetzen</button>
</div>
<?php endif; ?>
<!-- Reiter -->
<h2 class="nav-tab-wrapper">
<a href="?page=ai-translate&tab=post" class="nav-tab <?php echo ($current_tab == 'post') ? 'nav-tab-active' : ''; ?>">Beiträge</a>
<a href="?page=ai-translate&tab=page" class="nav-tab <?php echo ($current_tab == 'page') ? 'nav-tab-active' : ''; ?>">Seiten</a>
<?php
$custom_post_types = get_post_types( ['_builtin' => false], 'objects' );
foreach ( $custom_post_types as $cpt ) {
echo '<a href="?page=ai-translate&tab=' . esc_attr( $cpt->name ) . '" class="nav-tab ' . (($current_tab == $cpt->name) ? 'nav-tab-active' : '') . '">' . esc_html( $cpt->label ) . '</a>';
}
?>
</h2>
<?php ait_display_table( $current_tab ); ?>
</div>
<?php
ob_end_flush();
}
/**
* Erzeugt den HTML-Code für die "Gespeicherte Auswahl".
* Die Titel werden fett (ohne Link) ausgegeben; es erscheint kein "Bearbeiten"-Link.
*/
function ait_get_selected_list_html( $current_tab ) {
ob_start();
$selected_posts = get_option( 'ait_selected_posts', [] );
echo '<div>';
echo '<h3>Gespeicherte Auswahl</h3>';
if ( ! empty( $selected_posts ) ) {
echo '<div id="selected-posts-list">';
$titles = [];
// Alle relevanten Parameter übernehmen, um den Zustand beizubehalten.
$params = array(
'tab' => $current_tab,
'paged' => isset($_GET['paged']) ? intval($_GET['paged']) : 1,
'orderby' => isset($_GET['orderby']) ? sanitize_text_field($_GET['orderby']) : 'modified',
'order' => isset($_GET['order']) ? sanitize_text_field($_GET['order']) : 'desc',
'category'=> isset($_GET['category']) ? intval($_GET['category']) : 0,
);
foreach ( $selected_posts as $post_id ) {
$post = get_post( $post_id );
if ( $post && ! empty( $post->post_title ) ) {
$remove_params = $params;
$remove_params['remove'] = $post_id;
$remove_url = add_query_arg( $remove_params, admin_url( 'admin.php?page=ai-translate' ) );
$titles[] = '<span class="selected-item" data-id="' . esc_attr( $post_id ) . '">'
. '<strong>' . esc_html( $post->post_title ) . '</strong>'
. ' <a class="remove-item" href="' . esc_url( $remove_url ) . '">[x]</a>'
. '</span>';
}
}
echo implode( '<br>', $titles );
echo '</div>';
} else {
echo '<p>Keine Einträge ausgewählt.</p>';
}
echo '</div>';
return ob_get_clean();
}
/**
* Gibt für einen Beitrag alle Begriffe aus den hierarchischen Taxonomien zurück.
*/
function ait_get_post_categories( $post_id, $post_type ) {
$taxonomies = get_object_taxonomies( $post_type, 'objects' );
$category_names = [];
foreach ( $taxonomies as $taxonomy ) {
if ( $taxonomy->hierarchical ) {
$terms = get_the_terms( $post_id, $taxonomy->name );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
foreach ( $terms as $term ) {
$category_names[] = $term->name;
}
}
}
}
return $category_names;
}
/**
* Ermittelt die erste hierarchische Taxonomie für den Post Type.
*/
function ait_get_category_taxonomy( $post_type ) {
$taxonomies = get_object_taxonomies( $post_type, 'objects' );
foreach ( $taxonomies as $taxonomy ) {
if ( $taxonomy->hierarchical ) {
return $taxonomy->name;
}
}
return '';
}
/**
* Erzeugt einen sortierbaren Link.
* Spalten, die sortierbar sein sollen, sind "Titel" und "Last Modified".
* Jetzt wird auch der aktuelle Kategorienfilter übernommen, sodass sich der Filter nicht zurücksetzt.
*/
function ait_sort_link( $column_label, $column_key, $current_tab ) {
$current_orderby = $_GET['orderby'] ?? 'modified';
$current_order = $_GET['order'] ?? 'desc';
$next_order = 'asc';
$class = 'sortable';
if ( $current_orderby === $column_key ) {
if ( $current_order === 'asc' ) {
$next_order = 'desc';
$class .= ' sorted-asc';
} else {
$next_order = 'asc';
$class .= ' sorted-desc';
}
}
$category = isset($_REQUEST['category']) ? intval($_REQUEST['category']) : 0;
$url = add_query_arg( [
'orderby' => $column_key,
'order' => $next_order,
'tab' => $current_tab,
'category' => $category,
], admin_url( 'admin.php?page=ai-translate' ) );
return '<a href="' . esc_url( $url ) . '" class="' . esc_attr( $class ) . '">' . esc_html( $column_label ) . '</a>';
}
/**
* Zeigt eine Tabelle mit Beiträgen, Seiten oder Custom Post Types an.
* Die Tabelle enthält:
* - Eine Checkbox-Spalte
* - Spalte "Titel": Fett dargestellter Link zum Beitrag (öffnet in neuem Tab) plus Statusanzeige (Privat/Entwurf) und einen "Bearbeiten"-Link.
* - Spalte "Kategorie"
* - Spalte "Last Modified": basierend auf dem Datum der letzten Änderung (Format: "YYYY/MM/DD at g:i a").
* Die Tabelle ist sortierbar nach "Titel" und "Last Modified".
* Die Pagination wird oben und unten angezeigt, jeweils rechtsbündig.
*
* Wichtig: Der Kategorien-Filter wird über ein separates GET-Formular geregelt – der Parameter "category" wird über $_REQUEST ausgelesen.
*/
function ait_display_table( $post_type ) {
$selected_category = intval( $_REQUEST['category'] ?? 0 );
$paged = max( 1, intval( $_GET['paged'] ?? 1 ) );
$posts_per_page = 10;
$orderby = $_GET['orderby'] ?? 'modified';
$order = $_GET['order'] ?? 'desc';
$args = [
'post_type' => $post_type,
'posts_per_page' => $posts_per_page,
'paged' => $paged,
'post_status' => [ 'publish', 'private', 'draft' ],
'orderby' => $orderby,
'order' => strtoupper( $order ),
];
$category_tax = ait_get_category_taxonomy( $post_type );
if ( $selected_category && $category_tax ) {
$args['tax_query'] = [[
'taxonomy' => $category_tax,
'field' => 'term_id',
'terms' => $selected_category,
]];
}
$query = new WP_Query( $args );
// Kategorie-Filter-Formular und Pagination oben in einem flexiblen Container
$category_filter_html = '';
if ( $category_tax ) {
ob_start();
echo '<form method="get" action="" class="category-filter">';
echo '<input type="hidden" name="page" value="ai-translate">';
echo '<input type="hidden" name="tab" value="' . esc_attr( $post_type ) . '">';
echo '<select name="category" onchange="this.form.submit();">';
echo '<option value="0">Alle Kategorien</option>';
$terms = get_terms( [ 'taxonomy' => $category_tax, 'hide_empty' => false ] );
if ( ! is_wp_error( $terms ) ) {
foreach ( $terms as $term ) {
echo '<option value="' . esc_attr( $term->term_id ) . '" ' . selected( $selected_category, $term->term_id, false ) . '>' . esc_html( $term->name ) . '</option>';
}
}
echo '</select>';
echo '</form>';
$category_filter_html = ob_get_clean();
}
$pagination_html = '';
if ( $query->max_num_pages > 1 ) {
ob_start();
echo '<div class="pagination" style="text-align: right;">';
for ( $i = 1; $i <= $query->max_num_pages; $i++ ) {
$page_url = add_query_arg( [
'paged' => $i,
'tab' => $post_type,
'orderby' => $orderby,
'order' => $order,
'category'=> $selected_category,
], admin_url( 'admin.php?page=ai-translate' ) );
$class = ( $paged == $i ) ? 'button button-primary' : 'button';
echo '<a href="' . esc_url( $page_url ) . '" class="' . esc_attr( $class ) . '">' . $i . '</a> ';
}
echo '</div>';
$pagination_html = ob_get_clean();
}
// Ausgabe des kombinierten Bereichs (Filter und obere Pagination)
if ( ! empty( $category_filter_html ) || ! empty( $pagination_html ) ) {
echo '<div class="filter-pagination" style="display: flex; justify-content: space-between; align-items: center; margin: 10px;">';
echo '<div class="filter-left">' . $category_filter_html . '</div>';
echo '<div class="pagination-right">' . $pagination_html . '</div>';
echo '</div>';
}
// Formular mit Tabelle
?>
<form id="ai-translate-form" method="post" action="">
<!-- Versteckte Felder, um GET-Parameter beizubehalten -->
<input type="hidden" name="page" value="ai-translate">
<input type="hidden" name="tab" value="<?php echo esc_attr( $post_type ); ?>">
<input type="hidden" name="category" value="<?php echo esc_attr( $selected_category ); ?>">
<input type="hidden" name="paged" value="<?php echo esc_attr( $_GET['paged'] ?? 1 ); ?>">
<input type="hidden" name="orderby" value="<?php echo esc_attr( $_GET['orderby'] ?? 'modified' ); ?>">
<input type="hidden" name="order" value="<?php echo esc_attr( $_GET['order'] ?? 'desc' ); ?>">
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th class="checkbox-column"><input type="checkbox" id="select-all"></th>
<th><?php echo ait_sort_link( 'Titel', 'title', $post_type ); ?></th>
<th>Kategorie</th>
<th><?php echo ait_sort_link( 'Last Modified', 'modified', $post_type ); ?></th>
</tr>
</thead>
<tbody>
<?php
if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
$post_id = get_the_ID();
$status = get_post_status( $post_id );
$status_text = '';
if ( $status === 'private' ) {
$status_text = ' <span style="color:#a00;">(Privat)</span>';
} elseif ( $status === 'draft' ) {
$status_text = ' <span style="color:#a00;">(Entwurf)</span>';
}
?>
<tr>
<td class="checkbox-column">
<input type="checkbox" name="selected_posts[]" value="<?php echo $post_id; ?>">
</td>
<td>
<a href="<?php echo esc_url( get_permalink( $post_id ) ); ?>" target="_blank">
<strong><?php echo esc_html( get_the_title() ); ?></strong>
</a>
<?php echo $status_text; ?>
<br>
<small>
<a href="<?php echo esc_url( admin_url( 'post.php?post=' . $post_id . '&action=edit' ) ); ?>" target="_blank">
Bearbeiten
</a>
</small>
</td>
<td><?php echo esc_html( implode( ', ', ait_get_post_categories( $post_id, $post_type ) ) ); ?></td>
<td>
<strong>Last Modified</strong><br>
<?php echo esc_html( get_the_modified_date( 'Y/m/d \a\t g:i a' ) ); ?>
</td>
</tr>
<?php
endwhile;
else :
?>
<tr>
<td colspan="4">Keine Beiträge gefunden.</td>
</tr>
<?php
endif;
wp_reset_postdata();
?>
</tbody>
</table>
<p>
<input type="submit" name="save_selection" class="button button-primary" value="Zur Auswahl hinzufügen">
</p>
</form>
<script>
// Select-All Funktionalität
document.addEventListener('DOMContentLoaded', function() {
var selectAllCheckbox = document.getElementById('select-all');
if ( selectAllCheckbox ) {
selectAllCheckbox.addEventListener('change', function() {
var checkboxes = document.querySelectorAll('tbody input[type="checkbox"]');
checkboxes.forEach(function(cb) {
cb.checked = selectAllCheckbox.checked;
});
});
}
});
</script>
<?php
}
?>