Skip to content

Instantly share code, notes, and snippets.

@zecka
Last active April 29, 2020 18:17
Show Gist options
  • Save zecka/def5c2e01c353aaa4cf41bcc37fb0946 to your computer and use it in GitHub Desktop.
Save zecka/def5c2e01c353aaa4cf41bcc37fb0946 to your computer and use it in GitHub Desktop.
Make Bulk taks tool in WordPress admin
<?php
/*
USAGE:
$task = new WP_Bulk_Task('test-bulk-task', 'product');
$task->set_callback(function($post){
error_log($post->ID);
});
$task->set_posts_per_page(1);
$task->register();
*/
class WP_Bulk_Task {
public $posts_per_page;
public function __construct($slug, $post_type, $title=null) {
$this->slug = $slug;
$this->title = ($title!==null) ? $title : $slug;
$this->post_type = $post_type;
$this->posts_per_page = 10;
$this->capabilities = 'install_plugins';
$this->position = 10;
$this->nonce = 'wp-bulk-task';
$this->btn_label = "Run bulk task";
$this->need_confirmation = true;
$this->confirmation_message = "Are you sure ?";
}
public function set_posts_per_page($posts_per_page) {
$this->posts_per_page = $posts_per_page;
}
public function register() {
add_action('admin_init', [$this, 'set_nonce']);
add_action('admin_menu', array($this, 'admin_menu'));
add_action('wp_ajax_' . $this->slug, [$this, 'ajax_action']); // executed when logged in
add_action('wp_ajax_nopriv_' . $this->slug, [$this, 'ajax_action_nopriv']); // executed when logged out
}
public function set_btn_label($label){
$this->btn_label = $label;
}
public function set_confirmation($is_needed, $message=null){
if($message!==null){
$this->confirmation_message = $message;
}
$this->need_confirmation = $is_needed;
}
public function set_nonce() {
$this->nonce = wp_create_nonce($this->slug);
}
public function ajax_action_nopriv() {
return wp_send_json_error(['message' => 'must be logged']);
}
public function loop_args() {
$paged = ($_POST['paged']) ? $_POST['paged'] : 1;
$args = [
'post_type' => $this->post_type,
'posts_per_page' => $this->posts_per_page,
'paged' => $paged,
];
$args = apply_filters('wpbt_loops_args', $args);
return apply_filters('wpbt_loops_args_'.$this->slug, $args);
}
public function ajax_action() {
$this->validate_ajax_action();
$paged = ($_POST['paged']) ? $_POST['paged'] : 1;
$query = new WP_Query($this->loop_args());
$max_num_pages = $query->max_num_pages;
$logs = [];
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
global $post;
$new_logs = call_user_func($this->callback, $post);
if (is_array($new_logs)) {
$logs = array_merge($logs, $new_logs);
} elseif ($new_logs) {
$logs = array_merge($logs, [$new_logs]);
}
}
}
wp_send_json_success([
'max_num_pages' => $max_num_pages,
'paged' => (int)$paged,
'logs' => $logs,
]);
}
public function set_callback($callback) {
$this->callback = $callback;
}
public function admin_menu() {
$hook = add_management_page(
$this->title,
$this->title,
$this->capabilities,
$this->slug,
[$this, 'admin_page_content'],
$this->position
);
add_action("load-$hook", array($this, 'admin_page_load'));
}
public function admin_page_load() {
// ...
}
public function admin_page_content() {
$this->admin_page_style();
$this->admin_page_script();
?>
<div class="wrap">
<h1><?php echo $this->title ?></h1>
<div style="margin-bottom: 20px;"><?php do_action('wpbt_before_content', $this->slug); ?></div>
<button id="wpbt-runner" class="button"><?php echo $this->btn_label; ?></button>
<div><?php do_action('wpbt_after_button', $this->slug); ?></div>
<div class="wpbt-progress__percent">0%</div>
<div class="wpbt-progress">
<div class="wpbt-progress__bar" style="width: 0%;"></div>
</div>
<div class="wpbt-logs"></div>
<?php do_action('wpbt_after_content', $this->slug); ?>
</div>
<?php
}
public function admin_page_script() {
?>
<script>
jQuery(document).ready(function($){
var wpbtCount = 0;
function setPercentage(current, max){
var percent = Math.round(current / max * 100);
$('.wpbt-progress__percent').html(percent+'%');
$('.wpbt-progress__bar').css( "width",percent+ "%" );
}
function putLogs(logs, currentPage){
for(var i = 0; i < logs.length; i++ ){
wpbtCount++;
$('.wpbt-logs').prepend('<div><strong>'+wpbtCount+'</strong> | '+logs[i]+'</div>');
}
}
function doBulkTask(paged) {
var data = {
action: "<?php echo $this->slug; ?>",
nonce: "<?php echo $this->nonce; ?>",
paged: paged
};
$.ajax({
type: "post",
url: "<?php echo admin_url('admin-ajax.php') ?>",
data: data,
error: (response, error) => {
console.error("response", response);
console.error("error", error);
},
success: response => {
var max_num_pages = response.data.max_num_pages;
var currentPage = response.data.paged;
if (max_num_pages > currentPage) {
setPercentage(currentPage, max_num_pages);
currentPage++;
doBulkTask(currentPage)
} else {
setPercentage(currentPage, max_num_pages);
}
putLogs(response.data.logs, currentPage);
}
});
}
$('#wpbt-runner').on('click', function(){
<?php if($this->need_confirmation): ?>
var confrimation = confirm("<?php echo $this->confirmation_message; ?>");
if(!confrimation){
return false;
}
<?php endif; ?>
$(this).prop('disabled', true);
doBulkTask(1)
});
});
</script>
<?php
}
public function admin_page_style() {
?>
<style>
.wpbt-progress{
margin-top: 20px;
width: 100%;
height: 40px;
border-radius: 10px;
background: white;
border: 1px solid -internal-root-color;
display: flex;
overflow: hidden;
}
.wpbt-progress__bar{
background-color: blue;
}
.wpbt-progress__percent{
text-align: center;
}
.wpbt-logs{
background: white;
max-height: 400px;
overflow-y: auto;
}
.wpbt-logs > div{
padding: 5px;
}
</style>
<?php
}
private function validate_ajax_action(){
if ( !wp_verify_nonce($_POST['nonce'], $this->slug)) {
wp_send_json_error(['message' => 'Invalid Ajax Action']);
die();
}
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
return true;
} else {
wp_send_json_error(['message' => 'Invalid Ajax Action']);
die();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment