415 lines
20 KiB
PHP
415 lines
20 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.0.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_post_dummylab_generate', [$this, 'handle_generate']);
|
||
add_action('admin_post_dummylab_purge', [$this, 'handle_purge']);
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
$users = get_users(['fields' => ['ID', 'display_name']]);
|
||
|
||
$query = new WP_Query([
|
||
'post_type' => ['post', 'page'],
|
||
'posts_per_page' => -1,
|
||
'meta_key' => $this->meta_key,
|
||
'meta_value' => '1',
|
||
'fields' => 'ids',
|
||
'post_status' => 'any',
|
||
]);
|
||
$dummy_count = $query->found_posts;
|
||
?>
|
||
<div class="wrap">
|
||
<h1>🧪 DummyLab – Post & Page Generator</h1>
|
||
<p>Dibuat oleh <a href="https://masbudi.my.id" target="_blank">masbudikusuma</a> | <a href="https://apps.masbudikusuma.my.id/dummylab-wp" target="_blank">Dokumentasi Plugin</a></p>
|
||
<hr />
|
||
|
||
<?php if (isset($_GET['status'])): ?>
|
||
<div class="notice notice-success is-dismissible">
|
||
<p>
|
||
<?php
|
||
if ($_GET['status'] === 'generated') {
|
||
echo esc_html(intval($_GET['count'])) . ' kontent dummy berhasil dibuat!';
|
||
} elseif ($_GET['status'] === 'purged') {
|
||
echo esc_html(intval($_GET['count'])) . ' data dummy berhasil dibersihkan!';
|
||
}
|
||
?>
|
||
</p>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div style="display: flex; gap: 20px; align-items: flex-start; margin-top: 20px;">
|
||
<div class="card" style="max-width: 650px; width: 100%; padding: 20px;">
|
||
<h2>Generate Content Dummy</h2>
|
||
<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">
|
||
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row"><label for="post_count">Jumlah Post/Halaman</label></th>
|
||
<td><input type="number" id="post_count" name="post_count" value="5" min="1" max="50" class="small-text" required></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="post_type">Tipe Konten</label></th>
|
||
<td>
|
||
<select name="post_type" id="post_type">
|
||
<option value="post">Post</option>
|
||
<option value="page">Halaman (Page)</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="content_lang">Bahasa Konten</label></th>
|
||
<td>
|
||
<select name="content_lang" id="content_lang">
|
||
<option value="id">Bahasa Indonesia</option>
|
||
<option value="en">English</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="post_status">Status Post</label></th>
|
||
<td>
|
||
<select name="post_status" id="post_status">
|
||
<option value="publish">Publish (terbit)</option>
|
||
<option value="draft">Draft</option>
|
||
<option value="pending">Pending Review</option>
|
||
<option value="private">Private</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="categories">Kategori</label></th>
|
||
<td>
|
||
<input type="text" name="categories" id="categories" class="regular-text" placeholder="Teknologi, Berita, Hiburan">
|
||
<p class="description">Kategori dibuat otomatis jika belum ada. Pisahkan dengan koma. Tidak berlaku untuk Halaman.</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="tags">Tag Tambahan</label></th>
|
||
<td>
|
||
<input type="text" name="tags" id="tags" class="regular-text" placeholder="wordpress, dummy, test">
|
||
<p class="description">Opsional, pisahkan dengan koma.</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="post_author">Penulis</label></th>
|
||
<td>
|
||
<select name="post_author" id="post_author">
|
||
<option value="random">Acak dari semua pengguna</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>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="date_option">Tanggal Post</label></th>
|
||
<td>
|
||
<select name="date_option" id="date_option">
|
||
<option value="now">Waktu sekarang</option>
|
||
<option value="random_past">Acak dalam beberapa hari terakhir</option>
|
||
<option value="future">Rentang tanggal tertentu (Future/Scheduled)</option>
|
||
</select>
|
||
<p class="description">Jika tanggal di masa depan, status otomatis "Scheduled".</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="content_length">Panjang Artikel</label></th>
|
||
<td>
|
||
<select name="content_length" id="content_length">
|
||
<option value="short">Pendek (2-3 paragraf)</option>
|
||
<option value="medium" selected>Sedang (4-6 paragraf + heading)</option>
|
||
<option value="long">Panjang (7-10 paragraf + heading, list, quote)</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Gambar Unggulan</th>
|
||
<td>
|
||
<label><input type="checkbox" name="use_featured_image" value="1"> Sertakan gambar acak dari Picsum Photos</label><br><br>
|
||
<select name="image_size" id="image_size">
|
||
<option value="800/600">Kecil (800x600)</option>
|
||
<option value="1200/800" selected>Sedang (1200x800)</option>
|
||
<option value="1600/1000">Besar (1600x1000)</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Opsi Tambahan</th>
|
||
<td>
|
||
<label><input type="checkbox" name="add_comments" value="1"> Sertakan komentar dummy</label><br>
|
||
<label><input type="checkbox" name="make_sticky" value="1"> Jadikan post pertama sebagai sticky post (khusus Post)</label>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<?php submit_button('Generate Data Dummy', 'primary', 'submit'); ?>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="card" style="max-width: 300px; width: 100%; border-left: 4px solid #dc3232; padding: 20px;">
|
||
<h2>Cleanup / Rollback</h2>
|
||
<p>Total data dummy aktif: <strong><?php echo esc_html($dummy_count); ?></strong></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">
|
||
<p class="description">Tindakan ini akan menghapus permanen seluruh post, page, dan gambar yang dibuat oleh DummyLab.</p>
|
||
<?php submit_button('Hapus Semua Data Dummy', 'delete', 'submit', true, ['disabled' => ($dummy_count === 0)]); ?>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
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');
|
||
|
||
$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;
|
||
|
||
// Process categories
|
||
$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'];
|
||
}
|
||
}
|
||
}
|
||
|
||
// Process tags
|
||
$tag_names = !empty($tags_raw) ? array_map('trim', explode(',', $tags_raw)) : [];
|
||
|
||
// Users pool
|
||
$user_ids = get_users(['fields' => 'ID']);
|
||
|
||
for ($i = 0; $i < $count; $i++) {
|
||
// Determine Author
|
||
$author_id = ($author_opt === 'random') ? $user_ids[array_rand($user_ids)] : intval($author_opt);
|
||
|
||
// Determine Date
|
||
$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';
|
||
}
|
||
|
||
// Build Content & Title
|
||
$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');
|
||
|
||
// Featured Image via Picsum
|
||
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);
|
||
}
|
||
}
|
||
|
||
// Sticky option
|
||
if ($i === 0 && $make_sticky && $post_type === 'post') {
|
||
stick_post($post_id);
|
||
}
|
||
|
||
// Add comments
|
||
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&status=generated&count=' . $count));
|
||
exit;
|
||
}
|
||
|
||
public function handle_purge() {
|
||
if (!current_user_can('manage_options') || !check_admin_referer('dummylab_purge_action', 'dummylab_nonce')) {
|
||
wp_die('Akses ditolak.');
|
||
}
|
||
|
||
$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&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;
|
||
}
|
||
}
|
||
|
||
DummyLab::get_instance();
|