664 lines
38 KiB
PHP
664 lines
38 KiB
PHP
<?php
|
||
/**
|
||
* Plugin Name: DummyLab – Dummy Post & Content Generator
|
||
* Plugin URI: https://apps.masbudikusuma.my.id/dummylab-wp
|
||
* Description: Advanced dummy content generator for WordPress development with safety controls and bulk purge features.
|
||
* Version: 1.2.0
|
||
* Author: masbudikusuma
|
||
* Author URI: https://masbudi.my.id
|
||
* Text Domain: dummylab
|
||
* License: GPL-2.0+
|
||
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
||
*/
|
||
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
class DummyLab {
|
||
private static $instance = null;
|
||
private $meta_key = '_is_dummylab_post';
|
||
|
||
public static function get_instance() {
|
||
if (null === self::$instance) {
|
||
self::$instance = new self();
|
||
}
|
||
return self::$instance;
|
||
}
|
||
|
||
private function __construct() {
|
||
add_action('admin_menu', [$this, 'add_admin_menu']);
|
||
add_action('admin_init', [$this, 'handle_activation_redirect']);
|
||
add_action('admin_post_dummylab_generate', [$this, 'handle_generate']);
|
||
add_action('admin_post_dummylab_purge', [$this, 'handle_purge']);
|
||
}
|
||
|
||
public static function activate_plugin() {
|
||
add_option('dummylab_do_activation_redirect', true);
|
||
}
|
||
|
||
public function handle_activation_redirect() {
|
||
if (get_option('dummylab_do_activation_redirect', false)) {
|
||
delete_option('dummylab_do_activation_redirect');
|
||
if (!isset($_GET['activate-multi'])) {
|
||
wp_safe_redirect(admin_url('tools.php?page=dummylab'));
|
||
exit;
|
||
}
|
||
}
|
||
}
|
||
|
||
public function add_admin_menu() {
|
||
add_management_page(
|
||
'DummyLab Generator',
|
||
'DummyLab',
|
||
'manage_options',
|
||
'dummylab',
|
||
[$this, 'render_admin_page']
|
||
);
|
||
}
|
||
|
||
public function render_admin_page() {
|
||
if (!current_user_can('manage_options')) {
|
||
return;
|
||
}
|
||
|
||
$ui_lang = isset($_GET['ui_lang']) && $_GET['ui_lang'] === 'en' ? 'en' : 'id';
|
||
$users = get_users(['fields' => ['ID', 'display_name']]);
|
||
|
||
$query = new WP_Query([
|
||
'post_type' => ['post', 'page', 'attachment'],
|
||
'posts_per_page' => -1,
|
||
'meta_key' => $this->meta_key,
|
||
'meta_value' => '1',
|
||
'fields' => 'ids',
|
||
'post_status' => 'any',
|
||
]);
|
||
$dummy_count = $query->found_posts;
|
||
|
||
$t = $this->get_translations($ui_lang);
|
||
?>
|
||
<style>
|
||
.dummylab-wrap { max-width: 1200px; margin: 20px 20px 0 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; }
|
||
.dummylab-header { background: #fff; border: 1px solid #c3c4c7; border-radius: 8px; padding: 20px 24px; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 1px 3px rgba(0,0,0,0.04); margin-bottom: 24px; }
|
||
.dummylab-header h1 { margin: 0 0 6px 0; font-size: 22px; font-weight: 600; color: #1d2327; display: flex; align-items: center; gap: 8px; }
|
||
.dummylab-header p { margin: 0; color: #646970; font-size: 13px; }
|
||
|
||
.dummylab-lang-switch { background: #f0f0f1; padding: 4px; border-radius: 20px; display: flex; gap: 4px; border: 1px solid #dcdcde; }
|
||
.dummylab-lang-btn { text-decoration: none; padding: 5px 14px; border-radius: 16px; font-size: 12px; font-weight: 600; color: #50575e; transition: all 0.2s ease; }
|
||
.dummylab-lang-btn.active { background: #2271b1; color: #fff; box-shadow: 0 1px 2px rgba(0,0,0,0.1); }
|
||
|
||
.dummylab-container { display: flex; gap: 24px; align-items: flex-start; }
|
||
.dummylab-main-card { flex: 2; background: #fff; border: 1px solid #c3c4c7; border-radius: 8px; padding: 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.04); min-width: 550px; }
|
||
.dummylab-sidebar { flex: 1; display: flex; flex-direction: column; gap: 20px; min-width: 320px; }
|
||
|
||
.dummylab-section-title { font-size: 15px; font-weight: 600; color: #1d2327; margin: 20px 0 14px 0; padding-bottom: 8px; border-bottom: 1px solid #f0f0f1; display: flex; align-items: center; gap: 8px; }
|
||
.dummylab-section-title:first-of-type { margin-top: 0; }
|
||
|
||
.dummylab-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
|
||
.dummylab-field { display: flex; flex-direction: column; gap: 6px; }
|
||
.dummylab-field.full-width { grid-column: span 2; }
|
||
.dummylab-field label { font-size: 13px; font-weight: 600; color: #2c3338; }
|
||
.dummylab-field input[type="text"],
|
||
.dummylab-field input[type="number"],
|
||
.dummylab-field select { width: 100%; border: 1px solid #8c8f94; border-radius: 6px; padding: 7px 10px; font-size: 13px; background-color: #fff; box-shadow: 0 0 0 transparent; transition: border-color 0.15s ease-in-out; }
|
||
.dummylab-field input:focus, .dummylab-field select:focus { border-color: #2271b1; box-shadow: 0 0 0 1px #2271b1; outline: none; }
|
||
.dummylab-field .description { margin: 2px 0 0 0; font-size: 12px; color: #646970; line-height: 1.4; }
|
||
|
||
.dummylab-checkbox-group { display: flex; flex-direction: column; gap: 10px; padding: 12px; background: #f6f7f7; border-radius: 6px; border: 1px solid #dcdcde; }
|
||
.dummylab-checkbox-group label { font-weight: 500; font-size: 13px; color: #1d2327; display: flex; align-items: center; gap: 8px; cursor: pointer; }
|
||
|
||
.dummylab-side-card { background: #fff; border: 1px solid #c3c4c7; border-radius: 8px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.04); }
|
||
.dummylab-side-card.purge-card { border-top: 4px solid #d63638; }
|
||
.dummylab-side-card h3 { margin: 0 0 12px 0; font-size: 15px; font-weight: 600; color: #1d2327; display: flex; align-items: center; gap: 8px; }
|
||
|
||
.dummylab-badge-count { display: inline-block; background: #fcf0f0; color: #d63638; font-weight: 700; font-size: 16px; padding: 4px 12px; border-radius: 20px; border: 1px solid #f5c6cb; margin-left: 6px; }
|
||
.dummylab-guide-list { margin: 0; padding-left: 20px; color: #3c434a; font-size: 13px; line-height: 1.6; }
|
||
.dummylab-guide-list li { margin-bottom: 8px; }
|
||
.dummylab-safety-list { margin: 0; padding-left: 18px; color: #3c434a; font-size: 13px; line-height: 1.6; list-style-type: square; }
|
||
.dummylab-safety-list li { margin-bottom: 6px; }
|
||
|
||
.dummylab-btn-primary { background: #2271b1 !important; border-color: #2271b1 !important; border-radius: 6px !important; padding: 8px 20px !important; font-size: 14px !important; height: auto !important; cursor: pointer; }
|
||
.dummylab-btn-danger { background: #d63638 !important; border-color: #d63638 !important; color: #fff !important; border-radius: 6px !important; padding: 6px 18px !important; font-size: 13px !important; height: auto !important; width: 100%; text-align: center; }
|
||
.dummylab-btn-danger:disabled { background: #f6f7f7 !important; border-color: #dcdcde !important; color: #a7aaad !important; cursor: not-allowed; }
|
||
|
||
/* Loading Overlay Styles */
|
||
.dummylab-loading-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(15, 23, 42, 0.6); backdrop-filter: blur(4px); z-index: 999999; align-items: center; justify-content: center; flex-direction: column; color: #fff; }
|
||
.dummylab-spinner { width: 50px; height: 50px; border: 5px solid rgba(255, 255, 255, 0.3); border-radius: 50%; border-top-color: #38bdf8; animation: dummylab-spin 1s ease-in-out infinite; margin-bottom: 16px; }
|
||
@keyframes dummylab-spin { to { transform: rotate(360deg); } }
|
||
.dummylab-loading-text { font-size: 18px; font-weight: 600; text-align: center; }
|
||
.dummylab-loading-subtext { font-size: 13px; color: #cbd5e1; margin-top: 6px; text-align: center; }
|
||
</style>
|
||
|
||
<!-- Loading Overlay Element -->
|
||
<div id="dummylab-loading-overlay" class="dummylab-loading-overlay">
|
||
<div class="dummylab-spinner"></div>
|
||
<div class="dummylab-loading-text"><?php echo $t['loading_title']; ?></div>
|
||
<div class="dummylab-loading-subtext"><?php echo $t['loading_subtitle']; ?></div>
|
||
</div>
|
||
|
||
<div class="dummylab-wrap">
|
||
<!-- Header Banner -->
|
||
<div class="dummylab-header">
|
||
<div>
|
||
<h1>🧪 DummyLab <span style="font-size: 14px; font-weight: 400; color: #646970;">v1.2.0</span></h1>
|
||
<p><?php echo $t['created_by']; ?> <a href="https://masbudi.my.id" target="_blank" style="text-decoration: none; font-weight: 600; color: #2271b1;">masbudikusuma</a> • <a href="https://apps.masbudikusuma.my.id/dummylab-wp" target="_blank" style="text-decoration: none; color: #2271b1;"><?php echo $t['plugin_doc']; ?></a></p>
|
||
</div>
|
||
<!-- UI Language Switcher -->
|
||
<div class="dummylab-lang-switch">
|
||
<a href="<?php echo esc_url(add_query_arg('ui_lang', 'id')); ?>" class="dummylab-lang-btn <?php echo $ui_lang === 'id' ? 'active' : ''; ?>">🇮🇩 ID</a>
|
||
<a href="<?php echo esc_url(add_query_arg('ui_lang', 'en')); ?>" class="dummylab-lang-btn <?php echo $ui_lang === 'en' ? 'active' : ''; ?>">🇬🇧 EN</a>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if (isset($_GET['status'])): ?>
|
||
<div class="notice notice-success is-dismissible" style="border-radius: 6px; margin-bottom: 20px; padding: 12px 16px;">
|
||
<p style="font-size: 14px; margin: 0; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;">
|
||
<?php
|
||
if ($_GET['status'] === 'generated') {
|
||
$gen_type = isset($_GET['type']) && $_GET['type'] === 'page' ? 'page' : 'post';
|
||
$type_label = ($gen_type === 'page') ? ($ui_lang === 'en' ? 'Pages' : 'Halaman (Page)') : ($ui_lang === 'en' ? 'Posts' : 'Post');
|
||
$target_url = ($gen_type === 'page') ? admin_url('edit.php?post_type=page') : admin_url('edit.php');
|
||
|
||
echo '<span>🎉 <strong>' . esc_html(intval($_GET['count'])) . '</strong> ' . esc_html($t['msg_generated']) . ' ' . sprintf(esc_html($t['check_msg']), '<strong>' . esc_html($type_label) . '</strong>') . '</span>';
|
||
echo '<a href="' . esc_url($target_url) . '" class="button button-secondary" style="font-weight: 600; text-decoration: none;">' . esc_html($t['btn_view_list']) . ' ' . esc_html($type_label) . ' →</a>';
|
||
} elseif ($_GET['status'] === 'purged') {
|
||
echo '<span>🧹 <strong>' . esc_html(intval($_GET['count'])) . '</strong> ' . esc_html($t['msg_purged']) . '</span>';
|
||
}
|
||
?>
|
||
</p>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="dummylab-container">
|
||
<!-- Left Main Form -->
|
||
<div class="dummylab-main-card">
|
||
<form id="dummylab-generate-form" method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
|
||
<?php wp_nonce_field('dummylab_generate_action', 'dummylab_nonce'); ?>
|
||
<input type="hidden" name="action" value="dummylab_generate">
|
||
<input type="hidden" name="ui_lang" value="<?php echo esc_attr($ui_lang); ?>">
|
||
|
||
<!-- Section 1: Core Settings -->
|
||
<div class="dummylab-section-title">⚙️ <?php echo $t['sec_general']; ?></div>
|
||
<div class="dummylab-grid">
|
||
<div class="dummylab-field">
|
||
<label for="post_count"><?php echo $t['lbl_count']; ?></label>
|
||
<input type="number" id="post_count" name="post_count" value="5" min="1" max="50" required>
|
||
</div>
|
||
<div class="dummylab-field">
|
||
<label for="post_type"><?php echo $t['lbl_type']; ?></label>
|
||
<select name="post_type" id="post_type">
|
||
<option value="post"><?php echo $t['opt_post']; ?></option>
|
||
<option value="page"><?php echo $t['opt_page']; ?></option>
|
||
</select>
|
||
</div>
|
||
<div class="dummylab-field">
|
||
<label for="content_lang"><?php echo $t['lbl_content_lang']; ?></label>
|
||
<select name="content_lang" id="content_lang">
|
||
<option value="id">🇮🇩 Bahasa Indonesia</option>
|
||
<option value="en">🇬🇧 English</option>
|
||
</select>
|
||
</div>
|
||
<div class="dummylab-field">
|
||
<label for="post_status"><?php echo $t['lbl_status']; ?></label>
|
||
<select name="post_status" id="post_status">
|
||
<option value="publish"><?php echo $t['opt_publish']; ?></option>
|
||
<option value="draft"><?php echo $t['opt_draft']; ?></option>
|
||
<option value="pending"><?php echo $t['opt_pending']; ?></option>
|
||
<option value="private"><?php echo $t['opt_private']; ?></option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Section 2: Taxonomy & Author -->
|
||
<div class="dummylab-section-title">🏷️ <?php echo $t['sec_taxonomy']; ?></div>
|
||
<div class="dummylab-grid">
|
||
<div class="dummylab-field full-width">
|
||
<label for="categories"><?php echo $t['lbl_cats']; ?></label>
|
||
<input type="text" name="categories" id="categories" placeholder="Teknologi, Berita, Hiburan">
|
||
<p class="description"><?php echo $t['desc_cats']; ?></p>
|
||
</div>
|
||
<div class="dummylab-field full-width">
|
||
<label for="tags"><?php echo $t['lbl_tags']; ?></label>
|
||
<input type="text" name="tags" id="tags" placeholder="wordpress, dummy, test">
|
||
<p class="description"><?php echo $t['desc_tags']; ?></p>
|
||
</div>
|
||
<div class="dummylab-field">
|
||
<label for="post_author"><?php echo $t['lbl_author']; ?></label>
|
||
<select name="post_author" id="post_author">
|
||
<option value="random"><?php echo $t['opt_random_author']; ?></option>
|
||
<?php foreach ($users as $user): ?>
|
||
<option value="<?php echo esc_attr($user->ID); ?>"><?php echo esc_html($user->display_name); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<div class="dummylab-field">
|
||
<label for="date_option"><?php echo $t['lbl_date']; ?></label>
|
||
<select name="date_option" id="date_option">
|
||
<option value="now"><?php echo $t['opt_date_now']; ?></option>
|
||
<option value="random_past"><?php echo $t['opt_date_past']; ?></option>
|
||
<option value="future"><?php echo $t['opt_date_future']; ?></option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Section 3: Content Structure & Media -->
|
||
<div class="dummylab-section-title">📝 <?php echo $t['sec_content']; ?></div>
|
||
<div class="dummylab-grid">
|
||
<div class="dummylab-field">
|
||
<label for="content_length"><?php echo $t['lbl_length']; ?></label>
|
||
<select name="content_length" id="content_length">
|
||
<option value="short"><?php echo $t['opt_len_short']; ?></option>
|
||
<option value="medium" selected><?php echo $t['opt_len_medium']; ?></option>
|
||
<option value="long"><?php echo $t['opt_len_long']; ?></option>
|
||
</select>
|
||
</div>
|
||
<div class="dummylab-field">
|
||
<label for="image_size"><?php echo $t['lbl_image_size']; ?></label>
|
||
<select name="image_size" id="image_size">
|
||
<option value="800/600"><?php echo $t['opt_img_small']; ?></option>
|
||
<option value="1200/800" selected><?php echo $t['opt_img_med']; ?></option>
|
||
<option value="1600/1000"><?php echo $t['opt_img_large']; ?></option>
|
||
</select>
|
||
</div>
|
||
<div class="dummylab-field full-width">
|
||
<div class="dummylab-checkbox-group">
|
||
<label><input type="checkbox" name="use_featured_image" value="1" checked> 🖼️ <?php echo $t['opt_use_img']; ?></label>
|
||
<label><input type="checkbox" name="add_comments" value="1"> 💬 <?php echo $t['opt_comments']; ?></label>
|
||
<label><input type="checkbox" name="make_sticky" value="1"> 📌 <?php echo $t['opt_sticky']; ?></label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top: 24px;">
|
||
<input type="submit" id="dummylab-submit-btn" class="button button-primary dummylab-btn-primary" value="<?php echo esc_attr($t['btn_generate']); ?>">
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Right Sidebar Column -->
|
||
<div class="dummylab-sidebar">
|
||
<!-- Rollback Card -->
|
||
<div class="dummylab-side-card purge-card">
|
||
<h3>🗑️ <?php echo $t['purge_title']; ?></h3>
|
||
<p style="font-size: 13px; color: #50575e; margin: 0 0 12px 0;">
|
||
<?php echo $t['purge_active']; ?>: <span class="dummylab-badge-count"><?php echo esc_html($dummy_count); ?></span>
|
||
</p>
|
||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
|
||
<?php wp_nonce_field('dummylab_purge_action', 'dummylab_nonce'); ?>
|
||
<input type="hidden" name="action" value="dummylab_purge">
|
||
<input type="hidden" name="ui_lang" value="<?php echo esc_attr($ui_lang); ?>">
|
||
<p class="description" style="margin-bottom: 14px;"><?php echo $t['purge_desc']; ?></p>
|
||
<?php submit_button($t['btn_purge'], 'delete dummylab-btn-danger', 'submit', false, ['disabled' => ($dummy_count === 0)]); ?>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- How to Use Documentation Card -->
|
||
<div class="dummylab-side-card">
|
||
<h3>📘 <?php echo $t['guide_title']; ?></h3>
|
||
<ol class="dummylab-guide-list">
|
||
<li><?php echo $t['guide_step1']; ?></li>
|
||
<li><?php echo $t['guide_step2']; ?></li>
|
||
<li><?php echo $t['guide_step3']; ?></li>
|
||
<li><?php echo $t['guide_step4']; ?></li>
|
||
</ol>
|
||
</div>
|
||
|
||
<!-- Safety & Features Info Card -->
|
||
<div class="dummylab-side-card" style="background-color: #f8fafc;">
|
||
<h3>🛡️ <?php echo $t['safety_title']; ?></h3>
|
||
<ul class="dummylab-safety-list">
|
||
<li><?php echo $t['safety_item1']; ?></li>
|
||
<li><?php echo $t['safety_item2']; ?></li>
|
||
<li><?php echo $t['safety_item3']; ?></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var form = document.getElementById('dummylab-generate-form');
|
||
if (form) {
|
||
form.addEventListener('submit', function() {
|
||
var overlay = document.getElementById('dummylab-loading-overlay');
|
||
var btn = document.getElementById('dummylab-submit-btn');
|
||
if (overlay) {
|
||
overlay.style.display = 'flex';
|
||
}
|
||
if (btn) {
|
||
btn.disabled = true;
|
||
btn.value = '⏳ Generating...';
|
||
}
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
<?php
|
||
}
|
||
|
||
private function get_translations($lang) {
|
||
if ($lang === 'en') {
|
||
return [
|
||
'created_by' => 'Created by',
|
||
'plugin_doc' => 'Plugin Documentation',
|
||
'msg_generated' => 'dummy item(s) generated successfully!',
|
||
'check_msg' => 'Please check your %s section.',
|
||
'btn_view_list' => 'View List of',
|
||
'msg_purged' => 'dummy items deleted successfully!',
|
||
'loading_title' => 'Generating dummy content...',
|
||
'loading_subtitle' => 'Please wait a few moments while we create your test data and images.',
|
||
'sec_general' => 'General Settings',
|
||
'sec_taxonomy' => 'Taxonomy & Author',
|
||
'sec_content' => 'Content & Media',
|
||
'lbl_count' => 'Post/Page Count',
|
||
'lbl_type' => 'Content Type',
|
||
'opt_post' => 'Post',
|
||
'opt_page' => 'Page',
|
||
'lbl_content_lang' => 'Content Language',
|
||
'lbl_status' => 'Post Status',
|
||
'opt_publish' => 'Publish',
|
||
'opt_draft' => 'Draft',
|
||
'opt_pending' => 'Pending Review',
|
||
'opt_private' => 'Private',
|
||
'lbl_cats' => 'Categories',
|
||
'desc_cats' => 'Categories created automatically if not present. Comma-separated.',
|
||
'lbl_tags' => 'Additional Tags',
|
||
'desc_tags' => 'Optional, comma-separated tags.',
|
||
'lbl_author' => 'Author',
|
||
'opt_random_author' => 'Random from all users',
|
||
'lbl_date' => 'Post Date',
|
||
'opt_date_now' => 'Current time',
|
||
'opt_date_past' => 'Random in past few days',
|
||
'opt_date_future' => 'Future date (Scheduled)',
|
||
'lbl_length' => 'Article Length',
|
||
'opt_len_short' => 'Short (2-3 paragraphs)',
|
||
'opt_len_medium' => 'Medium (4-6 paragraphs + heading)',
|
||
'opt_len_long' => 'Long (7-10 paragraphs + heading, quote)',
|
||
'lbl_image_size' => 'Featured Image Size',
|
||
'opt_use_img' => 'Include random image from Picsum Photos',
|
||
'opt_img_small' => 'Small (800x600)',
|
||
'opt_img_med' => 'Medium (1200x800)',
|
||
'opt_img_large' => 'Large (1600x1000)',
|
||
'opt_comments' => 'Include dummy comments',
|
||
'opt_sticky' => 'Make first post sticky (Post type only)',
|
||
'btn_generate' => '🚀 Generate Dummy Data',
|
||
'purge_title' => 'Cleanup & Purge',
|
||
'purge_active' => 'Active dummy items',
|
||
'purge_desc' => 'Permanently deletes all posts, pages, and media attachments created by DummyLab.',
|
||
'btn_purge' => 'Delete All Dummy Data',
|
||
'guide_title' => 'Quick Usage Guide',
|
||
'guide_step1' => 'Select total count and content type (Post/Page).',
|
||
'guide_step2' => 'Choose generated text language and length.',
|
||
'guide_step3' => 'Check image box to auto-fetch thumbnails from Picsum.',
|
||
'guide_step4' => 'Click Purge anytime to completely clean test data.',
|
||
'safety_title' => 'Development Safety',
|
||
'safety_item1' => 'All dummy posts tracked via unique metadata key.',
|
||
'safety_item2' => 'Clean purge removes featured images from Media Library.',
|
||
'safety_item3' => 'Safe for staging and local theme testing.',
|
||
];
|
||
}
|
||
|
||
return [
|
||
'created_by' => 'Dibuat oleh',
|
||
'plugin_doc' => 'Dokumentasi Plugin',
|
||
'msg_generated' => 'konten dummy berhasil dibuat!',
|
||
'check_msg' => 'Silakan cek daftar %s Anda.',
|
||
'btn_view_list' => 'Lihat Daftar',
|
||
'msg_purged' => 'data dummy berhasil dibersihkan!',
|
||
'loading_title' => 'Sedang membuat konten dummy...',
|
||
'loading_subtitle' => 'Mohon tunggu beberapa saat. Server sedang mengunduh gambar dan membuat data artikel.',
|
||
'sec_general' => 'Pengaturan Utama',
|
||
'sec_taxonomy' => 'Taksonomi & Penulis',
|
||
'sec_content' => 'Konten & Media',
|
||
'lbl_count' => 'Jumlah Post/Halaman',
|
||
'lbl_type' => 'Tipe Konten',
|
||
'opt_post' => 'Post',
|
||
'opt_page' => 'Halaman (Page)',
|
||
'lbl_content_lang' => 'Bahasa Konten',
|
||
'lbl_status' => 'Status Post',
|
||
'opt_publish' => 'Publish (terbit)',
|
||
'opt_draft' => 'Draft',
|
||
'opt_pending' => 'Pending Review',
|
||
'opt_private' => 'Private',
|
||
'lbl_cats' => 'Kategori',
|
||
'desc_cats' => 'Kategori dibuat otomatis jika belum ada. Pisahkan dengan koma.',
|
||
'lbl_tags' => 'Tag Tambahan',
|
||
'desc_tags' => 'Opsional, pisahkan dengan koma.',
|
||
'lbl_author' => 'Penulis',
|
||
'opt_random_author' => 'Acak dari semua pengguna',
|
||
'lbl_date' => 'Tanggal Post',
|
||
'opt_date_now' => 'Waktu sekarang',
|
||
'opt_date_past' => 'Acak dalam beberapa hari terakhir',
|
||
'opt_date_future' => 'Rentang tanggal tertentu (Scheduled)',
|
||
'lbl_length' => 'Panjang Artikel',
|
||
'opt_len_short' => 'Pendek (2-3 paragraf)',
|
||
'opt_len_medium' => 'Sedang (4-6 paragraf + heading)',
|
||
'opt_len_long' => 'Panjang (7-10 paragraf + heading, quote)',
|
||
'lbl_image_size' => 'Ukuran Gambar Unggulan',
|
||
'opt_use_img' => 'Sertakan gambar acak dari Picsum Photos',
|
||
'opt_img_small' => 'Kecil (800x600)',
|
||
'opt_img_med' => 'Sedang (1200x800)',
|
||
'opt_img_large' => 'Besar (1600x1000)',
|
||
'opt_comments' => 'Sertakan komentar dummy',
|
||
'opt_sticky' => 'Jadikan post pertama sebagai sticky post (khusus Post)',
|
||
'btn_generate' => '🚀 Generate Data Dummy',
|
||
'purge_title' => 'Pembersihan & Purge',
|
||
'purge_active' => 'Total data dummy aktif',
|
||
'purge_desc' => 'Tindakan ini akan menghapus permanen seluruh post, page, dan gambar yang dibuat oleh DummyLab.',
|
||
'btn_purge' => 'Hapus Semua Data Dummy',
|
||
'guide_title' => 'Panduan Penggunaan',
|
||
'guide_step1' => 'Pilih jumlah data dan tipe konten (Post atau Halaman).',
|
||
'guide_step2' => 'Atur bahasa dan panjang artikel yang akan dihasilkan.',
|
||
'guide_step3' => 'Centang opsi gambar untuk mengunduh thumbnail dari Picsum.',
|
||
'guide_step4' => 'Gunakan tombol Purge untuk menghapus semua data pengujian.',
|
||
'safety_title' => 'Pengembangan Aman',
|
||
'safety_item1' => 'Setiap postingan dummy dilindungi metadata internal unik.',
|
||
'safety_item2' => 'Fitur Purge juga membersihkan berkas gambar dari Media Library.',
|
||
'safety_item3' => 'Aman digunakan pada lingkungan staging maupun lokal.',
|
||
];
|
||
}
|
||
|
||
public function handle_generate() {
|
||
if (!current_user_can('manage_options') || !check_admin_referer('dummylab_generate_action', 'dummylab_nonce')) {
|
||
wp_die('Akses ditolak.');
|
||
}
|
||
|
||
require_once(ABSPATH . 'wp-admin/includes/image.php');
|
||
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
||
require_once(ABSPATH . 'wp-admin/includes/media.php');
|
||
|
||
$ui_lang = isset($_POST['ui_lang']) ? sanitize_text_field($_POST['ui_lang']) : 'id';
|
||
$count = isset($_POST['post_count']) ? min(50, max(1, intval($_POST['post_count']))) : 5;
|
||
$post_type = isset($_POST['post_type']) && in_array($_POST['post_type'], ['post', 'page']) ? $_POST['post_type'] : 'post';
|
||
$lang = isset($_POST['content_lang']) ? sanitize_text_field($_POST['content_lang']) : 'id';
|
||
$status = isset($_POST['post_status']) ? sanitize_text_field($_POST['post_status']) : 'publish';
|
||
$categories_raw = isset($_POST['categories']) ? sanitize_text_field($_POST['categories']) : '';
|
||
$tags_raw = isset($_POST['tags']) ? sanitize_text_field($_POST['tags']) : '';
|
||
$author_opt = isset($_POST['post_author']) ? sanitize_text_field($_POST['post_author']) : 'random';
|
||
$date_opt = isset($_POST['date_option']) ? sanitize_text_field($_POST['date_option']) : 'now';
|
||
$content_length = isset($_POST['content_length']) ? sanitize_text_field($_POST['content_length']) : 'medium';
|
||
$use_image = isset($_POST['use_featured_image']) ? true : false;
|
||
$image_size = isset($_POST['image_size']) ? sanitize_text_field($_POST['image_size']) : '1200/800';
|
||
$add_comments = isset($_POST['add_comments']) ? true : false;
|
||
$make_sticky = isset($_POST['make_sticky']) ? true : false;
|
||
|
||
$cat_ids = [];
|
||
if ($post_type === 'post' && !empty($categories_raw)) {
|
||
$cat_names = array_map('trim', explode(',', $categories_raw));
|
||
foreach ($cat_names as $cat_name) {
|
||
if (empty($cat_name)) continue;
|
||
$term = term_exists($cat_name, 'category');
|
||
if (!$term) {
|
||
$term = wp_insert_term($cat_name, 'category');
|
||
}
|
||
if (!is_wp_error($term)) {
|
||
$cat_ids[] = (int) $term['term_id'];
|
||
}
|
||
}
|
||
}
|
||
|
||
$tag_names = !empty($tags_raw) ? array_map('trim', explode(',', $tags_raw)) : [];
|
||
$user_ids = get_users(['fields' => 'ID']);
|
||
|
||
for ($i = 0; $i < $count; $i++) {
|
||
$author_id = ($author_opt === 'random') ? $user_ids[array_rand($user_ids)] : intval($author_opt);
|
||
|
||
$post_date = current_time('mysql');
|
||
$final_status = $status;
|
||
if ($date_opt === 'random_past') {
|
||
$days_back = rand(1, 30);
|
||
$post_date = date('Y-m-d H:i:s', strtotime("-$days_back days"));
|
||
} elseif ($date_opt === 'future') {
|
||
$days_ahead = rand(1, 15);
|
||
$post_date = date('Y-m-d H:i:s', strtotime("+$days_ahead days"));
|
||
$final_status = 'future';
|
||
}
|
||
|
||
$title = $this->get_sample_title($lang, $i);
|
||
$content = $this->get_sample_content($lang, $content_length);
|
||
|
||
$post_data = [
|
||
'post_title' => $title,
|
||
'post_content' => $content,
|
||
'post_status' => $final_status,
|
||
'post_type' => $post_type,
|
||
'post_author' => $author_id,
|
||
'post_date' => $post_date,
|
||
];
|
||
|
||
if ($post_type === 'post' && !empty($cat_ids)) {
|
||
$post_data['post_category'] = [$cat_ids[array_rand($cat_ids)]];
|
||
}
|
||
|
||
if ($post_type === 'post' && !empty($tag_names)) {
|
||
$post_data['tags_input'] = $tag_names;
|
||
}
|
||
|
||
$post_id = wp_insert_post($post_data);
|
||
|
||
if ($post_id && !is_wp_error($post_id)) {
|
||
update_post_meta($post_id, $this->meta_key, '1');
|
||
|
||
if ($use_image) {
|
||
$image_url = 'https://picsum.photos/' . $image_size . '?random=' . rand(1, 9999);
|
||
$tmp = download_url($image_url);
|
||
if (!is_wp_error($tmp)) {
|
||
$file_array = [
|
||
'name' => 'dummylab-' . $post_id . '.jpg',
|
||
'tmp_name' => $tmp
|
||
];
|
||
$attach_id = media_handle_sideload($file_array, $post_id);
|
||
if (!is_wp_error($attach_id)) {
|
||
set_post_thumbnail($post_id, $attach_id);
|
||
update_post_meta($attach_id, $this->meta_key, '1');
|
||
}
|
||
@unlink($tmp);
|
||
}
|
||
}
|
||
|
||
if ($i === 0 && $make_sticky && $post_type === 'post') {
|
||
stick_post($post_id);
|
||
}
|
||
|
||
if ($add_comments) {
|
||
$comment_count = rand(1, 3);
|
||
for ($c = 0; $c < $comment_count; $c++) {
|
||
wp_insert_comment([
|
||
'comment_post_ID' => $post_id,
|
||
'comment_author' => 'Tester Dummy',
|
||
'comment_author_email' => '[email protected]',
|
||
'comment_content' => ($lang === 'id') ? 'Artikel yang sangat bermanfaat dan informatif!' : 'Great content, thanks for sharing!',
|
||
'comment_approved' => 1,
|
||
]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
wp_redirect(admin_url('tools.php?page=dummylab&ui_lang=' . $ui_lang . '&status=generated&count=' . $count . '&type=' . $post_type));
|
||
exit;
|
||
}
|
||
|
||
public function handle_purge() {
|
||
if (!current_user_can('manage_options') || !check_admin_referer('dummylab_purge_action', 'dummylab_nonce')) {
|
||
wp_die('Akses ditolak.');
|
||
}
|
||
|
||
$ui_lang = isset($_POST['ui_lang']) ? sanitize_text_field($_POST['ui_lang']) : 'id';
|
||
|
||
$query = new WP_Query([
|
||
'post_type' => ['post', 'page', 'attachment'],
|
||
'posts_per_page' => -1,
|
||
'meta_key' => $this->meta_key,
|
||
'meta_value' => '1',
|
||
'fields' => 'ids',
|
||
'post_status' => 'any',
|
||
]);
|
||
|
||
$purged_count = 0;
|
||
if (!empty($query->posts)) {
|
||
foreach ($query->posts as $post_id) {
|
||
if (wp_delete_post($post_id, true)) {
|
||
$purged_count++;
|
||
}
|
||
}
|
||
}
|
||
|
||
wp_redirect(admin_url('tools.php?page=dummylab&ui_lang=' . $ui_lang . '&status=purged&count=' . $purged_count));
|
||
exit;
|
||
}
|
||
|
||
private function get_sample_title($lang, $index) {
|
||
$titles_id = [
|
||
'Panduan Lengkap Pengembangan Infrastruktur Web Modern',
|
||
'Mengoptimalkan Performa Database untuk Trafik Tinggi',
|
||
'Desain Responsif dan Pengalaman Pengguna Terbaik',
|
||
'Strategi Keamanan Server dan Arsitektur Komputasi Awan',
|
||
'Manajemen Konten Efektif untuk Pertumbuhan Bisnis'
|
||
];
|
||
$titles_en = [
|
||
'Exploring the Future of Scalable Web Architecture',
|
||
'10 Essential Practices for High-Performance Servers',
|
||
'Understanding Modern UI/UX Design Principles',
|
||
'Building Secure Application Infrastructures',
|
||
'Optimizing Database Queries for Enterprise Solutions'
|
||
];
|
||
$arr = ($lang === 'id') ? $titles_id : $titles_en;
|
||
return $arr[array_rand($arr)] . ' #' . rand(100, 999);
|
||
}
|
||
|
||
private function get_sample_content($lang, $length) {
|
||
$p_id = [
|
||
'Pengembangan aplikasi web modern memerlukan perhatian ekstra pada arsitektur sistem dasar. Komponen seperti manajemen memori, optimasi kueri, dan konfigurasi server menjadi kunci utama.',
|
||
'Dengan menerapkan standar keamanan terbaik, kita dapat mencegah potensi bahaya siber dan memastikan layanan tetap stabil di bawah beban lalu lintas data yang tinggi.',
|
||
'Pengalaman pengguna merupakan elemen krusial. Tata letak visual yang konsisten serta navigasi intuitif memudahkan pengunjung dalam menemukan informasi secara cepat.'
|
||
];
|
||
|
||
$p_en = [
|
||
'Modern web applications require strict adherence to solid system architectures. Key aspects include efficient database queries, memory management, and caching layer implementation.',
|
||
'Ensuring continuous infrastructure security prevents vulnerabilities while guaranteeing optimal uptime during high-volume traffic spikes.',
|
||
'User experience design directly impacts engagement rates. Clean layouts, readable typography, and intuitive interfaces make content consumption seamless.'
|
||
];
|
||
|
||
$paragraphs = ($lang === 'id') ? $p_id : $p_en;
|
||
$output = '';
|
||
|
||
$loops = ($length === 'short') ? 2 : (($length === 'long') ? 7 : 4);
|
||
for ($k = 0; $k < $loops; $k++) {
|
||
$output .= '<p>' . $paragraphs[array_rand($paragraphs)] . '</p>';
|
||
if ($length !== 'short' && $k === 1) {
|
||
$output .= '<h2>' . (($lang === 'id') ? 'Sub-judul Informasi Penting' : 'Key Technical Insights') . '</h2>';
|
||
}
|
||
if ($length === 'long' && $k === 3) {
|
||
$output .= '<blockquote><p>' . (($lang === 'id') ? 'Keamanan dan kecepatan adalah fondasi utama pengembangan web.' : 'Security and performance are the core foundations of web development.') . '</p></blockquote>';
|
||
}
|
||
}
|
||
|
||
return $output;
|
||
}
|
||
}
|
||
|
||
register_activation_hook(__FILE__, ['DummyLab', 'activate_plugin']);
|
||
DummyLab::get_instance();
|