Files
adocWP/kb-markdown-importer/includes/Admin/ProductsPage.php
2026-05-27 14:17:22 +02:00

172 lines
9.6 KiB
PHP

<?php
declare(strict_types=1);
namespace KbMarkdownImporter\Admin;
use KbMarkdownImporter\Repository\ProductRepository;
final class ProductsPage
{
public static function render(): void
{
if (! current_user_can('manage_kb_docs')) {
wp_die(esc_html__('You do not have permission to manage documentation products.', 'kb-markdown-importer'));
}
$repository = new ProductRepository();
self::handleActions($repository);
$products = $repository->allWithStats();
?>
<div class="wrap">
<h1><?php esc_html_e('Documentation Products', 'kb-markdown-importer'); ?></h1>
<p><?php esc_html_e('Manage imported products, group them into frontend products, and assign categories.', 'kb-markdown-importer'); ?></p>
<?php settings_errors('kb_markdown_products'); ?>
<form method="post" action="">
<?php wp_nonce_field('kb_markdown_save_all_products'); ?>
<table class="widefat striped">
<thead>
<tr>
<th><?php esc_html_e('Imported product', 'kb-markdown-importer'); ?></th>
<th><?php esc_html_e('Frontend product', 'kb-markdown-importer'); ?></th>
<th><?php esc_html_e('Documentation part', 'kb-markdown-importer'); ?></th>
<th><?php esc_html_e('Category', 'kb-markdown-importer'); ?></th>
<th><?php esc_html_e('Versions', 'kb-markdown-importer'); ?></th>
<th><?php esc_html_e('Pages', 'kb-markdown-importer'); ?></th>
<th><?php esc_html_e('Delete', 'kb-markdown-importer'); ?></th>
</tr>
</thead>
<tbody>
<?php if (! $products) : ?>
<tr><td colspan="7"><?php esc_html_e('No products have been imported yet.', 'kb-markdown-importer'); ?></td></tr>
<?php endif; ?>
<?php foreach ($products as $item) : ?>
<?php
$term = $item['term'];
$meta = (array) $item['meta'];
$versions = array_map(static fn (\WP_Term $version): string => $version->name, (array) $item['versions']);
?>
<tr>
<td>
<input type="hidden" name="products[<?php echo esc_attr((string) $term->term_id); ?>][term_id]" value="<?php echo esc_attr((string) $term->term_id); ?>">
<strong><?php echo esc_html($term->name); ?></strong>
<br>
<code><?php echo esc_html($term->slug); ?></code>
<input type="hidden" name="products[<?php echo esc_attr((string) $term->term_id); ?>][product_name]" value="<?php echo esc_attr($term->name); ?>">
<input type="hidden" name="products[<?php echo esc_attr((string) $term->term_id); ?>][product_slug]" value="<?php echo esc_attr($term->slug); ?>">
</td>
<td>
<label class="screen-reader-text" for="group_name_<?php echo esc_attr((string) $term->term_id); ?>"><?php esc_html_e('Frontend product name', 'kb-markdown-importer'); ?></label>
<input id="group_name_<?php echo esc_attr((string) $term->term_id); ?>" class="regular-text" type="text" name="products[<?php echo esc_attr((string) $term->term_id); ?>][group_name]" value="<?php echo esc_attr((string) $meta['group_name']); ?>" placeholder="<?php echo esc_attr($term->name); ?>">
<br>
<label class="screen-reader-text" for="group_slug_<?php echo esc_attr((string) $term->term_id); ?>"><?php esc_html_e('Frontend product slug', 'kb-markdown-importer'); ?></label>
<input id="group_slug_<?php echo esc_attr((string) $term->term_id); ?>" class="regular-text" type="text" name="products[<?php echo esc_attr((string) $term->term_id); ?>][group_slug]" value="<?php echo esc_attr((string) $meta['group_slug']); ?>" placeholder="<?php echo esc_attr($term->slug); ?>">
</td>
<td>
<input class="regular-text" type="text" name="products[<?php echo esc_attr((string) $term->term_id); ?>][part_label]" value="<?php echo esc_attr((string) $meta['part_label']); ?>" placeholder="<?php esc_attr_e('App, Modul, Exporter', 'kb-markdown-importer'); ?>">
</td>
<td>
<input class="regular-text" type="text" name="products[<?php echo esc_attr((string) $term->term_id); ?>][category]" value="<?php echo esc_attr((string) $meta['category']); ?>" placeholder="<?php esc_attr_e('CRM, Telefonie, Integration', 'kb-markdown-importer'); ?>">
</td>
<td><?php echo esc_html($versions ? implode(', ', $versions) : __('No versions', 'kb-markdown-importer')); ?></td>
<td><?php echo esc_html((string) $item['page_count']); ?></td>
<td>
<label>
<input type="checkbox" name="delete_terms[]" value="<?php echo esc_attr((string) $term->term_id); ?>">
<?php esc_html_e('Trash pages and remove product', 'kb-markdown-importer'); ?>
</label>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php submit_button(__('Save all products', 'kb-markdown-importer'), 'primary', 'kb_markdown_save_all_products', false); ?>
<?php submit_button(__('Delete selected', 'kb-markdown-importer'), 'delete', 'kb_markdown_delete_selected_products', false, [
'onclick' => "return window.confirm('" . esc_js(__('Move selected products and their imported pages to the trash?', 'kb-markdown-importer')) . "');",
]); ?>
</form>
</div>
<?php
}
private static function handleActions(ProductRepository $repository): void
{
$action = '';
if (isset($_POST['kb_markdown_save_all_products'])) {
$action = 'save_all';
} elseif (isset($_POST['kb_markdown_delete_selected_products'])) {
$action = 'delete_selected';
} else {
$action = sanitize_key(wp_unslash((string) ($_POST['kb_markdown_product_action'] ?? '')));
}
if (! $action) {
return;
}
if ('save_all' === $action) {
check_admin_referer('kb_markdown_save_all_products');
$products = (array) ($_POST['products'] ?? []);
$saved = 0;
foreach ($products as $rawTermId => $rawProduct) {
$termId = absint($rawTermId);
$rawProduct = (array) $rawProduct;
if (! $termId) {
continue;
}
$result = $repository->update(
$termId,
sanitize_text_field(wp_unslash((string) ($rawProduct['product_name'] ?? ''))),
sanitize_title(wp_unslash((string) ($rawProduct['product_slug'] ?? ''))),
[
'group_name' => sanitize_text_field(wp_unslash((string) ($rawProduct['group_name'] ?? ''))),
'group_slug' => sanitize_title(wp_unslash((string) ($rawProduct['group_slug'] ?? ''))),
'part_label' => sanitize_text_field(wp_unslash((string) ($rawProduct['part_label'] ?? ''))),
'category' => sanitize_text_field(wp_unslash((string) ($rawProduct['category'] ?? ''))),
]
);
if (is_wp_error($result)) {
add_settings_error('kb_markdown_products', 'update_failed_' . $termId, $result->get_error_message(), 'error');
continue;
}
$saved++;
}
add_settings_error('kb_markdown_products', 'updated', sprintf(
/* translators: %d: number of saved products. */
__('Saved %d products.', 'kb-markdown-importer'),
$saved
), 'success');
return;
}
if ('delete_selected' === $action) {
check_admin_referer('kb_markdown_save_all_products');
$termIds = array_map('absint', (array) ($_POST['delete_terms'] ?? []));
$deleted = 0;
foreach (array_filter($termIds) as $termId) {
$result = $repository->deleteProduct($termId, true);
if (is_wp_error($result)) {
add_settings_error('kb_markdown_products', 'delete_failed_' . $termId, $result->get_error_message(), 'error');
continue;
}
$deleted++;
}
add_settings_error('kb_markdown_products', 'deleted', sprintf(
/* translators: %d: number of deleted products. */
__('Deleted %d products.', 'kb-markdown-importer'),
$deleted
), 'success');
}
}
}