PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/admin/write-panels/product-types/variable.php

https://github.com/scottpoulin/jigoshop
PHP | 607 lines | 390 code | 94 blank | 123 comment | 57 complexity | 96bd2def818afc6654793c3df1fa1873 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * Variable Product Type
  4. *
  5. * Functions specific to variable products (for the write panels)
  6. *
  7. * DISCLAIMER
  8. *
  9. * Do not edit or add directly to this file if you wish to upgrade Jigoshop to newer
  10. * versions in the future. If you wish to customise Jigoshop core for your needs,
  11. * please use our GitHub repository to publish essential changes for consideration.
  12. *
  13. * @package Jigoshop
  14. * @category Admin
  15. * @author Jigoshop
  16. * @copyright Copyright Š 2011-2013 Jigoshop.
  17. * @license http://jigoshop.com/license/commercial-edition
  18. */
  19. // Temporary fix for selectbox triggering the click event.
  20. // For some reason enqueing the script inside a class causes the event unbind()
  21. // to not work. Would prefer this to be part of the class but perhaps its better to enqueue
  22. // everything all at once.
  23. add_action( 'admin_enqueue_scripts', 'jigoshop_product_meta_variable_script' );
  24. function jigoshop_product_meta_variable_script( $hook ) {
  25. global $post;
  26. // Don't enqueue script if not on product edit screen
  27. if ( $hook != 'post.php' || $post->post_type != 'product' )
  28. return false;
  29. wp_enqueue_script('jigoshop-variable-js', jigoshop::assets_url() . '/assets/js/variable.js' , array('jquery'),1,true);
  30. }
  31. class jigoshop_product_meta_variable extends jigoshop_product_meta
  32. {
  33. public function __construct() {
  34. add_action( 'jigoshop_product_write_panel_tabs', array($this, 'register_tab') );
  35. add_action( 'jigoshop_process_product_meta_variable', array($this, 'save'), 1 );
  36. add_action( 'jigoshop_product_write_panels', array($this, 'display') );
  37. add_action( 'admin_enqueue_scripts', array($this, 'admin_enqueue_scripts') );
  38. add_action( 'wp_ajax_jigoshop_remove_variation', array($this, 'remove') );
  39. }
  40. /**
  41. * Registers tab for use in the product meta box
  42. *
  43. * @return void
  44. */
  45. public function register_tab() {
  46. echo '<li class="variable_tab">
  47. <a href="#variable_product_options">'.__('Variations','jigoshop').'</a>
  48. </li>';
  49. }
  50. /**
  51. * Registers scripts for use in the admin
  52. * Also localizes variables for use in the javascript, essential for variation addition
  53. *
  54. * @return void
  55. */
  56. public function admin_enqueue_scripts( $hook ) {
  57. global $post;
  58. // Don't enqueue script if not on product edit screen
  59. if ( $hook != 'post.php' || $post->post_type != 'product' )
  60. return false;
  61. // wp_enqueue_script('jigoshop-variable-js', jigoshop::assets_url() . '/assets/js/variable.js', array('postbox', 'jquery'), true);
  62. wp_localize_script( 'jigoshop-variable-js', 'varmeta', array(
  63. 'assets_url' => jigoshop::assets_url(),
  64. 'ajax_url' => admin_url('admin-ajax.php'),
  65. 'i18n' => array(
  66. 'variations_required' => __('You need to add some variations first', 'jigoshop'),
  67. 'remove_all' => __('Are you sure you want to delete all variations', 'jigoshop'),
  68. 'set_regular_price' => __('Enter a regular price', 'jigoshop'),
  69. 'set_sale_price' => __('Enter a sale price', 'jigoshop'),
  70. 'set_stock' => __('Enter a stock value', 'jigoshop'),
  71. 'set_weight' => __('Enter a weight value', 'jigoshop'),
  72. 'set_width' => __('Enter a width value', 'jigoshop'),
  73. 'set_length' => __('Enter a length value', 'jigoshop'),
  74. 'set_height' => __('Enter a height value', 'jigoshop'),
  75. ),
  76. 'actions' => array(
  77. 'remove' => array(
  78. 'action' => 'jigoshop_remove_variation',
  79. 'nonce' => wp_create_nonce("delete-variation"),
  80. 'confirm' => __('Are you sure you want to remove this variation?', 'jigoshop'),
  81. ),
  82. 'create' => array(
  83. 'action' => 'jigoshop_create_variation',
  84. 'panel' => $this->generate_panel(maybe_unserialize( get_post_meta($post->ID, 'product_attributes', true) ))
  85. )
  86. )
  87. ));
  88. }
  89. /**
  90. * Echos a variable type option for the product type selector
  91. *
  92. * @return void
  93. */
  94. public function register( $type ) {
  95. echo '<option value="variable" ' . selected($type, 'variable', false) . '>' . __('Variable', 'jigoshop') . '</option>';
  96. }
  97. /**
  98. * Removes a product variation via XHR
  99. *
  100. * @return void
  101. */
  102. public function remove() {
  103. check_ajax_referer( 'delete-variation', 'security' );
  104. $ID = intval( $_POST['variation_id'] );
  105. wp_set_object_terms( $ID, null, 'product_type'); // Remove object terms
  106. wp_delete_post( $ID );
  107. exit;
  108. }
  109. /**
  110. * Process the product variable meta
  111. *
  112. * @param int Product ID
  113. * @return void
  114. */
  115. public function save( $parent_id ) {
  116. global $wpdb;
  117. // Do not run if there are no variations
  118. if ( ! isset($_POST['variations']) )
  119. return false;
  120. // Get the attributes to be used later
  121. $attributes = (array) maybe_unserialize( get_post_meta($parent_id, 'product_attributes', true) );
  122. foreach ( $_POST['variations'] as $ID => $meta ) {
  123. /**
  124. * Generate a post title of the current variation.
  125. * Parent Title - [attribute: variation]
  126. */
  127. $taxes = array();
  128. foreach ( $meta as $k => $v ) :
  129. if ( strstr ( $k, 'tax_' ) ) {
  130. $tax = substr( $k, 4 );
  131. $taxes[] = sprintf('[%s: %s]', $tax, !empty($v) ? $v : 'Any ' . $tax );
  132. }
  133. endforeach;
  134. $post_title = !empty($_POST['post_title']) ? $_POST['post_title'] : the_title('','',false);
  135. $title = sprintf('%s - %s', $post_title, implode( $taxes, ' ' ) );
  136. /**
  137. * Prevent duplicate variations
  138. */
  139. // Update post data or Add post if new
  140. if ( strpos( $ID, '_new' ) ) {
  141. // check for an existing variation with matching attributes to prevent duplication
  142. $current_meta = $meta;
  143. foreach ( $current_meta as $current_id => $current_value ) {
  144. // discard everything but the taxonomies
  145. if ( strpos( $current_id, 'tax_' ) !== 0 ) {
  146. unset( $current_meta[$current_id] );
  147. }
  148. }
  149. // we now have just the taxonomies in use for this new variation in $current_meta, match them up to others
  150. $all_variations = $_POST['variations'];
  151. unset( $all_variations[$ID] ); // we don't need the current new variation
  152. $duplicate = false;
  153. foreach ( $all_variations as $this_id => $this_meta ) {
  154. $haystack_meta = $this_meta;
  155. foreach ( $haystack_meta as $haystack_id => $haystack_value ) {
  156. // discard everything but the taxonomies
  157. if ( strpos( $haystack_id, 'tax_' ) !== 0 ) {
  158. unset( $haystack_meta[$haystack_id] );
  159. }
  160. }
  161. // we now have the taxonomies only for this haystack variation
  162. $result = array_diff( $haystack_meta, $current_meta );
  163. if ( empty( $result ) ) $duplicate = true;
  164. }
  165. if ( ! $duplicate ) {
  166. $ID = wp_insert_post( array(
  167. 'post_title' => !empty($title) ? $title : "#{$parent_id}: Child Variation",
  168. 'post_status' => isset($meta['enabled']) ? 'publish' : 'draft',
  169. 'post_parent' => $parent_id,
  170. 'post_type' => 'product_variation'
  171. ));
  172. } else {
  173. // silent fail, should put up a message?
  174. }
  175. } else {
  176. $wpdb->update( $wpdb->posts, array(
  177. 'post_title' => !empty($title) ? $title : "#{$parent_id}: Child Variation",
  178. 'post_status' => isset($meta['enabled']) ? 'publish' : 'draft'
  179. ), array( 'ID' => $ID ) );
  180. }
  181. // Set the product type
  182. wp_set_object_terms( $ID, sanitize_title($meta['product-type']), 'product_type');
  183. // Set variation meta data
  184. update_post_meta( $ID, 'sku', $meta['sku'] );
  185. update_post_meta( $ID, 'regular_price', $meta['regular_price'] );
  186. $sale_price = ! empty( $meta['sale_price'] )
  187. ? ( !strstr( $meta['sale_price'], '%' ) ? jigoshop_sanitize_num( $meta['sale_price'] ) : $meta['sale_price'] )
  188. : '';
  189. if ( strstr( $meta['sale_price'], '%' ) ) {
  190. update_post_meta( $ID, 'sale_price', $sale_price );
  191. } else if ( ! empty( $sale_price ) && $sale_price < jigoshop_sanitize_num( $meta['regular_price'] ) ) {
  192. update_post_meta( $ID, 'sale_price', $sale_price );
  193. } else {
  194. // silently fail if entered sale price > regular price (or nothing entered)
  195. update_post_meta( $ID, 'sale_price', '' );
  196. }
  197. update_post_meta( $ID, 'weight', $meta['weight'] );
  198. update_post_meta( $ID, 'length', $meta['length'] );
  199. update_post_meta( $ID, 'height', $meta['height'] );
  200. update_post_meta( $ID, 'width', $meta['width'] );
  201. update_post_meta( $ID, 'stock', $meta['stock'] );
  202. update_post_meta( $ID, '_thumbnail_id', $meta['_thumbnail_id'] );
  203. // Downloadable Only
  204. if( $meta['product-type'] == 'downloadable' ) {
  205. update_post_meta( $ID, 'file_path', $meta['file_path']);
  206. update_post_meta( $ID, 'download_limit', $meta['download_limit']);
  207. }
  208. // Refresh taxonomy attributes
  209. $current_meta = get_post_custom( $ID );
  210. // Remove the current data
  211. delete_post_meta( $ID, 'variation_data' );
  212. // Update taxonomies
  213. $variation_data = array();
  214. foreach ( $attributes as $attribute ) {
  215. // Skip if attribute is not for variation
  216. if ( ! isset( $attribute['variation'] )) continue;
  217. // Configure the data
  218. $key = 'tax_' . sanitize_title($attribute['name']);
  219. if ( isset( $meta[$key] ) ) $variation_data[$key] = $meta[$key];
  220. }
  221. update_post_meta( $ID, 'variation_data', $variation_data );
  222. do_action( 'jigoshop_variable_product_table_data_save' , $ID, $meta);
  223. }
  224. // Update default attribute options setting
  225. $default_attributes = array();
  226. foreach ($attributes as $attribute) {
  227. if ( isset( $attribute['variation'] ) ) {
  228. $value = 'default_attribute_' . sanitize_title($attribute['name']);
  229. if ( isset( $_POST[$value] )) {
  230. $value = esc_attr(trim($_POST[$value]));
  231. } else {
  232. $value = null;
  233. }
  234. if ($value) {
  235. $default_attributes[sanitize_title($attribute['name'])] = $value;
  236. }
  237. }
  238. }
  239. update_post_meta( $parent_id, '_default_attributes', $default_attributes );
  240. }
  241. public function display() {
  242. global $post;
  243. // Get the attributes
  244. $attributes = (array) maybe_unserialize( get_post_meta($post->ID, 'product_attributes', true) );
  245. // Get all variations of the product
  246. $variations = get_posts(array(
  247. 'post_type' => 'product_variation',
  248. 'post_status' => array('draft', 'publish'),
  249. 'numberposts' => -1,
  250. 'orderby' => 'id',
  251. 'order' => 'desc',
  252. 'post_parent' => $post->ID
  253. ));
  254. ?>
  255. <div id='variable_product_options' class='panel'>
  256. <?php if($this->has_variable_attributes($attributes)): ?>
  257. <div class="toolbar">
  258. <select name="variation_actions">
  259. <option value="default"><?php _e('Bulk Actions', 'jigoshop') ?></option>
  260. <option value="remove_all"><?php _e('Remove All Variations', 'jigoshop') ?></option>
  261. <optgroup label="<?php _e('Set All', 'jigoshop') ?>:">
  262. <option value="set_all_regular_prices"><?php _e('Regular Prices', 'jigoshop') ?></option>
  263. <option value="set_all_sale_prices"><?php _e('Sale Prices', 'jigoshop') ?></option>
  264. <option value="set_all_stock"><?php _e('Stock', 'jigoshop') ?></option>
  265. <option value="set_all_weight"><?php _e('Weight', 'jigoshop') ?></option>
  266. <option value="set_all_width"><?php _e('Width', 'jigoshop') ?></option>
  267. <option value="set_all_length"><?php _e('Length', 'jigoshop') ?></option>
  268. <option value="set_all_height"><?php _e('Height', 'jigoshop') ?></option>
  269. </optgroup>
  270. </select>
  271. <input id="do_actions" type="submit" class="button-secondary" value="<?php _e('Apply','jigoshop'); ?>">
  272. <button type='button' class='button button-seconday add_variation'><?php _e('Add Variation', 'jigoshop') ?></button>
  273. </div>
  274. <?php endif; ?>
  275. <div class='jigoshop_variations'>
  276. <?php if ( $this->has_variable_attributes( $attributes ) ): ?>
  277. <?php
  278. if( $variations ) {
  279. foreach( $variations as $variation ) {
  280. echo $this->generate_panel($attributes, $variation);
  281. }
  282. }
  283. ?>
  284. <?php endif; ?>
  285. </div>
  286. <div class="toolbar">
  287. <strong><?php _e('Default selections:', 'jigoshop'); ?></strong>
  288. <?php
  289. $default_attributes = (array) maybe_unserialize(get_post_meta( $post->ID, '_default_attributes', true ));
  290. foreach ($attributes as $attr) {
  291. // If not variable attribute then skip
  292. if ( ! isset( $attr['variation'] ) )
  293. continue;
  294. // Get current value for variation (if set)
  295. $selected = (isset($default_attributes[sanitize_title($attr['name'])])) ? $default_attributes[sanitize_title($attr['name'])] : '';
  296. // Open the select & set a default value
  297. echo '<select name="default_attribute_' . sanitize_title($attr['name']).'" >';
  298. echo '<option value="">'.__('No default', 'jigoshop') . ' ' . jigoshop_product::attribute_label('pa_'.$attr['name']).'&hellip;</option>';
  299. // Get terms for attribute taxonomy or value if its a custom attribute
  300. if ( $attr['is_taxonomy'] ) {
  301. $options = wp_get_object_terms( $post->ID, 'pa_'.sanitize_title($attr['name']), array( 'orderby' => 'slug' ) );
  302. if( ! is_wp_error( $options )) foreach( $options as $option ) {
  303. echo '<option value="'.esc_attr($option->slug).'" '.selected($selected, $option->slug, false).'>'.$option->name.'</option>';
  304. }
  305. }
  306. else {
  307. $options = explode(',', $attr['value']);
  308. foreach( $options as $option ) {
  309. $option = trim($option);
  310. echo '<option '.selected($selected, $option, false).' value="'.esc_attr($option).'">'.$option.'</option>';
  311. }
  312. }
  313. // Close the select
  314. echo '</select>';
  315. }
  316. ?>
  317. </div>
  318. </div>
  319. <?php
  320. }
  321. /**
  322. * Returns a specially formatted field name for variations
  323. *
  324. * @param string Field Name
  325. * @param object Variation Post Object
  326. * @return string
  327. */
  328. private function field_name( $name, $variation = null ) {
  329. return "variations[{$variation->ID}][{$name}]";
  330. }
  331. /**
  332. * Returns all the possible variable attributes in select form
  333. *
  334. * @param array Attributes array
  335. * @param object Variation Post Object
  336. * @return HTML
  337. */
  338. private function attribute_selector( $attributes, $variation = null ) {
  339. global $post;
  340. $html = null;
  341. if ( ! is_ajax() ) {
  342. $variation_data = get_post_meta( $variation->ID, 'variation_data' );
  343. }
  344. // Attribute Variation Selector
  345. foreach ( $attributes as $attr ) {
  346. // If not variable attribute then skip
  347. if ( ! isset( $attr['variation'] ) ) continue;
  348. // Get current value for variation (if set)
  349. $selected = '';
  350. if ( ! is_ajax() ) {
  351. $tax = 'tax_' . sanitize_title($attr['name']);
  352. if ( isset( $variation_data[0][ $tax ] )) $selected = $variation_data[0][ $tax ];
  353. }
  354. // Open the select & set a default value
  355. $html .= '<select name="' . $this->field_name('tax_' . sanitize_title($attr['name']), $variation) . '" >
  356. <option value="">'.__('Any', 'jigoshop') . ' ' .jigoshop_product::attribute_label('pa_'.$attr['name']).'&hellip;</option>';
  357. // Get terms for attribute taxonomy or value if its a custom attribute
  358. if ( $attr['is_taxonomy'] ) {
  359. $options = wp_get_object_terms( $post->ID, 'pa_'.sanitize_title($attr['name']), array( 'orderby' => 'slug' ) );
  360. if ( ! is_wp_error( $options )) foreach( $options as $option ) {
  361. $html .= '<option value="'.esc_attr($option->slug).'" '.selected($selected, $option->slug, false).'>'.$option->name.'</option>';
  362. }
  363. }
  364. else {
  365. $options = explode(',', $attr['value']);
  366. foreach( $options as $option ) {
  367. $option = trim($option);
  368. $html .= '<option '.selected($selected, $option, false).' value="'.esc_attr($option).'">'.$option.'</option>';
  369. }
  370. }
  371. // Close the select
  372. $html .= '</select>';
  373. }
  374. return $html;
  375. }
  376. /**
  377. * Checks all the product attributes for variation defined attributes
  378. *
  379. * @param mixed Attributes
  380. * @return bool
  381. */
  382. private function has_variable_attributes( $attributes ) {
  383. if ( ! $attributes )
  384. return false;
  385. foreach ( $attributes as $attribute ) {
  386. if ( isset($attribute['variation']) && $attribute['variation'] )
  387. return true;
  388. }
  389. return false;
  390. }
  391. /**
  392. * Generates a variation panel
  393. *
  394. * @param array attributes
  395. * @param object variation
  396. * @return HTML
  397. */
  398. private function generate_panel($attributes, $variation = null) {
  399. if ( ! $this->has_variable_attributes($attributes) )
  400. return false;
  401. // Set the default image as the placeholder
  402. $image = jigoshop::assets_url().'/assets/images/placeholder.png';
  403. if ( ! $variation ) {
  404. // Create a blank variation object with a unique id
  405. $variation = new stdClass;
  406. $variation->ID = '__ID__';
  407. $variation->post_status = 'publish';
  408. }
  409. else {
  410. // Get the variation meta
  411. $meta = get_post_custom( $variation->ID );
  412. // If variation has a thumbnail display that
  413. if ( $image_id = $meta['_thumbnail_id'][0] )
  414. $image = wp_get_attachment_url( $image_id );
  415. }
  416. // Start buffering the output
  417. ob_start();
  418. ?>
  419. <div class="jigoshop_variation postbox closed" rel="<?php echo $variation->ID; ?>">
  420. <button type="button" class="remove_variation button"><?php _e('Remove', 'jigoshop'); ?></button>
  421. <div class="handlediv" title="Click to toggle"><br></div>
  422. <h3 class="handle"><?php echo $this->attribute_selector($attributes, $variation); ?></h3>
  423. <div class="inside">
  424. <table cellpadding="0" cellspacing="0" class="jigoshop_variable_attributes">
  425. <tbody>
  426. <?php do_action('jigoshop_variable_product_table_begin', $variation, $attributes)?>
  427. <tr>
  428. <td class="upload_image" rowspan="2">
  429. <a href="#" class="upload_image_button <?php if (isset($image_id)) echo 'remove'; ?>" rel="<?php echo $variation->ID; ?>">
  430. <img src="<?php echo $image ?>" width="93px" />
  431. <input type="hidden" name="<?php echo esc_attr( $this->field_name('_thumbnail_id', $variation) ); ?>" class="upload_image_id" value="<?php if ( isset($image_id)) echo esc_attr( $image_id ); ?>" />
  432. <!-- TODO: APPEND THIS IN JS <span class="overlay"></span> -->
  433. </a>
  434. </td>
  435. <td>
  436. <?php
  437. $terms = get_the_terms( $variation->ID, 'product_type' );
  438. $product_type = ($terms) ? current($terms)->slug : 'simple';
  439. ?>
  440. <label class="clearlabel"><?php _e('Type', 'jigoshop') ?></label>
  441. <select class="product_type" name="<?php echo esc_attr( $this->field_name('product-type', $variation) ); ?>">
  442. <option value="simple" <?php selected('simple', $product_type) ?>><?php _e('Simple', 'jigoshop') ?></option>
  443. <option value="downloadable" <?php selected('downloadable', $product_type) ?>><?php _e('Downloadable', 'jigoshop') ?></option>
  444. <option value="virtual" <?php selected('virtual', $product_type) ?>><?php _e('Virtual', 'jigoshop') ?></option>
  445. </select>
  446. </td>
  447. <td>
  448. <label><?php _e('SKU', 'jigoshop'); ?>
  449. <input type="text" name="<?php echo esc_attr( $this->field_name('sku', $variation) ); ?>" placeholder="<?php echo esc_attr( $variation->ID ); ?>" value="<?php echo esc_attr( isset($meta['sku'][0]) ? $meta['sku'][0] : null ); ?>" />
  450. </label>
  451. </td>
  452. <td>
  453. <label><?php _e('Stock Qty', 'jigoshop'); ?>
  454. <input type="text" name="<?php echo esc_attr( $this->field_name('stock', $variation) ); ?>" value="<?php echo esc_attr( isset($meta['stock'][0]) ? $meta['stock'][0] : null ); ?>" />
  455. </label>
  456. </td>
  457. <td>
  458. <label><?php _e('Price', 'jigoshop'); ?>
  459. <input type="text" name="<?php echo esc_attr( $this->field_name('regular_price', $variation) ); ?>" value="<?php echo esc_attr( isset($meta['regular_price'][0]) ? $meta['regular_price'][0] : null ); ?>" />
  460. </label>
  461. </td>
  462. <td>
  463. <label><?php _e('Sale Price', 'jigoshop'); ?>
  464. <input type="text" name="<?php echo esc_attr( $this->field_name('sale_price', $variation) ); ?>" value="<?php echo esc_attr( isset($meta['sale_price'][0]) ? $meta['sale_price'][0] : null ); ?>" />
  465. </label>
  466. </td>
  467. <td>
  468. <label><?php _e('Enabled', 'jigoshop'); ?>
  469. <input type="checkbox" class="checkbox" name="<?php echo esc_attr( $this->field_name('enabled', $variation) ); ?>" <?php checked($variation->post_status, 'publish'); ?> />
  470. </label>
  471. </td>
  472. </tr>
  473. <tr class="simple options" <?php echo ( ('simple' == $product_type) || ('variable' == $product_type)) ? 'style="display: table-row;"' : 'style="display: none;"';?>>
  474. <td>
  475. <label><?php _e('Weight', 'jigoshop') ?>
  476. <input type="text" name="<?php echo esc_attr( $this->field_name('weight', $variation) ); ?>" value="<?php echo esc_attr( isset($meta['weight'][0]) ? $meta['weight'][0] : null ); ?>" />
  477. </label>
  478. </td>
  479. <td colspan="4" class="dimensions">
  480. <label><?php _e('Dimensions', 'jigoshop') ?> <?php echo '('. Jigoshop_Base::get_options()->get_option('jigoshop_dimension_unit'). ')' ?></label>
  481. <input type="text" name="<?php echo esc_attr( $this->field_name('length', $variation) ); ?>" placeholder="<?php _e('Length', 'jigoshop') ?>" value="<?php echo esc_attr( isset($meta['length'][0]) ? $meta['length'][0] : null ); ?>" />
  482. <input type="text" name="<?php echo esc_attr( $this->field_name('width', $variation) ); ?>" placeholder="<?php _e('Width', 'jigoshop') ?>" value="<?php echo esc_attr( isset($meta['width'][0]) ? $meta['width'][0] : null ); ?>" />
  483. <input type="text" name="<?php echo esc_attr( $this->field_name('height', $variation) ); ?>" placeholder="<?php _e('Height', 'jigoshop') ?>" value="<?php echo esc_attr( isset($meta['height'][0]) ? $meta['height'][0] : null ); ?>" />
  484. <td colspan="3"></td>
  485. </td>
  486. </tr>
  487. <tr class="downloadable options" <?php echo ('downloadable' == $product_type) ? 'style="display: table-row;"' : 'style="display: none;"';?>>
  488. <td colspan="4" class="download_file">
  489. <label class="clearlabel"><?php _e('File Location', 'jigoshop') ?></label>
  490. <input type="text" name="<?php echo esc_attr( $this->field_name('file_path', $variation) ); ?>" value="<?php echo esc_attr( isset($meta['file_path'][0]) ? $meta['file_path'][0] : null ); ?>" />
  491. <input type="submit" class="upload_file_button button-secondary" value="Upload">
  492. </td>
  493. <td colspan="2">
  494. <label><?php _e('Re-downloads Limit', 'jigoshop') ?>
  495. <input type="text" name="<?php echo esc_attr( $this->field_name('download_limit', $variation) ); ?>" value="<?php echo esc_attr( isset($meta['file_path'][0]) ? $meta['download_limit'][0] : null ); ?>" />
  496. </label>
  497. </td>
  498. </tr>
  499. <tr class="virtual options" <?php echo ('virtual' == $product_type ? 'style="display: table-row;"' : 'style="display: none;"');?>>
  500. <td colspan="6">
  501. &nbsp;
  502. </td>
  503. </tr>
  504. <?php do_action( 'jigoshop_variable_product_table_end' , $variation, $attributes)?>
  505. </tbody>
  506. </table>
  507. </div>
  508. </div>
  509. <?php
  510. // Flush & return the buffer
  511. return ob_get_clean();
  512. }
  513. } new jigoshop_product_meta_variable();