Commit 43edb2af authored by Franco nextime Lanza's avatar Franco nextime Lanza

Forket WooCommerce Product Add-ons

parents
<?php
/**
* Product_Addon_Admin class.
*/
class Product_Addon_Admin {
/**
* __construct function.
*
* @access public
* @return void
*/
public function __construct() {
add_action( 'woocommerce_admin_css', array( $this, 'styles' ) );
add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
add_filter( 'woocommerce_screen_ids', array( $this, 'add_screen_id' ) );
add_action( 'woocommerce_product_write_panel_tabs', array( $this, 'tab' ) );
add_action( 'woocommerce_product_write_panels', array( $this, 'panel' ) );
add_action( 'woocommerce_process_product_meta', array( $this, 'process_meta_box'), 1, 2 );
}
/**
* Add menus
*/
public function admin_menu() {
$page = add_submenu_page( 'edit.php?post_type=product', __( 'Global Add-ons', 'wc_product_addons' ), __( 'Global Add-ons', 'wc_product_addons' ), 'manage_woocommerce', 'global_addons', array( $this, 'global_addons_admin' ) );
add_action( 'admin_print_styles-'. $page, array( &$this, 'admin_enqueue' ) );
}
/**
* admin_enqueue function.
*
* @access public
* @return void
*/
public function admin_enqueue() {
wp_enqueue_script( 'chosen' );
}
/**
* styles function.
*
* @access public
* @return void
*/
public function styles() {
wp_enqueue_style( 'woocommerce_product_addons_css', plugins_url( basename( dirname( dirname( __FILE__ ) ) ) ) . '/assets/css/admin.css' );
}
/**
* Add screen id to WooCommerce
*
* @param array $screen_ids
*/
public function add_screen_id( $screen_ids ) {
$screen_ids[] = 'product_page_global_addons';
return $screen_ids;
}
/**
* Controls the global addons admin page
* @return void
*/
public function global_addons_admin() {
if ( ! empty( $_GET['add'] ) || ! empty( $_GET['edit'] ) ) {
if ( $_POST ) {
if ( $this->save_global_addons() ) {
echo '<div class="updated"><p>' . __( 'Add-on saved successfully', 'wc_product_addons' ) . '</p></div>';
}
$reference = woocommerce_clean( $_POST['addon-reference'] );
$priority = absint( $_POST['addon-priority'] );
$objects = ! empty( $_POST['addon-objects'] ) ? array_map( 'absint', $_POST['addon-objects'] ) : array();
$product_addons = array_filter( (array) $this->get_posted_product_addons() );
}
if ( ! empty( $_GET['edit'] ) ) {
$edit_id = absint( $_GET['edit'] );
$global_addon = get_post( $edit_id );
if ( ! $global_addon ) {
echo '<div class="error">' . __( 'Error: Global Add-on not found', 'wc_product_addons' ) . '</div>';
return;
}
$reference = $global_addon->post_title;
$priority = get_post_meta( $global_addon->ID, '_priority', true );
$objects = (array) wp_get_post_terms( $global_addon->ID, 'product_cat', array( 'fields' => 'ids' ) );
$product_addons = array_filter( (array) get_post_meta( $global_addon->ID, '_product_addons', true ) );
if ( get_post_meta( $global_addon->ID, '_all_products', true ) == 1 )
$objects[] = 0;
} else {
$global_addons_count = wp_count_posts( 'global_product_addon' );
$reference = __( 'Global Add-on Group' ) . ' #' . ( $global_addons_count->publish + 1 );
$priority = 10;
$objects = array( 0 );
$product_addons = array();
}
include( 'html-global-admin-add.php' );
} else {
if ( ! empty( $_GET['delete'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'delete_addon' ) ) {
wp_delete_post( absint( $_GET['delete'] ), true );
echo '<div class="updated"><p>' . __( 'Add-on deleted successfully', 'wc_product_addons' ) . '</p></div>';
}
include( 'html-global-admin.php' );
}
}
/**
* tab function.
*
* @access public
* @return void
*/
public function tab() {
?><li class="addons_tab product_addons"><a href="#product_addons_data"><?php _e( 'Add-ons', 'wc_product_addons' ); ?></a></li><?php
}
/**
* panel function.
*
* @access public
* @return void
*/
public function panel() {
global $post;
$product_addons = array_filter( (array) get_post_meta( $post->ID, '_product_addons', true ) );
include( 'html-addon-panel.php' );
}
/**
* Save global addons
*
* @return bool success or failure
*/
public function save_global_addons() {
$edit_id = ! empty( $_POST['edit_id'] ) ? absint( $_POST['edit_id'] ) : '';
$reference = woocommerce_clean( $_POST['addon-reference'] );
$priority = absint( $_POST['addon-priority'] );
$objects = ! empty( $_POST['addon-objects'] ) ? array_map( 'absint', $_POST['addon-objects'] ) : array();
$product_addons = $this->get_posted_product_addons();
if ( ! $reference ) {
$global_addons_count = wp_count_posts( 'global_product_addon' );
$reference = __( 'Global Add-on Group' ) . ' #' . ( $global_addons_count->publish + 1 );
}
if ( ! $priority && $priority !== 0 )
$priority = 10;
if ( $edit_id ) {
$edit_post = array();
$edit_post['ID'] = $edit_id;
$edit_post['post_title'] = $reference;
wp_update_post( $edit_post );
wp_set_post_terms( $edit_id, $objects, 'product_cat', false );
} else {
$edit_id = wp_insert_post( array(
'post_title' => $reference,
'post_status' => 'publish',
'post_type' => 'global_product_addon',
'tax_input' => array(
'product_cat' => $objects
)
) );
}
if ( in_array( 0, $objects ) )
update_post_meta( $edit_id, '_all_products', 1 );
else
update_post_meta( $edit_id, '_all_products', 0 );
update_post_meta( $edit_id, '_priority', $priority );
update_post_meta( $edit_id, '_product_addons', $product_addons );
return true;
}
/**
* process_meta_box function.
*
* @access public
* @param mixed $post_id
* @param mixed $post
* @return void
*/
public function process_meta_box( $post_id, $post ) {
// Save addons as serialised array
$product_addons = $this->get_posted_product_addons();
$product_addons_exclude_global = isset( $_POST['_product_addons_exclude_global'] ) ? 1 : 0;
update_post_meta( $post_id, '_product_addons', $product_addons );
update_post_meta( $post_id, '_product_addons_exclude_global', $product_addons_exclude_global );
}
/**
* Put posted addon data into an array
*
* @return [type] [description]
*/
private function get_posted_product_addons() {
$product_addons = array();
if ( isset( $_POST[ 'product_addon_name' ] ) ) {
$addon_name = $_POST['product_addon_name'];
$addon_description = $_POST['product_addon_description'];
$addon_type = $_POST['product_addon_type'];
$addon_position = $_POST['product_addon_position'];
$addon_required = isset( $_POST['product_addon_required'] ) ? $_POST['product_addon_required'] : array();
$addon_option_label = $_POST['product_addon_option_label'];
$addon_option_price = $_POST['product_addon_option_price'];
$addon_option_min = $_POST['product_addon_option_min'];
$addon_option_max = $_POST['product_addon_option_max'];
for ( $i = 0; $i < sizeof( $addon_name ); $i++ ) {
if ( ! isset( $addon_name[ $i ] ) || ( '' == $addon_name[ $i ] ) ) continue;
$addon_options = array();
$option_label = $addon_option_label[ $i ];
$option_price = $addon_option_price[ $i ];
$option_min = $addon_option_min[ $i ];
$option_max = $addon_option_max[ $i ];
for ( $ii = 0; $ii < sizeof( $option_label ); $ii++ ) {
$label = sanitize_text_field( stripslashes( $option_label[ $ii ] ) );
$price = sanitize_text_field( stripslashes( $option_price[ $ii ] ) );
$min = sanitize_text_field( stripslashes( $option_min[ $ii ] ) );
$max = sanitize_text_field( stripslashes( $option_max[ $ii ] ) );
$addon_options[] = array(
'label' => $label,
'price' => $price,
'min' => $min,
'max' => $max
);
}
if ( sizeof( $addon_options ) == 0 )
continue; // Needs options
// Add to array
$product_addons[] = array(
'name' => sanitize_text_field( stripslashes( $addon_name[ $i ] ) ),
'description' => wp_kses_post( stripslashes( $addon_description[ $i ] ) ),
'type' => sanitize_text_field( stripslashes( $addon_type[ $i ] ) ),
'position' => absint( $addon_position[ $i ] ),
'options' => $addon_options,
'required' => isset( $addon_required[ $i ] ) ? 1 : 0,
);
}
}
if ( ! empty( $_POST['import_product_addon'] ) ) {
$import_addons = maybe_unserialize( maybe_unserialize( stripslashes( trim( $_POST['import_product_addon'] ) ) ) );
if ( is_array( $import_addons ) && sizeof( $import_addons ) > 0 ) {
$valid = true;
foreach ( $import_addons as $addon ) {
if ( ! isset( $addon['name'] ) || ! $addon['name'] ) $valid = false;
if ( ! isset( $addon['description'] ) ) $valid = false;
if ( ! isset( $addon['type'] ) ) $valid = false;
if ( ! isset( $addon['position'] ) ) $valid = false;
if ( ! isset( $addon['options'] ) ) $valid = false;
if ( ! isset( $addon['required'] ) ) $valid = false;
}
if ( $valid ) {
$product_addons = array_merge( $product_addons, $import_addons );
}
}
}
uasort( $product_addons, array( $this, 'addons_cmp' ) );
return $product_addons;
}
/**
* Sort addons
*
* @param [type] $a [description]
* @param [type] $b [description]
* @return [type] [description]
*/
private function addons_cmp( $a, $b ) {
if ( $a['position'] == $b['position'] ) {
return 0;
}
return ( $a['position'] < $b['position'] ) ? -1 : 1;
}
}
\ No newline at end of file
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
?>
<tr>
<td><input type="text" name="product_addon_option_label[<?php echo $loop; ?>][]" value="<?php echo esc_attr($option['label']) ?>" placeholder="<?php _e('Label', 'wc_product_addons'); ?>" /></td>
<td class="price_column"><input type="number" name="product_addon_option_price[<?php echo $loop; ?>][]" value="<?php echo esc_attr($option['price']) ?>" placeholder="0.00" min="0" step="any" /></td>
<td class="minmax_column"><input type="number" name="product_addon_option_min[<?php echo $loop; ?>][]" value="<?php echo esc_attr($option['min']) ?>" placeholder="N/A" min="0" step="any" /></td>
<td class="minmax_column"><input type="number" name="product_addon_option_max[<?php echo $loop; ?>][]" value="<?php echo esc_attr($option['max']) ?>" placeholder="N/A" min="0" step="any" /></td>
<td class="actions"><button type="button" class="remove_addon_option button">x</button></td>
</tr>
\ No newline at end of file
<div id="product_addons_data" class="panel woocommerce_options_panel">
<div class="wc-metaboxes-wrapper">
<p class="toolbar">
<a href="#" class="close_all"><?php _e( 'Close all', 'woocommerce' ); ?></a><a href="#" class="expand_all"><?php _e( 'Expand all', 'woocommerce' ); ?></a>
</p>
<div class="woocommerce_product_addons wc-metaboxes">
<?php
$loop = 0;
foreach ( $product_addons as $addon ) {
include( 'html-addon.php' );
$loop++;
}
?>
</div>
<div class="toolbar">
<button type="button" class="button add_new_addon button-primary"><?php _e( 'New Addon Group', 'wc_product_addons' ); ?></button>
<button type="button" class="button import_addons"><?php _e( 'Import', 'wc_product_addons' ); ?></button>
<button type="button" class="button export_addons"><?php _e( 'Export', 'wc_product_addons' ); ?></button>
<textarea name="export_product_addon" class="export" cols="20" rows="5" readonly="readonly"><?php echo esc_textarea( serialize( $product_addons ) ); ?></textarea>
<textarea name="import_product_addon" class="import" cols="20" rows="5" placeholder="<?php _e('Paste exported form data here and then save to import fields. The imported fields will be appended.', 'wc_product_addons'); ?>"></textarea>
</div>
<?php if( isset($post->ID) ):?>
<div class="options_group">
<p class="form-field">
<label for="_product_addons_exclude_global"><?php _e( 'Global Addon Exclusion', 'wc_product_addons' ); ?></label>
<input id="_product_addons_exclude_global" name="_product_addons_exclude_global" class="checkbox" type="checkbox" value="1" <?php checked( get_post_meta( $post->ID, '_product_addons_exclude_global', TRUE ), 1 ); ?>/><span class="description"><?php _e( 'Check this to exclude this product from all Global Addons', 'wc_product_addons' ); ?></span>
</p>
</div>
<?php endif; ?>
</div>
</div>
<script type="text/javascript">
jQuery(function(){
jQuery( 'select.chosen_select' ).chosen();
jQuery('#product_addons_data')
.on( 'change', '.addon_name input', function() {
if ( jQuery(this).val() )
jQuery(this).closest('.woocommerce_product_addon').find('span.group_name').text( '"' + jQuery(this).val() + '"' );
else
jQuery(this).closest('.woocommerce_product_addon').find('span.group_name').text('');
})
.on( 'change', 'select.product_addon_type', function() {
var value = jQuery(this).val();
if ( value == 'custom' || value == 'custom_price' || value == 'custom_textarea' || value == 'input_multiplier' ) {
jQuery(this).closest('.woocommerce_product_addon').find('td.minmax_column, th.minmax_column').show();
} else {
jQuery(this).closest('.woocommerce_product_addon').find('td.minmax_column, th.minmax_column').hide();
}
if ( value == 'custom_price' ) {
jQuery(this).closest('.woocommerce_product_addon').find('td.price_column, th.price_column').hide();
} else {
jQuery(this).closest('.woocommerce_product_addon').find('td.price_column, th.price_column').show();
}
})
.on( 'click', 'button.add_addon_option', function() {
var loop = jQuery(this).closest('.woocommerce_product_addon').index('.woocommerce_product_addon');
var html = '<?php
ob_start();
$option['label'] = '';
$option['price'] = '';
$option['min'] = '';
$option['max'] = '';
$loop = "{loop}";
include( 'html-addon-option.php' );
$html = ob_get_clean();
echo str_replace( array( "\n", "\r" ), '', str_replace( "'", '"', $html ) );
?>';
html = html.replace( /{loop}/g, loop );
jQuery(this).closest('.woocommerce_product_addon .data').find('tbody').append( html );
jQuery('select.product_addon_type').change();
return false;
})
.on( 'click', '.add_new_addon', function() {
var loop = jQuery('.woocommerce_product_addons .woocommerce_product_addon').size();
var html = '<?php
ob_start();
$addon['name'] = '';
$addon['description'] = '';
$addon['required'] = '';
$addon['type'] = 'checkbox';
$addon['options'] = array();
$loop = "{loop}";
include( 'html-addon.php' );
$html = ob_get_clean();
echo str_replace( array( "\n", "\r" ), '', str_replace( "'", '"', $html ) );
?>';
html = html.replace( /{loop}/g, loop );
jQuery('.woocommerce_product_addons').append( html );
jQuery('select.product_addon_type').change();
return false;
})
.on( 'click', '.remove_addon', function() {
var answer = confirm('<?php _e('Are you sure you want remove this add-on?', 'wc_product_addons'); ?>');
if (answer) {
var addon = jQuery(this).closest('.woocommerce_product_addon');
jQuery(addon).find('input').val('');
jQuery(addon).hide();
}
return false;
})
.find('select.product_addon_type').change();
// Import / Export
jQuery('#product_addons_data').on('click', '.export_addons', function() {
jQuery('#product_addons_data textarea.import').hide();
jQuery('#product_addons_data textarea.export').slideToggle('500', function() {
jQuery(this).select();
});
return false;
});
jQuery('#product_addons_data').on('click', '.import_addons', function() {
jQuery('#product_addons_data textarea.export').hide();
jQuery('#product_addons_data textarea.import').slideToggle('500', function() {
jQuery(this).val('');
});
return false;
});
// Sortable
jQuery('.woocommerce_product_addons').sortable({
items:'.woocommerce_product_addon',
cursor:'move',
axis:'y',
handle:'h3',
scrollSensitivity:40,
helper:function(e,ui){
return ui;
},
start:function(event,ui){
ui.item.css('border-style','dashed');
},
stop:function(event,ui){
ui.item.removeAttr('style');
addon_row_indexes();
}
});
function addon_row_indexes() {
jQuery('.woocommerce_product_addons .woocommerce_product_addon').each(function(index, el){ jQuery('.product_addon_position', el).val( parseInt( jQuery(el).index('.woocommerce_product_addons .woocommerce_product_addon') ) ); });
};
// Sortable options
jQuery('.woocommerce_product_addon .data table tbody').sortable({
items:'tr',
cursor:'move',
axis:'y',
scrollSensitivity:40,
helper:function(e,ui){
ui.children().each(function(){
jQuery(this).width(jQuery(this).width());
});
return ui;
},
start:function(event,ui){
ui.item.css('background-color','#f6f6f6');
},
stop:function(event,ui){
ui.item.removeAttr('style');
}
});
// Remove option
jQuery('button.remove_addon_option').live('click', function(){
var answer = confirm('<?php _e('Are you sure you want delete this option?', 'wc_product_addons'); ?>');
if (answer) {
jQuery(this).closest('tr').remove();
}
return false;
});
});
</script>
\ No newline at end of file
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
?>
<div class="woocommerce_product_addon wc-metabox closed">
<h3>
<button type="button" class="remove_addon button"><?php _e( 'Remove', 'woocommerce' ); ?></button>
<div class="handlediv" title="<?php _e( 'Click to toggle', 'woocommerce' ); ?>"></div>
<strong><?php _e( 'Group', 'woocommerce' ); ?> <span class="group_name"><?php if ( $addon['name'] ) echo '"' . esc_attr( $addon['name'] ) . '"'; ?></span> &mdash; </strong>
<select name="product_addon_type[<?php echo $loop; ?>]" class="product_addon_type">
<option <?php selected('checkbox', $addon['type']); ?> value="checkbox"><?php _e('Checkboxes', 'wc_product_addons'); ?></option>
<option <?php selected('radiobutton', $addon['type']); ?> value="radiobutton"><?php _e('Radio buttons', 'wc_product_addons'); ?></option>
<option <?php selected('select', $addon['type']); ?> value="select"><?php _e('Select box', 'wc_product_addons'); ?></option>
<option <?php selected('custom', $addon['type']); ?> value="custom"><?php _e('Custom input (text)', 'wc_product_addons'); ?></option>
<option <?php selected('custom_textarea', $addon['type']); ?> value="custom_textarea"><?php _e('Custom input (textarea)', 'wc_product_addons'); ?></option>
<option <?php selected('file_upload', $addon['type']); ?> value="file_upload"><?php _e('File upload', 'wc_product_addons'); ?></option>
<option <?php selected('custom_price', $addon['type']); ?> value="custom_price"><?php _e('Custom price input', 'wc_product_addons'); ?></option>
<option <?php selected('input_multiplier', $addon['type']); ?> value="input_multiplier"><?php _e('Custom Input Multipler', 'wc_product_addons'); ?></option>
</select>
<input type="hidden" name="product_addon_position[<?php echo $loop; ?>]" class="product_addon_position" value="<?php echo $loop; ?>" />
</h3>
<table cellpadding="0" cellspacing="0" class="wc-metabox-content">
<tbody>
<tr>
<td class="addon_name" width="50%">
<label for="addon_name_<?php echo $loop; ?>"><?php _e( 'Group Name', 'woocommerce' ); ?></label>
<input type="text" id="addon_name_<?php echo $loop; ?>" name="product_addon_name[<?php echo $loop; ?>]" value="<?php echo esc_attr( $addon['name'] ) ?>" />
</td>
<td class="addon_required" width="50%">
<label for="addon_required_<?php echo $loop; ?>"><?php _e( 'Required fields?', 'wc_product_addons' ); ?></label>
<input type="checkbox" id="addon_required_<?php echo $loop; ?>" name="product_addon_required[<?php echo $loop; ?>]" <?php checked( $addon['required'], 1 ) ?> />
</td>
</tr>
<tr>
<td class="addon_description" colspan="2">
<label for="addon_description_<?php echo $loop; ?>"><?php _e( 'Group Description', 'woocommerce' ); ?></label>
<textarea cols="20" id="addon_description_<?php echo $loop; ?>" rows="3" name="product_addon_description[<?php echo $loop; ?>]"><?php echo esc_textarea( $addon['description'] ) ?></textarea>
</td>
</tr>
<tr>
<td class="data" colspan="3">
<table cellspacing="0" cellpadding="0">
<thead>
<tr>
<th><?php _e('Option Label', 'wc_product_addons'); ?></th>
<th class="price_column"><?php _e('Option Price', 'wc_product_addons'); ?></th>
<th class="minmax_column"><?php _e('Min', 'wc_product_addons'); ?></th>
<th class="minmax_column"><?php _e('Max', 'wc_product_addons'); ?></th>
<th width="1%"></th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="5"><button type="button" class="add_addon_option button"><?php _e('New&nbsp;Option', 'wc_product_addons'); ?></button></td>
</tr>
</tfoot>
<tbody>
<?php
foreach ( $addon['options'] as $option )
include( 'html-addon-option.php' );
?>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<div class="wrap woocommerce">
<div class="icon32 icon32-posts-product" id="icon-woocommerce"><br/></div>
<h2><?php _e( 'Add/Edit Global Add-on', 'wc_product_addons' ) ?></h2><br/>
<form method="POST" action="">
<table class="form-table global-addons-form">
<tr>
<th>
<label for="addon-reference"><?php _e( 'Global Add-on Reference', 'wc_product_addons' ); ?></label>
</th>
<td>
<input type="text" name="addon-reference" id="addon-reference" style="width:50%;" value="<?php echo esc_attr( $reference ); ?>" />
<p class="description"><?php _e( 'Give this global add-on a reference/name to make it recognisable.', 'wc_product_addons' ); ?></p>
</td>
</tr>
<tr>
<th>
<label for="addon-priority"><?php _e( 'Priority', 'wc_product_addons' ); ?></label>
</th>
<td>
<input type="text" name="addon-priority" id="addon-priority" style="width:50%;" value="<?php echo esc_attr( $priority ); ?>" />
<p class="description"><?php _e( 'Give this global addon a priority - this will deternmine the order in which multiple groups of addons get displayed on the frontend. Per-product add-ons will always have priority 10.', 'wc_product_addons' ); ?></p>
</td>
</tr>
<tr>
<th>
<label for="addon-objects"><?php _e( 'Applied to...', 'wc_product_addons' ); ?></label>
</th>
<td>
<select id="addon-objects" name="addon-objects[]" multiple="multiple" style="width:50%;" data-placeholder="<?php _e('Choose some options&hellip;', 'wc_product_addons'); ?>" class="chosen_select">
<option value="0" <?php selected( in_array( '0', $objects ), true ); ?>><?php _e( 'All Products', 'wc_product_addons' ); ?></option>
<optgroup label="<?php _e( 'Product category notifications', 'wc_product_addons' ); ?>">
<?php
$terms = get_terms( 'product_cat', array( 'hide_empty' => 0 ) );
foreach( $terms as $term )
echo '<option value="' . $term->term_id . '" ' . selected( in_array( $term->term_id, $objects ), true, false ) . '>' . __( 'Category:', 'wc_product_addons' ) . ' ' . $term->name . '</option>';
?>
</optgroup>
</select>
<p class="description"><?php _e( 'Choose categories which should show these addons (or apply to all products).', 'wc_product_addons' ); ?></p>
</td>
</tr>
<tr>
<th>
<label for="addon-objects"><?php _e( 'Add-ons', 'wc_product_addons' ); ?></label>
</th>
<td id="poststuff" class="postbox">
<?php include( 'html-addon-panel.php' ); ?>
</td>
</tr>
</table>
<p class="submit">
<input type="hidden" name="edit_id" value="<?php if ( ! empty( $edit_id ) ) echo $edit_id; ?>" />
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Global Add-on', 'wc_product_addons' ); ?>">
</p>
</form>
</div>
<script type="text/javascript">
// Open/close
jQuery('.wc-metaboxes-wrapper').on('click', '.wc-metabox h3', function(event){
// If the user clicks on some form input inside the h3, like a select list (for variations), the box should not be toggled
if (jQuery(event.target).filter(':input, option').length) return;
jQuery(this).next('.wc-metabox-content').toggle();
})
.on('click', '.expand_all', function(event){
jQuery(this).closest('.wc-metaboxes-wrapper').find('.wc-metabox > table').show();
return false;
})
.on('click', '.close_all', function(event){
jQuery(this).closest('.wc-metaboxes-wrapper').find('.wc-metabox > table').hide();
return false;
});
jQuery('.wc-metabox.closed').each(function(){
jQuery(this).find('.wc-metabox-content').hide();
});
</script>
\ No newline at end of file
<div class="wrap woocommerce">
<div class="icon32 icon32-posts-product" id="icon-woocommerce"><br/></div>
<h2><?php _e( 'Global Add-ons', 'wc_product_addons' ) ?> <a href="<?php echo add_query_arg( 'add', true, admin_url( 'edit.php?post_type=product&page=global_addons' ) ); ?>" class="add-new-h2"><?php _e( 'Add Global Add-on', 'wc_product_addons' ); ?></a></h2><br/>
<table id="global-addons-table" class="wp-list-table widefat" cellspacing="0">
<thead>
<tr>
<th scope="col"><?php _e( 'Reference', 'wc_product_addons' ); ?></th>
<th><?php _e( 'Number of Fields', 'wc_product_addons' ); ?></th>
<th><?php _e( 'Priority', 'wc_product_addons' ); ?></th>
<th><?php _e( 'Applies to...', 'wc_product_addons' ); ?></th>
<th><?php _e( 'Actions', 'wc_product_addons' ); ?></th>
</tr>
</thead>
<tbody id="the-list">
<?php
$args = array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
'post_type' => 'global_product_addon',
'post_status' => 'any',
'suppress_filters' => true
);
$global_addons = get_posts( $args );
if ( $global_addons ) {
foreach ( $global_addons as $global_addon ) {
$reference = $global_addon->post_title;
$priority = get_post_meta( $global_addon->ID, '_priority', true );
$objects = (array) wp_get_post_terms( $global_addon->ID, 'product_cat', array( 'fields' => 'ids' ) );
$product_addons = array_filter( (array) get_post_meta( $global_addon->ID, '_product_addons', true ) );
if ( get_post_meta( $global_addon->ID, '_all_products', true ) == 1 )
$objects[] = 0;
?>
<tr>
<td><?php echo $reference; ?></td>
<td><?php echo sizeof( $product_addons ); ?></td>
<td><?php echo $priority; ?></td>
<td><?php
if ( in_array( 0, $objects ) )
_e( 'All Products', 'wc_product_addons' );
else {
$term_names = array();
foreach ( $objects as $object_id ) {
$term = get_term_by( 'id', $object_id, 'product_cat' );
$term_names[] = $term->name;
}
echo implode( ', ', $term_names );
}
?></td>
<td>
<a href="<?php echo add_query_arg( 'edit', $global_addon->ID, admin_url( 'edit.php?post_type=product&page=global_addons' ) ); ?>" class="button"><?php _e( 'Edit', 'wc_product_addons' ); ?></a> <a href="<?php echo wp_nonce_url( add_query_arg( 'delete', $global_addon->ID, admin_url( 'edit.php?post_type=product&page=global_addons' ) ), 'delete_addon' ); ?>" class="button"><?php _e( 'Delete', 'wc_product_addons' ); ?></a>
</td>
</tr>
<?php
}
} else {
?>
<tr>
<td colspan="5"><?php _e( 'No global add-ons exists yet.', 'wc_product_addons' ); ?> <a href="<?php echo add_query_arg( 'add', true, admin_url( 'edit.php?post_type=product&page=global_addons' ) ); ?>"><?php _e( 'Add one?', 'wc_product_addons' ); ?></a></td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
\ No newline at end of file
#global-addons-table td{padding:7px 9px;vertical-align:middle}#global-addons-table th{padding:7px 9px}.global-addons-form td.postbox,.woocommerce_product_addons td.postbox{padding:0!important}.global-addons-form td label,.woocommerce_product_addons td label{margin:0}.global-addons-form .addon_required label,.woocommerce_product_addons .addon_required label{display:block;float:none}.global-addons-form .addon_required input,.woocommerce_product_addons .addon_required input{width:16px!important;min-width:0!important}#woocommerce-product-data ul.product_data_tabs li.addons_tab a:before{content:"\e007"}#product_addons_data .add_new_addon{float:right}#product_addons_data textarea.import,#product_addons_data textarea.export{width:100%;display:none;margin:10px 0 0}#product_addons_data .woocommerce_product_addon .product_addon_type{float:none}#product_addons_data .woocommerce_product_addon .data table{padding:0;border:1px solid #ececec}#product_addons_data .woocommerce_product_addon .data table thead th{background:#ececec;padding:5px}#product_addons_data .woocommerce_product_addon .data table tfoot td{border-top:1px solid #ececec}#product_addons_data .woocommerce_product_addon .data input{min-width:50px}
\ No newline at end of file
#global-addons-table {
td {
padding: 7px 9px;
vertical-align: middle;
}
th {
padding: 7px 9px;
}
}
.global-addons-form, .woocommerce_product_addons {
td.postbox {
padding: 0 !important;
}
td {
label {
margin: 0;
}
}
.addon_required {
label {
display: block;
float: none;
}
input {
width: 16px !important;
min-width: 0 !important;
}
}
}
#woocommerce-product-data ul.product_data_tabs {
li.addons_tab {
a {
&:before {
content: "\e007";
}
}
}
}
#product_addons_data {
.add_new_addon {
float: right;
}
textarea.import, textarea.export {
width: 100%;
display: none;
margin: 10px 0 0;
}
.woocommerce_product_addon {
.product_addon_type {
float: none;
}
.data {
table {
padding: 0;
border: 1px solid #ececec;
thead {
th {
background: #ececec;
padding: 5px;
}
}
tfoot {
td {
border-top: 1px solid #ececec;
}
}
}
input {
min-width: 50px;
}
}
}
}
\ No newline at end of file
div.product-addon {
margin: 1em 0;
}
h3.addon-name {
margin-top: 0;
}
div.addon-description p {
margin-bottom: .5em;
font-style: italic
}
dl.product-addon-totals {
margin-bottom: 1em;
overflow: hidden;
}
dl.product-addon-totals dt {
width: 50%;
float: left;
clear: left;
}
dl.product-addon-totals dd {
float: left;
}
.addon-alert{
display: none;
color: red;
}
\ No newline at end of file
This diff is collapsed.
/*!
* accounting.js v0.3.2
* Copyright 2011, Joss Crowcroft
*
* Freely distributable under the MIT license.
* Portions of accounting.js are inspired or borrowed from underscore.js
*
* Full details and documentation:
* http://josscrowcroft.github.com/accounting.js/
*/(function(e,t){function o(e){return!!(e===""||e&&e.charCodeAt&&e.substr)}function u(e){return i?i(e):s.call(e)==="[object Array]"}function a(e){return e&&s.call(e)==="[object Object]"}function f(e,t){var n;e=e||{};t=t||{};for(n in t)t.hasOwnProperty(n)&&e[n]==null&&(e[n]=t[n]);return e}function l(e,t,n){var i=[],s,o;if(!e)return i;if(r&&e.map===r)return e.map(t,n);for(s=0,o=e.length;s<o;s++)i[s]=t.call(n,e[s],s,e);return i}function c(e,t){e=Math.round(Math.abs(e));return isNaN(e)?t:e}function h(e){var t=n.settings.currency.format;typeof e=="function"&&(e=e());return o(e)&&e.match("%v")?{pos:e,neg:e.replace("-","").replace("%v","-%v"),zero:e}:!e||!e.pos||!e.pos.match("%v")?o(t)?n.settings.currency.format={pos:t,neg:t.replace("%v","-%v"),zero:t}:t:e}var n={};n.version="0.3.2";n.settings={currency:{symbol:"$",format:"%s%v",decimal:".",thousand:",",precision:2,grouping:3},number:{precision:0,grouping:3,thousand:",",decimal:"."}};var r=Array.prototype.map,i=Array.isArray,s=Object.prototype.toString,p=n.unformat=n.parse=function(e,t){if(u(e))return l(e,function(e){return p(e,t)});e=e||0;if(typeof e=="number")return e;t=t||n.settings.number.decimal;var r=new RegExp("[^0-9-"+t+"]",["g"]),i=parseFloat((""+e).replace(/\((.*)\)/,"-$1").replace(r,"").replace(t,"."));return isNaN(i)?0:i},d=n.toFixed=function(e,t){t=c(t,n.settings.number.precision);var r=Math.pow(10,t);return(Math.round(n.unformat(e)*r)/r).toFixed(t)},v=n.formatNumber=function(e,t,r,i){if(u(e))return l(e,function(e){return v(e,t,r,i)});e=p(e);var s=f(a(t)?t:{precision:t,thousand:r,decimal:i},n.settings.number),o=c(s.precision),h=e<0?"-":"",m=parseInt(d(Math.abs(e||0),o),10)+"",g=m.length>3?m.length%3:0;return h+(g?m.substr(0,g)+s.thousand:"")+m.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+s.thousand)+(o?s.decimal+d(Math.abs(e),o).split(".")[1]:"")},m=n.formatMoney=function(e,t,r,i,s,o){if(u(e))return l(e,function(e){return m(e,t,r,i,s,o)});e=p(e);var d=f(a(t)?t:{symbol:t,precision:r,thousand:i,decimal:s,format:o},n.settings.currency),g=h(d.format),y=e>0?g.pos:e<0?g.neg:g.zero;return y.replace("%s",d.symbol).replace("%v",v(Math.abs(e),c(d.precision),d.thousand,d.decimal))};n.formatColumn=function(e,t,r,i,s,d){if(!e)return[];var m=f(a(t)?t:{symbol:t,precision:r,thousand:i,decimal:s,format:d},n.settings.currency),g=h(m.format),y=g.pos.indexOf("%s")<g.pos.indexOf("%v")?!0:!1,b=0,w=l(e,function(e,t){if(u(e))return n.formatColumn(e,m);e=p(e);var r=e>0?g.pos:e<0?g.neg:g.zero,i=r.replace("%s",m.symbol).replace("%v",v(Math.abs(e),c(m.precision),m.thousand,m.decimal));i.length>b&&(b=i.length);return i});return l(w,function(e,t){return o(e)&&e.length<b?y?e.replace(m.symbol,m.symbol+(new Array(b-e.length+1)).join(" ")):(new Array(b-e.length+1)).join(" ")+e:e})};if(typeof exports!="undefined"){typeof module!="undefined"&&module.exports&&(exports=module.exports=n);exports.accounting=n}else if(typeof define=="function"&&define.amd)define([],function(){return n});else{n.noConflict=function(r){return function(){e.accounting=r;n.noConflict=t;return n}}(e.accounting);e.accounting=n}})(this);
\ No newline at end of file
jQuery(document).ready(function($) {
function init_addon_totals() {
$('.cart').on( 'keyup change', '.product-addon input, .product-addon textarea', function() {
if ( $(this).attr('maxlength') > 0 ) {
var value = $(this).val();
var remaining = $(this).attr('maxlength') - value.length;
$(this).next('.chars_remaining').find('span').text( remaining );
}
} );
$('.cart').find('.addon-custom, .addon-custom-textarea').each(function(){
if ( $(this).attr('maxlength') > 0 ) {
$(this).after('<small class="chars_remaining"><span>' + $(this).attr('maxlength') + '</span> ' + woocommerce_addons_params.i18n_remaining + '</small>' );
}
} );
$('.cart').on( 'change', '.product-addon input, .product-addon textarea, .product-addon select, input.qty', function() {
var $cart = $(this).closest('.cart');
$cart.trigger('woocommerce-product-addons-update');
} );
$('.variations_form').on('found_variation', function( event, variation ) {
var $variation_form = $(this);
var $totals = $variation_form.find('#product-addons-total');
if ( $( variation.price_html ).find('.amount:last').size() ) {
product_price = $( variation.price_html ).find('.amount:last').text();
product_price = product_price.replace( woocommerce_addons_params.currency_format_thousand_sep, '' );
product_price = product_price.replace( woocommerce_addons_params.currency_format_decimal_sep, '.' );
product_price = product_price.replace(/[^0-9\.]/g, '');
product_price = parseFloat( product_price );
$totals.data( 'price', product_price );
}
$variation_form.trigger('woocommerce-product-addons-update');
});
$('.cart').bind( 'woocommerce-product-addons-update', function() {
var total = 0;
var $cart = $(this);
var $totals = $cart.find('#product-addons-total');
var product_price = $totals.data( 'price' );
var product_type = $totals.data( 'type' );
// Move totals
if ( product_type == 'variable' ) {
$cart.find('.single_variation').after( $totals );
}
$cart.find('.addon').each(function() {
var addon_cost = 0;
if ( $(this).is('.addon-custom-price') ) {
addon_cost = $(this).val();
} else if ( $(this).is('.addon-input_multiplier') ) {
if( isNaN( $(this).val() ) || $(this).val() == "" ) { // Number inputs return blank when invalid
$(this).val('');
$(this).closest('p').find('.addon-alert').show();
} else {
if( $(this).val() != "" ){
$(this).val( Math.ceil( $(this).val() ) );
}
$(this).closest('p').find('.addon-alert').hide();
}
addon_cost = $(this).data('price') * $(this).val();
} else if ( $(this).is('.addon-checkbox, .addon-radio') ) {
if ( $(this).is(':checked') )
addon_cost = $(this).data('price');
} else if ( $(this).is('.addon-select') ) {
if ( $(this).val() )
addon_cost = $(this).find('option:selected').data('price');
} else {
if ( $(this).val() )
addon_cost = $(this).data('price');
}
if ( ! addon_cost )
addon_cost = 0;
total = parseFloat( total ) + parseFloat( addon_cost );
} );
var qty = parseFloat( $cart.find('input.qty').val() );
if ( total > 0 && qty > 0 ) {
total = parseFloat( total * qty );
var formatted_addon_total = accounting.formatMoney( total, {
symbol : woocommerce_addons_params.currency_format_symbol,
decimal : woocommerce_addons_params.currency_format_decimal_sep,
thousand : woocommerce_addons_params.currency_format_thousand_sep,
precision : woocommerce_addons_params.currency_format_num_decimals,
format : woocommerce_addons_params.currency_format
} );
if ( product_price ) {
product_total_price = parseFloat( product_price * qty );
var formatted_grand_total = accounting.formatMoney( product_total_price + total, {
symbol : woocommerce_addons_params.currency_format_symbol,
decimal : woocommerce_addons_params.currency_format_decimal_sep,
thousand : woocommerce_addons_params.currency_format_thousand_sep,
precision : woocommerce_addons_params.currency_format_num_decimals,
format : woocommerce_addons_params.currency_format
} );
}
html = '<dl class="product-addon-totals"><dt>' + woocommerce_addons_params.i18n_addon_total + '</dt><dd><strong><span class="amount">' + formatted_addon_total + '</span></strong></dd>';
if ( formatted_grand_total ) {
html = html + '<dt>' + woocommerce_addons_params.i18n_grand_total + '</dt><dd><strong><span class="amount">' + formatted_grand_total + '</span></strong></dd>';
}
html = html + '</dl>';
$totals.html( html );
} else {
$totals.empty();
}
$('body').trigger('updated_addons');
} );
$('.cart').find('.addon-custom, .addon-custom-textarea, .product-addon input, .product-addon textarea, .product-addon select, input.qty').change();
}
init_addon_totals();
$( '.variations_form .product-addon' ).closest( '.cart' ).find( '.variations select' ).change();
// Quick view
$('body').on('quick-view-displayed', function() {
init_addon_totals();
});
});
\ No newline at end of file
jQuery(document).ready(function(e){function t(){e("form.cart").on("keyup change",".product-addon input, .product-addon textarea",function(){if(e(this).attr("maxlength")>0){var t=e(this).val(),n=e(this).attr("maxlength")-t.length;e(this).next(".chars_remaining").find("span").text(n)}});e("form.cart").find(".addon-custom, .addon-custom-textarea").each(function(){e(this).attr("maxlength")>0&&e(this).after('<small class="chars_remaining"><span>'+e(this).attr("maxlength")+"</span> "+woocommerce_addons_params.i18n_remaining+"</small>")});e("form.cart").on("change",".product-addon input, .product-addon textarea, .product-addon select, input.qty",function(){var t=e(this).closest("form.cart");t.trigger("woocommerce-product-addons-update")});e("form.variations_form").on("found_variation",function(t,n){var r=e(this),i=r.find("#product-addons-total");if(e(n.price_html).find(".amount:last").size()){product_price=e(n.price_html).find(".amount:last").text();product_price=product_price.replace(woocommerce_addons_params.currency_format_thousand_sep,"");product_price=product_price.replace(woocommerce_addons_params.currency_format_decimal_sep,".");product_price=product_price.replace(/[^0-9\.]/g,"");product_price=parseFloat(product_price);i.data("price",product_price)}r.trigger("woocommerce-product-addons-update")});e("form.cart").bind("woocommerce-product-addons-update",function(){var t=0,n=e(this),r=n.find("#product-addons-total"),i=r.data("price"),s=r.data("type");s=="variable"&&n.find(".single_variation").after(r);n.find(".addon").each(function(){var n=0;if(e(this).is(".addon-custom-price"))n=e(this).val();else if(e(this).is(".addon-input_multiplier")){if(isNaN(e(this).val())||e(this).val()==""){e(this).val("");e(this).closest("p").find(".addon-alert").show()}else{e(this).val()!=""&&e(this).val(Math.ceil(e(this).val()));e(this).closest("p").find(".addon-alert").hide()}n=e(this).data("price")*e(this).val()}else e(this).is(".addon-checkbox, .addon-radio")?e(this).is(":checked")&&(n=e(this).data("price")):e(this).is(".addon-select")?e(this).val()&&(n=e(this).find("option:selected").data("price")):e(this).val()&&(n=e(this).data("price"));n||(n=0);t=parseFloat(t)+parseFloat(n)});var o=parseFloat(n.find("input.qty").val());if(t>0&&o>0){t=parseFloat(t*o);var u=accounting.formatMoney(t,{symbol:woocommerce_addons_params.currency_format_symbol,decimal:woocommerce_addons_params.currency_format_decimal_sep,thousand:woocommerce_addons_params.currency_format_thousand_sep,precision:woocommerce_addons_params.currency_format_num_decimals,format:woocommerce_addons_params.currency_format});if(i){product_total_price=parseFloat(i*o);var a=accounting.formatMoney(product_total_price+t,{symbol:woocommerce_addons_params.currency_format_symbol,decimal:woocommerce_addons_params.currency_format_decimal_sep,thousand:woocommerce_addons_params.currency_format_thousand_sep,precision:woocommerce_addons_params.currency_format_num_decimals,format:woocommerce_addons_params.currency_format})}html='<dl class="product-addon-totals"><dt>'+woocommerce_addons_params.i18n_addon_total+'</dt><dd><strong><span class="amount">'+u+"</span></strong></dd>";a&&(html=html+"<dt>"+woocommerce_addons_params.i18n_grand_total+'</dt><dd><strong><span class="amount">'+a+"</span></strong></dd>");html+="</dl>";r.html(html)}else r.empty();e("body").trigger("updated_addons")});e("form.cart").find(".addon-custom, .addon-custom-textarea, .product-addon input, .product-addon textarea, .product-addon select, input.qty").change()}t();e("form.variations_form .product-addon").closest("form.cart").find(".variations select").change();e("body").on("quick-view-displayed",function(){t()})});
\ No newline at end of file
*** Product Addons Changelog ***
2014.03.21 - version 2.5.6
* Fix upload dir when "subdir" is not set.
2014.02.23 - version 2.5.5
* Fix cart button text for required addons in 2.1
2014.02.20 - version 2.5.4
* Styling fixes
2014.01.16 - version 2.5.3
* 2.1 compat
2013.12.06 - verison 2.5.2
* Check for subscription product type for add to cart urls
2013.12.06 - version 2.5.1
* Increased add_to_cart_text hook priority so that it applies to subscriptions too
2013.12.02 - version 2.5.0
* Removed legacy support
* Order again - restore addons
2013.10.10 - version 2.4.5
* Allow zero value for custom text inputs
2013.10.10 - version 2.4.4
* Only set addons to array when not set already
2013.10.10 - version 2.4.3
* Added min attribute when min is 0
2013.10.10 - version 2.4.2
* Prevent negative multiplier
2013.10.10 - version 2.4.1
* get_product_addons filter
2013.09.16 - version 2.4.0
* New custom input multipler field type which multiples an input value by the price. Thanks Andrew Beeken.
2013.09.08 - version 2.3.0
* Exclude products from Global Addons option
2013.08.22 - version 2.2.0
* Various tweaks to support composite products
2013.07.31 - version 2.1.3
* Corrected product type checking
* Unique class per addon
2013.07.23 - version 2.1.2
* Better compatibility with quick view
2013.07.18 - version 2.1.0
* Allow HTML in the addon descriptions
* Improved sanitization of posted options
2013.06.28 - version 2.0.9
* Global addons - include_children false so sibling category addons are not found.
2013.06.27 - version 2.0.8
* Rename addon totals string
2013.06.07 - version 2.0.7
* Change event on page load to show totals if needed
* Currency converter compatibility
2013.06.07 - version 2.0.6
* Labels are optional
* Select first radio element by default
2013.06.07 - version 2.0.5
* Variable product support when variations all cost the same
2013.06.07 - version 2.0.4
* Variable product support
2013.06.03 - version 2.0.3
* Fix global import
2013.05.31 - version 2.0.2
* get_woocommerce_price_format fallback
* Stripslashes fix
2013.05.29 - version 2.0.1
* Fix escaping of user defined data
2013.02.01 - version 2.0.0
* Complete rewrite for WooCommerce 2.0 with new interface.
* Global forms which can be applied to any product.
* Custom price inputs.
* More hooks for extending the plugin.
* Template based overrides for fields.
* Dynamic total cost display
* Removed upload size filter for the benefit of WP MU
* When required, select box default is "Select an option" rather than "None"
* Add to cart button on archives links to product page for products with required add ons
* Removed colon for text fields when label is empty
* required-product-addon class on wrapper div for required fields
* Add option to provide id for product_addons function
2013.02.09 - version 1.2.0
* WC 2.0 Compat
2012.12.04 - version 1.1.1
* New updater
2012.01.26 - version 1.1
* Required fields
* Textarea field type
* File upload field type
* Import/export forms between products
* Validation hook - woocommerce_validate_posted_addon_data
2012.01.26 - version 1.0.2
* Small plugin header update
* Strip tags from prices/meta
2011.12.1 - version 1.0.1
* Woo Updater
* Hook change
2011.11.17 - version 1.0
* First Release
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<?php
/*
Plugin Name: WooCommerce Better Product Add-ons
Plugin URI: https://github.com/nextime/woocommerce-better-product-addons
Description: WooCommerce Better Product Add-ons is a fork of WooCommerce Product Add-ons 2.5.6. It lets you add extra options to products which the user can select. Add-ons can be checkboxes, a select box, or custom input. Each option can optionally be given a price which is added to the cost of the product.
Version: 2.5.7
Original Author: WooThemes
Fork Author: nextime
Original Author URI: http://woothemes.com
Fork Author URI: https://github.com/nextime/
Requires at least: 3.1
Tested up to: 3.2
Copyright for original WooCommerce Product Add-ons: © 2009-2011 WooThemes.
Copyright: © 2014 nextime.
License: GNU General Public License v3.0
License URI: http://www.gnu.org/licenses/gpl-3.0.html
*/
/**
* Required functions
*/
if ( ! function_exists( 'woothemes_queue_update' ) )
require_once( 'woo-includes/woo-functions.php' );
/**
* Plugin updates
*/
woothemes_queue_update( plugin_basename( __FILE__ ), '147d0077e591e16db9d0d67daeb8c484', '18618' );
if ( is_woocommerce_active() ) {
/**
* Localisation
*/
load_plugin_textdomain( 'wc_product_addons', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
/**
* Init
*/
if ( ! class_exists( 'Product_Addon_Display' ) ) {
if ( is_admin() ) {
include_once( 'admin/class-product-addon-admin.php' );
$GLOBALS['Product_Addon_Admin'] = new Product_Addon_Admin();
}
include_once( 'classes/class-product-addon-display.php' );
$GLOBALS['Product_Addon_Display'] = new Product_Addon_Display();
include_once( 'classes/class-product-addon-cart.php' );
$GLOBALS['Product_Addon_Cart'] = new Product_Addon_Cart();
}
/**
* Gets addons assigned to a product by ID
*
* @param int $post_id ID of the product to get addons for
* @return array array of addons
*/
function get_product_addons( $post_id, $prefix = false ) {
if ( ! $post_id )
return array();
$addons = array();
$raw_addons = array();
$product_terms = wp_get_post_terms( $post_id, 'product_cat', array( 'fields' => 'ids' ) );
$exclude = get_post_meta( $post_id, '_product_addons_exclude_global', TRUE );
// Product level addons
$raw_addons[10][0] = array_filter( (array) get_post_meta( $post_id, '_product_addons', true ) );
if ( !isset($exclude) || $exclude != '1' ) :
// Global level addons (all products)
$args = array(
'posts_per_page' => -1,
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_key' => '_priority',
'post_type' => 'global_product_addon',
'post_status' => 'publish',
'suppress_filters' => true,
'meta_query' => array(
array(
'key' => '_all_products',
'value' => '1',
)
)
);
$global_addons = get_posts( $args );
if ( $global_addons ) :
foreach ( $global_addons as $global_addon ) {
$priority = get_post_meta( $global_addon->ID, '_priority', true );
$raw_addons[ $priority ][ $global_addon->ID ] = array_filter( (array) get_post_meta( $global_addon->ID, '_product_addons', true ) );
}
endif;
// Global level addons (categories)
if ( $product_terms ) :
$args = array(
'posts_per_page' => -1,
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_key' => '_priority',
'post_type' => 'global_product_addon',
'post_status' => 'publish',
'suppress_filters' => true,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $product_terms,
'include_children' => false
)
)
);
$global_addons = get_posts( $args );
if ( $global_addons ) :
foreach ( $global_addons as $global_addon ) {
$priority = get_post_meta( $global_addon->ID, '_priority', true );
$raw_addons[ $priority ][ $global_addon->ID ] = array_filter( (array) get_post_meta( $global_addon->ID, '_product_addons', true ) );
}
endif;
endif;
endif; // exclude from global addons
ksort( $raw_addons );
foreach ( $raw_addons as $addon_group ) {
if ( $addon_group ) {
foreach ( $addon_group as $addon )
$addons = array_merge( $addons, $addon );
}
}
// Generate field names with unqiue prefixes
if ( ! $prefix )
$prefix = apply_filters( 'product_addons_field_prefix', "{$post_id}-", $post_id );
foreach ( $addons as $addon_key => $addon ) {
$addons[ $addon_key ]['field-name'] = $prefix . $addon['name'];
}
return apply_filters( 'wc_get_product_addons', $addons );
}
/**
* Register post types for global addons
*/
function product_addons_post_types() {
register_post_type( "global_product_addon",
array(
'public' => false,
'show_ui' => false,
'capability_type' => 'product',
'map_meta_cap' => true,
'publicly_queryable' => false,
'exclude_from_search' => true,
'hierarchical' => false,
'rewrite' => false,
'query_var' => false,
'supports' => array( 'title' ),
'show_in_nav_menus' => false
)
);
register_taxonomy_for_object_type( 'product_cat', 'global_product_addon' );
}
add_action( 'init', 'product_addons_post_types', 20 );
}
<?php do_action( 'wc_product_addon_end', $addon ); ?>
<div class="clear"></div>
</div>
\ No newline at end of file
<div class="<?php if ( 1 == $required ) echo 'required-product-addon'; ?> product-addon product-addon-<?php echo sanitize_title( $name ); ?>">
<?php do_action( 'wc_product_addon_start', $addon ); ?>
<?php if ( $name ) : ?>
<h3 class="addon-name"><?php echo wptexturize( $name ); ?> <?php if ( 1 == $required ) echo '<abbr class="required" title="required">*</abbr>'; ?></h3>
<?php endif; ?>
<?php if ( $description ) : ?>
<?php echo '<div class="addon-description">' . wpautop( wptexturize( $description ) ) . '</div>'; ?>
<?php endif; ?>
<?php do_action( 'wc_product_addon_options', $addon ); ?>
<?php foreach ( $addon['options'] as $i => $option ) :
$price = $option['price'] > 0 ? '(' . woocommerce_price( $option['price'] ) . ')' : '';
$current_value = (
isset( $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) ] ) &&
in_array( sanitize_title( $option['label'] ), $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) ] )
) ? 1 : 0;
?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ) . '-' . $i; ?>">
<label><input type="checkbox" class="addon addon-checkbox" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>[]" data-price="<?php echo $option['price']; ?>" value="<?php echo sanitize_title( $option['label'] ); ?>" <?php checked( $current_value, 1 ); ?> /> <?php echo wptexturize( $option['label'] . ' ' . $price ); ?></label>
</p>
<?php endforeach; ?>
\ No newline at end of file
<?php foreach ( $addon['options'] as $key => $option ) :
$current_value = isset( $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] ) ? $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] : '';
$price = $option['price'] > 0 ? '(' . woocommerce_price( $option['price'] ) . ')' : '';
if ( empty( $option['label'] ) ) : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<input type="text" class="input-text addon addon-custom" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" value="<?php echo esc_attr( $current_value ); ?>" <?php if ( ! empty( $option['max'] ) ) echo 'maxlength="' . $option['max'] .'"'; ?> />
</p>
<?php else : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<label><?php echo wptexturize( $option['label'] ) . ' ' . $price; ?> <input type="text" class="input-text addon addon-custom" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" value="<?php echo esc_attr( $current_value ); ?>" <?php if ( ! empty( $option['max'] ) ) echo 'maxlength="' . $option['max'] .'"'; ?> /></label>
</p>
<?php endif; ?>
<?php endforeach; ?>
\ No newline at end of file
<?php foreach ( $addon['options'] as $key => $option ) :
$current_value = isset( $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] ) ? $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] : '';
$price = $option['price'] > 0 ? '(' . woocommerce_price( $option['price'] ) . ')' : '';
if ( empty( $option['label'] ) ) : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<input type="number" step="any" class="input-text addon addon-custom-price" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" value="<?php echo esc_attr( $current_value ); ?>" <?php if ( ! empty( $option['min'] ) ) echo 'min="' . $option['min'] .'"'; ?> <?php if ( ! empty( $option['max'] ) ) echo 'max="' . $option['max'] .'"'; ?> />
</p>
<?php else : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<label><?php echo wptexturize( $option['label'] ) . ' ' . $price; ?> <input type="number" step="any" class="input-text addon addon-custom-price" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" value="<?php echo esc_attr( $current_value ); ?>" <?php if ( ! empty( $option['min'] ) ) echo 'min="' . $option['min'] .'"'; ?> <?php if ( ! empty( $option['max'] ) ) echo 'max="' . $option['max'] .'"'; ?> /></label>
</p>
<?php endif; ?>
<?php endforeach; ?>
\ No newline at end of file
<?php foreach ( $addon['options'] as $key => $option ) :
$current_value = isset( $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] ) ? $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] : '';
$price = $option['price'] > 0 ? '(' . woocommerce_price( $option['price'] ) . ')' : '';
if ( empty( $option['label'] ) ) : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<textarea type="text" class="input-text addon addon-custom-textarea" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" rows="4" cols="20" <?php if ( ! empty( $option['max'] ) ) echo 'maxlength="' . $option['max'] .'"'; ?>><?php echo esc_textarea( $current_value ); ?></textarea>
</p>
<?php else : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<label><?php echo wptexturize( $option['label'] ) . ' ' . $price; ?> <textarea type="text" class="input-text addon addon-custom-textarea" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" rows="4" cols="20" <?php if ( ! empty( $option['max'] ) ) echo 'maxlength="' . $option['max'] .'"'; ?>><?php echo esc_textarea( $current_value ); ?></textarea></label>
</p>
<?php endif; ?>
<?php endforeach; ?>
\ No newline at end of file
<?php foreach ( $addon['options'] as $key => $option ) :
$price = ($option['price']>0) ? ' (' . woocommerce_price( $option['price'] ) . ')' : '';
if ( empty( $option['label'] ) ) : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<input type="file" class="input-text addon" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" /> <small><?php echo sprintf( __( '(max file size %s)', 'wc_product_addons' ), $max_size ) ?></small>
</p>
<?php else : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<label><?php echo wptexturize( $option['label'] ) . ' ' . $price; ?> <input type="file" class="input-text addon" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" /> <small><?php echo sprintf( __( '(max file size %s)', 'wc_product_addons' ), $max_size ) ?></small></label>
</p>
<?php endif; ?>
<?php endforeach; ?>
\ No newline at end of file
<?php foreach ( $addon['options'] as $key => $option ) :
$current_value = max( 0, $option['min'], isset( $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] ) ? $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) . '-' . sanitize_title( $option['label'] ) ] : '' );
$price = $option['price'] > 0 ? '(' . woocommerce_price( $option['price'] ) . ')' : '';
if ( empty( $option['label'] ) ) : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<input type="number" step="" class="input-text addon addon-input_multiplier" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" value="<?php echo esc_attr( $current_value ); ?>" <?php if ( ! empty( $option['min'] ) || $option['min'] === '0' ) echo 'min="' . $option['min'] .'"'; ?> <?php if ( ! empty( $option['max'] ) ) echo 'max="' . $option['max'] .'"'; ?> />
<span class="addon-alert"><?php _e( 'This must be a number!', 'wc_product_addons' ); ?></span>
</p>
<?php else : ?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<label><?php echo wptexturize( $option['label'] ) . ' ' . $price; ?> <input type="number" step="" class="input-text addon addon-input_multiplier" data-price="<?php echo $option['price']; ?>" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>-<?php echo sanitize_title( $option['label'] ); ?>" value="<?php echo esc_attr( $current_value ); ?>" <?php if ( ! empty( $option['min'] ) || $option['min'] === '0' ) echo 'min="' . $option['min'] .'"'; ?> <?php if ( ! empty( $option['max'] ) ) echo 'max="' . $option['max'] .'"'; ?> /></label>
<span class="addon-alert"><?php _e( 'This must be a number!', 'wc_product_addons' ); ?></span>
</p>
<?php endif; ?>
<?php endforeach; ?>
\ No newline at end of file
<?php $first = true; foreach ( $addon['options'] as $i => $option ) :
$price = $option['price'] > 0 ? '(' . woocommerce_price( $option['price'] ) . ')' : '';
if ( isset( $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) ] ) ) {
$current_value = (
isset( $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) ] ) &&
in_array( sanitize_title( $option['label'] ), $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) ] )
) ? 1 : 0;
} else {
$current_value = $first ? 1 : 0;
$first = false;
}
?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ) . '-' . $i; ?>">
<label><input type="radio" class="addon addon-radio" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>[]" data-price="<?php echo $option['price']; ?>" value="<?php echo sanitize_title( $option['label'] ); ?>" <?php checked( $current_value, 1 ); ?> /> <?php echo wptexturize( $option['label'] . ' ' . $price ); ?></label>
</p>
<?php endforeach; ?>
\ No newline at end of file
<?php
$loop = 0;
$current_value = isset( $_POST['addon-' . sanitize_title( $addon['field-name'] ) ] ) ? $_POST[ 'addon-' . sanitize_title( $addon['field-name'] ) ] : '';
?>
<p class="form-row form-row-wide addon-wrap-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<select class="addon addon-select" name="addon-<?php echo sanitize_title( $addon['field-name'] ); ?>">
<?php if ( ! isset( $addon['required'] ) ) : ?>
<option value=""><?php _e('None', 'wc_product_addons'); ?></option>
<?php else : ?>
<option value=""><?php _e('Select an option...', 'wc_product_addons'); ?></option>
<?php endif; ?>
<?php foreach ( $addon['options'] as $option ) :
$loop ++;
$price = $option['price'] > 0 ? ' (' . woocommerce_price( $option['price'] ) . ')' : '';
?>
<option data-price="<?php echo $option['price']; ?>" value="<?php echo sanitize_title( $option['label'] ) . '-' . $loop; ?>" <?php selected( $current_value, sanitize_title( $option['label'] ) . '-' . $loop ); ?>><?php echo wptexturize( $option['label'] ) . $price ?></option>
<?php endforeach; ?>
</select>
</p>
\ No newline at end of file
<?php
/**
* WC Dependency Checker
*
* Checks if WooCommerce is enabled
*/
class WC_Dependencies {
private static $active_plugins;
public static function init() {
self::$active_plugins = (array) get_option( 'active_plugins', array() );
if ( is_multisite() )
self::$active_plugins = array_merge( self::$active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
}
public static function woocommerce_active_check() {
if ( ! self::$active_plugins ) self::init();
return in_array( 'woocommerce/woocommerce.php', self::$active_plugins ) || array_key_exists( 'woocommerce/woocommerce.php', self::$active_plugins );
}
}
<?php
/**
* Functions used by plugins
*/
if ( ! class_exists( 'WC_Dependencies' ) )
require_once 'class-wc-dependencies.php';
/**
* WC Detection
*/
if ( ! function_exists( 'is_woocommerce_active' ) ) {
function is_woocommerce_active() {
return WC_Dependencies::woocommerce_active_check();
}
}
/**
* Queue updates for the WooUpdater
*/
if ( ! function_exists( 'woothemes_queue_update' ) ) {
function woothemes_queue_update( $file, $file_id, $product_id ) {
global $woothemes_queued_updates;
if ( ! isset( $woothemes_queued_updates ) )
$woothemes_queued_updates = array();
$plugin = new stdClass();
$plugin->file = $file;
$plugin->file_id = $file_id;
$plugin->product_id = $product_id;
$woothemes_queued_updates[] = $plugin;
}
}
/**
* Load installer for the WooThemes Updater.
* @return $api Object
*/
if ( ! class_exists( 'WooThemes_Updater' ) && ! function_exists( 'woothemes_updater_install' ) ) {
function woothemes_updater_install( $api, $action, $args ) {
$download_url = 'http://woodojo.s3.amazonaws.com/downloads/woothemes-updater/woothemes-updater.zip';
if ( 'plugin_information' != $action ||
false !== $api ||
! isset( $args->slug ) ||
'woothemes-updater' != $args->slug
) return $api;
$api = new stdClass();
$api->name = 'WooThemes Updater';
$api->version = '1.0.0';
$api->download_link = esc_url( $download_url );
return $api;
}
add_filter( 'plugins_api', 'woothemes_updater_install', 10, 3 );
}
/**
* WooUpdater Installation Prompts
*/
if ( ! class_exists( 'WooThemes_Updater' ) && ! function_exists( 'woothemes_updater_notice' ) ) {
/**
* Display a notice if the "WooThemes Updater" plugin hasn't been installed.
* @return void
*/
function woothemes_updater_notice() {
$active_plugins = apply_filters( 'active_plugins', get_option('active_plugins' ) );
if ( in_array( 'woothemes-updater/woothemes-updater.php', $active_plugins ) ) return;
$slug = 'woothemes-updater';
$install_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . $slug ), 'install-plugin_' . $slug );
$activate_url = 'plugins.php?action=activate&plugin=' . urlencode( 'woothemes-updater/woothemes-updater.php' ) . '&plugin_status=all&paged=1&s&_wpnonce=' . urlencode( wp_create_nonce( 'activate-plugin_woothemes-updater/woothemes-updater.php' ) );
$message = '<a href="' . esc_url( $install_url ) . '">Install the WooThemes Updater plugin</a> to get updates for your WooThemes plugins.';
$is_downloaded = false;
$plugins = array_keys( get_plugins() );
foreach ( $plugins as $plugin ) {
if ( strpos( $plugin, 'woothemes-updater.php' ) !== false ) {
$is_downloaded = true;
$message = '<a href="' . esc_url( admin_url( $activate_url ) ) . '">Activate the WooThemes Updater plugin</a> to get updates for your WooThemes plugins.';
}
}
echo '<div class="updated fade"><p>' . $message . '</p></div>' . "\n";
}
add_action( 'admin_notices', 'woothemes_updater_notice' );
}
/**
* Prevent conflicts with older versions
*/
if ( ! class_exists( 'WooThemes_Plugin_Updater' ) ) {
class WooThemes_Plugin_Updater { function init() {} }
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment