File: /var/www/dinamo-shop/wp-content/plugins/bulk-edit/index.php
<?php
/*
Plugin Name: Dinamo Bulk edit
Plugin URI: http://gnkdinamo.hr
Description: Dinamo bulk edit plugin
Version: 1.0
Author: Dinamo
Author URI: http://www.gnkdinamo.hr/
Text Domain: dinamo
*/
add_action( 'admin_enqueue_scripts', function(){
wp_enqueue_script( 'jquery-toast-js', plugins_url() . '/bulk-edit/jquery-toast-plugin-master/dist/jquery.toast.min.js', array('jquery'), '1.0', true );
//wp_enqueue_style( 'jquery-toast-css', plugins_url() . '/bulk-edit/jquery-toast-plugin-master/dist/jquery.toast.min.css', array(), '1.0', true );
});
add_action( 'admin_menu', 'sitepoint_settings_page' );
function sitepoint_settings_page() {
add_menu_page( "Bulk edit", "Bulk edit", "manage_bulk", "dinamo-bulk-edit", "bulk_page_display" );
$admin_role = get_role( 'administrator' );
$admin_role->add_cap( 'manage_bulk', true );
}
add_action( 'init', function(){
/* remove_role( 'product_manager' ); */
add_role( 'product_manager', 'Product Manager', array(
'read' => true,
'edit_posts' => true,
"manage_bulk" => true,
));
});
add_action( 'admin_menu', function(){
$curr_user = wp_get_current_user();
$menus = $GLOBALS[ 'menu' ];
if( in_array( 'product_manager', $curr_user->roles ) ){
foreach( $menus as $menu ){
if( $menu['2'] != 'dinamo-bulk-edit' ){
remove_menu_page( $menu['2'] );
}
}
}
}, 999);
add_action( 'current_screen', function(){
$screen = get_current_screen();
$curr_user = wp_get_current_user();
if( $screen->id != 'toplevel_page_dinamo-bulk-edit' && in_array( 'product_manager', $curr_user->roles ) ){
wp_redirect( admin_url('admin.php?page=dinamo-bulk-edit' ) );
}
});
function bulk_get_products( $query ){
ob_start();
if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
$product = wc_get_product(get_the_ID());
$lowstock = get_option('woocommerce_notify_low_stock_amount');
if($product->is_type('simple')){ ?>
<?php $stock = $product->get_total_stock(); ?>
<tr data-product-row="<?= get_the_ID(); ?>" <?= ( $stock <= $lowstock ) ? 'style="background-color: #fee"' : '' ?> >
<td><?= $product->get_sku(); ?></td>
<td><?= the_title(); ?></td>
<td>
<input data-product-price="<?= get_the_ID(); ?>" type="number" style="width:100px;" value="<?= $product->get_regular_price(); ?>" />
</td>
<td>
<input data-product-sale="<?= get_the_ID(); ?>" type="number" style="width:100px;" value="<?= $product->get_sale_price(); ?>" />
<?php
$sale_start = get_post_meta( get_the_ID(), '_sale_price_dates_from', true );
$sale_end = get_post_meta( get_the_ID(), '_sale_price_dates_to', true ); ?>
<br>
<?php
if($sale_start) {
$sale_start_val = date('Y-m-d', $sale_start);
}else{
$sale_start_val = "";
}
?>
<div style="display:none;">
<input data-product-sale-start="<?= get_the_ID(); ?>" style="width:100px;" type="text" value="<?= $sale_start_val ?>" placeholder="dd/mm/yyyy" onfocus="(this.type='date')" />
<br>
<?php
if($sale_end) {
$sale_end_val = date('Y-m-d', $sale_end);
}else{
$sale_end_val = "";
}
?>
<input data-product-sale-end="<?= get_the_ID(); ?>" style="width:100px;" type="text" value="<?= $sale_end_val ?>" placeholder="dd/mm/yyyy" onfocus="(this.type='date')" />
</div>
</td>
<td>
<input data-product-qt="<?= get_the_ID(); ?>" style="width:100px;" value="<?= $product->get_stock_quantity(); ?>" />
</td>
<td>
<button data-save-product="<?= get_the_ID(); ?>">Spremi</button>
</td>
</tr>
<?php } else {
$available_variations = $product->get_available_variations();
foreach ($available_variations as $variation) {
// var_dump($value);
$variation = new WC_Product_Variation( $variation['variation_id'] );
$manage_stock = $variation->get_manage_stock();
$stock = ( $manage_stock === true ) ? $variation->get_stock_quantity() : 0;
?>
<tr data-product-row="<?= $variation->get_id() ?>" <?= ( $variation->get_manage_stock() && ($stock <= $lowstock) ) ? 'style="background-color: #fee"' : '' ?>>
<td><?= $product->get_sku(); ?></td>
<td><?= $variation->name ?></td>
<td>
<input data-product-price="<?= $variation->get_id() ?>" type="number" style="width:100px;" value="<?= $variation->regular_price ?>" />
</td>
<td>
<input data-product-sale="<?= $variation->get_id() ?>" type="number" style="width:100px;" value="<?= $variation->sale_price ?>" />
<?php
$sale_start = get_post_meta( $variation->get_id(), '_sale_price_dates_from', true );
$sale_end = get_post_meta( $variation->get_id(), '_sale_price_dates_to', true ); ?>
<?php
if($sale_start) {
$sale_start_val = date('Y-m-d', $sale_start);
}else{
$sale_start_val = "";
}
?>
<?php
if($sale_end) {
$sale_end_val = date('Y-m-d', $sale_end);
}else{
$sale_end_val = "";
}
?>
<br>
<div style="display:none;">
<input data-product-sale-start="<?= $variation->get_id() ?>" style="width:100px;" type="text" value="<?= $sale_start_val ?>" placeholder="dd/mm/yyyy" onfocus="(this.type='date')" /> početak akcije
<br>
<input data-product-sale-end="<?= $variation->get_id() ?>" style="width:100px;" type="text" value="<?= $sale_end_val ?>" placeholder="dd/mm/yyyy" onfocus="(this.type='date')" /> kraj akcije
</div>
</td>
<td>
<?php if( $manage_stock !== true ) {
echo '<br>';
echo 'Upravljanje zalihama nije uključeno za varijaciju';
} else { ?>
<input data-product-qt="<?= $variation->get_id() ?>" style="width:100px;" value="<?= ( $manage_stock === true ) ? $variation->get_stock_quantity() : '' ?>" />
<?php } ?>
</td>
<td>
<button data-save-product="<?= $variation->get_id() ?>">Spremi</button>
</td>
</tr>
<?php }
?>
<?php } ?>
<?php
endwhile;
endif;
$content = ob_get_clean();
echo $content;
}
function bulk_page_display() {
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
);
$products_query = new WP_Query($args);
?>
<style>
.jq-toast-wrap,.jq-toast-wrap *{margin:0;padding:0}.jq-toast-wrap{display:block;position:fixed;width:250px;pointer-events:none!important;letter-spacing:normal;z-index:9000!important}.jq-toast-wrap.bottom-left{bottom:20px;left:20px}.jq-toast-wrap.bottom-right{bottom:20px;right:40px}.jq-toast-wrap.top-left{top:20px;left:20px}.jq-toast-wrap.top-right{top:20px;right:40px}.jq-toast-single{display:block;width:100%;padding:10px;margin:0 0 5px;border-radius:4px;font-size:12px;font-family:arial,sans-serif;line-height:17px;position:relative;pointer-events:all!important;background-color:#444;color:#fff}.jq-toast-single h2{font-family:arial,sans-serif;font-size:14px;margin:0 0 7px;background:0 0;color:inherit;line-height:inherit;letter-spacing:normal}.jq-toast-single a{color:#eee;text-decoration:none;font-weight:700;border-bottom:1px solid #fff;padding-bottom:3px;font-size:12px}.jq-toast-single ul{margin:0 0 0 15px;background:0 0;padding:0}.jq-toast-single ul li{list-style-type:disc!important;line-height:17px;background:0 0;margin:0;padding:0;letter-spacing:normal}.close-jq-toast-single{position:absolute;top:3px;right:7px;font-size:14px;cursor:pointer}.jq-toast-loader{display:block;position:absolute;top:-2px;height:5px;width:0;left:0;border-radius:5px;background:red}.jq-toast-loaded{width:100%}.jq-has-icon{padding:10px 10px 10px 50px;background-repeat:no-repeat;background-position:10px}.jq-icon-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=);background-color:#31708f;color:#d9edf7;border-color:#bce8f1}.jq-icon-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=);background-color:#8a6d3b;color:#fcf8e3;border-color:#faebcc}.jq-icon-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=);background-color:#a94442;color:#f2dede;border-color:#ebccd1}.jq-icon-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==);color:#dff0d8;background-color:#3c763d;border-color:#d6e9c6}
.jq-toast-single{
font-size: 24px;
line-height: normal;
}
</style>
<h1>Dinamo bulk edit</h1>
<div id="save_success"></div>
<div id="save_fail"></div>
<form id="bulk_edit_search" method="POST">
<p class="search-box">
<label class="screen-reader-text" for="bulk-edit-search-input">Pretraži proizvode</label>
<input id="bulk-edit-search-input" type="search" name="bulk-edit-search-input" value="">
<input class="button" type="submit" value="Pretraži proizvode">
</p>
</form>
<table class="wp-list-table widefat fixed striped pages">
<thead>
<tr>
<td>
Šifra
</td>
<td>
Naziv
</td>
<td>
Cijena
</td>
<td>
Akcijska cijena
</td>
<td>
Količina
</td>
<td>
Akcije
</td>
</tr>
</thead>
<tbody id="bulk_edit_products">
<?php bulk_get_products( $products_query ); ?>
</tbody>
</table>
<script>
(function($){
$("body").on('click', '[data-save-product]', function(e){
var pid = $(e.currentTarget).attr('data-save-product');
var price = $("[data-product-price='" + pid + "']").val();
var sale = $("[data-product-sale='" + pid + "']").val();
var sale_start = $("[data-product-sale-start='" + pid + "']").val();
var sale_end = $("[data-product-sale-end='" + pid + "']").val();
var qt = $("[data-product-qt='" + pid + "']").val();
$("[data-product-row='" + pid + "']").css('opacity', '0.5');
$.ajax({
type: 'POST',
dataType: 'json',
url: ajaxurl,
data: {
'action': 'change_price_qt',
'id' : pid,
'price' : price,
'sale' : sale,
'sale_start' : sale_start,
'sale_end' : sale_end,
'qt' : qt
}
}).done(function(){
$("[data-product-row='" + pid + "']").css('opacity', '1');
$.toast({
text: "Vaše promjene su uspješno pohranjene.",
position:"bottom-right"
})
});
});
$("form#bulk_edit_search").on( 'submit', function(e){
e.preventDefault();
var table = $("tbody#bulk_edit_products");
table.css( 'opacity', 0.5 );
$.ajax({
type: 'POST',
dataType: 'json',
url: ajaxurl,
data: {
'action': 'bulk_edit_search',
's': $('form#bulk_edit_search #bulk-edit-search-input').val()
},
success: function(data){
table.html(data.content);
table.css( 'opacity', 1 );
}
});
});
})(jQuery);
</script>
<?php
}
add_action( 'wp_ajax_change_price_qt', 'change_price_qt' );
function change_price_qt(){
$id = $_POST["id"];
$price = $_POST["price"];
$sale = $_POST["sale"];
$sale_start = $_POST["sale_start"];
$sale_end = $_POST["sale_end"];
$qt = $_POST["qt"];
update_post_meta($id, '_regular_price', (float)$price);
if( ! empty ($sale) ){
update_post_meta($id, '_sale_price', (float)$sale);
update_post_meta($id, '_price', (float)$sale);
} else {
update_post_meta($id, '_price', (float)$price);
}
if( ! empty ($sale_start) ){
update_post_meta($id, '_sale_price_dates_from', strtotime($sale_start) );
}
if( ! empty ($sale_end) ){
update_post_meta($id, '_sale_price_dates_to', strtotime($sale_end) );
}
wc_update_product_stock($id,(float)$qt);
if((float)$qt > 0){
wc_update_product_stock_status($id, 'instock');
}else{
wc_update_product_stock_status($id, 'outofstock');
}
if( $sale == (0 || false || null) ){
delete_post_meta( $id, '_sale_price' );
}
$product = wc_get_product( $id );
if( $product->is_type( 'simple' ) ){
$price = get_post_meta( '_regular_price', $id );
$sale = get_post_meta( '_sale_price', $id );
if( metadata_exists( 'post', $id, '_sale_price' ) ){
update_post_meta( $id, 'is_sale', 1 );
} else {
delete_post_meta( $id, 'is_sale');
}
algolia_add_product( $id );
} else {
$variation = wc_get_product( $id );
//
$parent = wc_get_product( $variation->get_parent_id() );
delete_transient("wc_var_prices_" . $variation->get_parent_id() );
$parent->get_variation_prices();
$variations = $parent->get_available_variations();
foreach( $variations as $v ){
$var_id = $v['variation_id'];
if( metadata_exists( 'post', $var_id, '_sale_price' ) ){
$result[] = $var_id;
}
}
if( ! empty( $result ) ){
update_post_meta( $parent->id, 'is_sale', 1 );
} else {
delete_post_meta( $parent->id, 'is_sale');
}
algolia_add_product( $parent->id );
}
}
function title_filter($where, &$wp_query){
global $wpdb;
if($search_term = $wp_query->get( 'title_filter' )){
$search_term = $wpdb->esc_like($search_term);
$search_term = ' \'%' . $search_term . '%\'';
$title_filter_relation = (strtoupper($wp_query->get( 'title_filter_relation'))=='OR' ? 'OR' : 'AND');
$where .= ' '.$title_filter_relation.' ' . $wpdb->posts . '.post_title LIKE '.$search_term;
}
return $where;
}
add_action( 'wp_ajax_bulk_edit_search', 'bulk_edit_search' );
function bulk_edit_search(){
$s = $_POST['s'];
add_filter( 'posts_where', 'title_filter', 10, 2 );
$query = new WP_Query( array(
'post_type' => 'product',
'posts_per_page' => -1,
'title_filter' => $s,
'title_filter_relation' => 'OR',
'orderby' => 'title',
'order' => 'ASC',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => '_sku',
'value' => $s,
'compare' => 'LIKE'
)
)
));
remove_filter( 'posts_where', 'title_filter', 10, 2 );
ob_start();
bulk_get_products($query);
$content = ob_get_clean();
wp_send_json(array(
'content' => $content
));
die();
}
?>