/**
  * Initializes the plugin
  */
 public function after_init()
 {
     $this->options_slug = 'woocommerce_ag-magma-ml-integration_settings';
     if ($this->user_has_privileges()) {
         if (isset($_POST['woocommerce_ag-magma-ml-integration_ml_app_id'])) {
             ML()->ml_app_id = $_POST['woocommerce_ag-magma-ml-integration_ml_app_id'];
         }
         if (isset($_POST['woocommerce_ag-magma-ml-integration_ml_secret_key'])) {
             ML()->ml_secret_key = $_POST['woocommerce_ag-magma-ml-integration_ml_secret_key'];
         }
     }
     require_once 'includes/class-ml-communication.php';
     $this->ml_communication = ML_Communication::get_instance('ML_Communication');
     require_once 'includes/class-ml-product.php';
     require_once 'includes/class-ml-category.php';
     if (defined('DOING_AJAX')) {
         // Include Ajax and dependencies
         require_once 'includes/class-ml-questions.php';
         require_once 'includes/class-ml-ajax.php';
         ML_Ajax::get_instance('ML_Ajax');
     } else {
         if ($this->user_has_privileges()) {
             // Check if the user just logged out
             $this->check_logout();
             // Verify if the user just logged in
             $this->check_login();
             if ($this->ml_is_logged()) {
                 // Include Metaboxes
                 require_once 'includes/class-ml-metaboxes.php';
                 ML_Metaboxes::get_instance('ML_Metaboxes');
             }
         }
     }
     parent::after_init();
 }
 private function get_translated_message($obj)
 {
     if (empty($obj->cause[0]->code)) {
         return print_r($obj, true);
     }
     switch ($obj->cause[0]->code) {
         case 'item.start_time.invalid':
             return __('Invalid start time.', ML()->textdomain);
         case 'item.category_id.invalid':
             return __('Invalid category.', ML()->textdomain);
         case 'item.buying_mode.invalid':
             return __('Invalid buying mode.', ML()->textdomain);
         case 'item.available_quantity.invalid':
             return __('Invalid item quantity.', ML()->textdomain);
         case 'item.attributes.invalid':
             return __('Invalid item attributes.', ML()->textdomain);
         case 'item.variations.attribute_combinations.invalid':
             return __('Invalid attribute combinations.', ML()->textdomain);
         case 'item.attributes.missing_required':
             return __('Missing required attributes.', ML()->textdomain);
         case 'item.listing_type_id.invalid':
             return __('Invalid listing type.', ML()->textdomain);
         case 'item.listing_type_id.requiresPictures':
             return __('Pictures is required.', ML()->textdomain);
         case 'item.site_id.invalid':
             return __('Invalid site.', ML()->textdomain);
         case 'item.shipping.mode.invalid':
             return __('Invalid shipping mode.', ML()->textdomain);
         case 'item.description.max':
             return __('The number of characters in description must be less then 50000 characters.', ML()->textdomain);
         case 'item.pictures.max':
             return __('Number of images exceeded.', ML()->textdomain);
         case 'item.pictures.variation.quantity':
             return __('Every variation must have between 1 and 6 pictures.', ML()->textdomain);
         case 'item.attributes.invalid_length':
             return __('Invalid value length for an attribute.', ML()->textdomain);
         case 'item.title.not_modifiable':
             return __('Title is not modifiable.', ML()->textdomain);
         case 'item.condition.not_modifiable':
             return __('Condition is not modifiable.', ML()->textdomain);
         case 'item.buying_mode.not_modifiable':
             return __('Buying Mode is not modifiable.', ML()->textdomain);
         case 'item.warranty.not_modifiable':
             return __('Warranty is not modifiable.', ML()->textdomain);
         case 'body.invalid':
             return __('Invalid item body.', ML()->textdomain);
         case 'item.status.invalid':
             return __('Item in status closed is not possible to change to status closed.', ML()->textdomain);
         case 'item.variations.attribute_combinations.duplicated':
             return __('Variation attribute is duplicated. Allowed unique atrributes combinations.', ML()->textdomain);
         case 'file.not_found':
             return __('There is no file in request.', ML()->textdomain);
     }
     return print_r($obj, true);
 }
 public function init_form_fields()
 {
     $textdomain = ML()->textdomain;
     if (ML()->ml_is_logged()) {
         $this->form_fields = array('ml_logout_button' => array('title' => __('Logout', $textdomain), 'type' => 'link', 'href' => add_query_arg(array('ml-logout' => 'logout'), wp_get_referer()), 'description' => sprintf('%s: <code>%s</code>', __('Click to log out the current user', $textdomain), ML()->ml_nickname)), 'ml_first_section' => array('title' => __('General Settings', $textdomain), 'type' => 'title', 'description' => __('Settings that affect the entire plugin behavior', $textdomain)), 'ml_site' => array('title' => __('Country', $textdomain), 'type' => 'select', 'description' => __('Country where you want to act on MercadoLivre', $textdomain), 'default' => 'MLB', 'options' => ML()->ml_sites), 'ml_auto_export' => array('title' => __('Export Automatically', $textdomain), 'type' => 'checkbox', 'description' => __('Determines whether to create a new product in the store he also will be created on MercadoLivre', $textdomain), 'default' => 'yes'), 'ml_auto_update' => array('title' => __('Update Automatically', $textdomain), 'type' => 'checkbox', 'description' => __('Determines whether to change a product in the store he also will be changed on MercadoLivre', $textdomain), 'default' => 'yes'));
     } else {
         $tutorial = sprintf(__(' Create your application %shere%s. Your \'Redirect URI\' is %s and \'Notifications Callback URL\' is %s', $textdomain), '<a href="http://applications.mercadolibre.com/" target="_blank">', '</a>', admin_url('admin.php'), get_site_url(get_current_blog_id(), 'ml-notifications'));
         $this->form_fields = array('ml_app_id' => array('title' => __('APP ID', $textdomain), 'type' => 'decimal', 'description' => __('Application ID on MercadoLivre.', $textdomain) . $tutorial, 'default' => ''), 'ml_secret_key' => array('title' => __('Secret Key', $textdomain), 'type' => 'text', 'description' => __('Application secret key on MercadoLivre.', $textdomain) . $tutorial, 'default' => ''));
         if (!empty(ML()->ml_app_id) && !empty(ML()->ml_secret_key)) {
             $login_button = array('ml_login_button' => array('title' => __('Login', $textdomain), 'type' => 'link', 'href' => add_query_arg(array('TB_iframe' => 'true', 'width' => '800', 'height' => '550'), ML()->ml_communication->get_login_url()), 'class' => 'button-secondary thickbox', 'custom_attributes' => array('title' => __('MercadoLivre Login', $textdomain)), 'description' => __('Log in to perform operations', $textdomain)));
             $this->form_fields = array_merge($this->form_fields, $login_button);
         }
     }
 }
 /**
  * Notifications handler for ML
  */
 public function process_notifications()
 {
     // Get the json post data
     global $HTTP_RAW_POST_DATA;
     if (empty($HTTP_RAW_POST_DATA)) {
         $HTTP_RAW_POST_DATA = file_get_contents('php://input');
     }
     $notification = json_decode($HTTP_RAW_POST_DATA);
     // End procedure if the json data or specific handler doesn't exist
     if (empty($notification) || !in_array($notification->topic, array('payments', 'items', 'questions', 'orders'))) {
         return;
     }
     // Get the resource data
     $resource = ML()->ml_communication->get_resource($notification->resource);
     // End if resource is not a valid one
     if (empty($resource)) {
         return;
     }
     // Dispatch to proper handler with the resource data
     call_user_func(array($this, $notification->topic . '_handler'), $resource);
 }
		</style>
	</head>
	<body>
		<div class="content">
			<div class="main_content">
				<img src="<?php 
echo ML()->get_plugin_url('assets/img/login-fail.png');
?>
" class="img_login">
				<p><?php 
printf('%s: %s', __('Error', ML()->textdomain), $_GET['error_description']);
?>
</p>
				<img src="<?php 
echo ML()->get_plugin_url('assets/img/logos.png');
?>
" class="img_logo">
			</div>
			<img src="<?php 
echo ML()->get_plugin_url('assets/img/woo-mercadolivre.png');
?>
" class="img_free">
			<div class="footer">
				<p class="free_message"><?php 
printf(__('Click %shere%s to see the premium version of the plugin WooCommerce MercadoLivre.', ML()->textdomain), '<a href="http://www.woocommercemercadolivre.com.br/" target="_blank" class="link_premium">', '</a>');
?>
</p>
			</div>
		</div>
	</body>
</html>
 /**
  * Get shipping modes
  *
  * @ajax( action: "get_ml_shipping_modes" , only_logged: true )
  */
 public function get_shipping_modes()
 {
     check_ajax_referer('ml-shipping-action', 'security');
     if (empty($_GET['category'])) {
         die;
     }
     $return = array();
     foreach (ML()->ml_communication->get_shipping_modes($_GET['category']) as $key => $value) {
         $return[] = array('id' => $key, 'name' => $value);
     }
     wp_send_json($return);
 }
    ?>
" <?php 
    echo $ml_product->can_update_special_fields() ? '' : 'disabled="disabled"';
    ?>
>
					</td>
					<td>
						<input name="ml_shipment_data[<?php 
    echo $i;
    ?>
][cost]" type="text" class="wc_input_price" value="<?php 
    echo isset($costs[$i]['cost']) ? $costs[$i]['cost'] : '';
    ?>
" <?php 
    echo $ml_product->can_update_special_fields() ? '' : 'disabled="disabled"';
    ?>
>
					</td>
				</tr>
			<?php 
}
?>
		</tbody>
	</table>
	<?php 
woocommerce_wp_checkbox(array('id' => 'ml_shipment_local_pickup', 'label' => __('Local pick up', ML()->textdomain), 'description' => __('Check if this product can be taken on site', ML()->textdomain), 'desc_tip' => true, 'value' => isset($ml_product->shipment_local_pickup) && $ml_product->shipment_local_pickup ? 'yes' : 'no', 'custom_attributes' => $ml_product->can_update_special_fields() ? array() : array('disabled' => 'disabled')));
if (!in_array(ML()->ml_site, array('MLA', 'MLB'))) {
    woocommerce_wp_checkbox(array('id' => 'ml_shipment_free_shipping', 'label' => __('Free Shipping', ML()->textdomain), 'description' => __('Check if this product can be delivered for free', ML()->textdomain), 'desc_tip' => true, 'value' => isset($ml_product->shipment_free_shipping) && $ml_product->shipment_free_shipping ? 'yes' : 'no', 'custom_attributes' => $ml_product->can_update_special_fields() ? array() : array('disabled' => 'disabled')));
}
?>
</div>
 /**
  * Save ML product data
  *
  * @action( hook: "woocommerce_process_product_meta_variable" )
  * @action( hook: "woocommerce_process_product_meta_simple" )
  */
 public function save_product_metaboxes_data($post_id)
 {
     $ml_product = new ML_Product($post_id);
     $ml_product->video_id = $_POST['ml_video_id'];
     if (!$ml_product->is_published()) {
         // Fields for a new product
         $ml_product->category_id = $_POST['ml_category_id'];
         $ml_product->listing_type_id = $_POST['ml_listing_type_id'];
         if (!empty($_POST['ml_official_store_id'])) {
             $ml_product->official_store_id = $_POST['ml_official_store_id'];
         }
     }
     if ($ml_product->can_update_special_fields()) {
         // Fields that can only be updated when the product has no sales
         $ml_product->title = sanitize_text_field($_POST['ml_title']);
         //$ml_product->buying_mode  = $_POST['ml_buying_mode'];
         //$ml_product->condition    = $_POST['ml_condition'];
         $ml_product->warranty = $_POST['ml_warranty'];
         if (isset($_POST['ml_shipping_mode']) && $_POST['ml_shipping_mode'] == 'custom') {
             // Custom Shipping
             $costs = array();
             for ($i = 0; $i < 10; $i++) {
                 if (empty($_POST['ml_shipment_data'][$i]['description']) || empty($_POST['ml_shipment_data'][$i]['cost'])) {
                     continue;
                 }
                 $costs[] = array('description' => sanitize_text_field($_POST['ml_shipment_data'][$i]['description']), 'cost' => floatval($_POST['ml_shipment_data'][$i]['cost']));
             }
             $ml_product->shipping_mode = 'custom';
             $ml_product->shipment_costs = $costs;
             $ml_product->shipment_local_pickup = $_POST['ml_shipment_local_pickup'] == 'yes';
             if (isset($_POST['ml_shipment_free_shipping'])) {
                 $ml_product->shipment_free_shipping = $_POST['ml_shipment_free_shipping'] == 'yes';
             } else {
                 $ml_product->shipment_free_shipping = false;
             }
         }
     }
     if (!$ml_product->is_published() || !$ml_product->is_variable()) {
         $ml_product->price = sanitize_text_field($_POST['ml_price']);
     }
     if ($ml_product->is_variable()) {
         // Set variations
         $number_of_variations = count($_POST['ml_variations']['child']);
         $attributes = array_diff(array_keys($_POST['ml_variations']), array('child', 'price'));
         for ($position = 0; $position < $number_of_variations; $position++) {
             $child_product = new ML_Product(intval($_POST['ml_variations']['child'][$position]));
             if (!$child_product->is_published()) {
                 $attribute_combinations = array();
                 foreach ($attributes as $attribute) {
                     if (!empty($_POST['ml_variations'][$attribute][$position])) {
                         $attribute_combinations[] = array('id' => strval($attribute), 'value_id' => strval($_POST['ml_variations'][$attribute][$position]));
                     }
                 }
                 $child_product->attribute_combinations = $attribute_combinations;
             }
             $child_product->price = sanitize_text_field($_POST['ml_variations']['price'][$position]);
         }
     }
     if ($ml_product->is_published() && (ML()->ml_auto_update == 'yes' || isset($_POST['ml_publish']) && $_POST['ml_publish'] == 'yes')) {
         // Verify aditional changes and update
         try {
             // Update the product
             $new_ml_product = $ml_product->update();
             if ($_POST['ml_listing_type_id'] != $new_ml_product->listing_type_id) {
                 $ml_product->update_listing_type($_POST['ml_listing_type_id']);
             }
             if (!empty($ml_product->get_wc_product()->get_post_data()->post_content)) {
                 $ml_product->update_description();
             }
             // Enqueue a message for the user
             ML()->add_notice(sprintf('%s: <a href="%s" target="_blank">%s</a>', __('The product has been updated successfully on MercadoLivre', ML()->textdomain), $new_ml_product->permalink, $new_ml_product->permalink), 'success');
         } catch (ML_Exception $e) {
             ML()->add_notice(sprintf('%s: %s', __('The product could not be updated on MercadoLivre', ML()->textdomain), $e->getMessage()), 'error');
         }
     } else {
         if (!$ml_product->is_published() && (ML()->ml_auto_export == 'yes' || isset($_POST['ml_publish']) && $_POST['ml_publish'] == 'yes')) {
             // Post
             try {
                 // Post the product
                 $new_ml_product = $ml_product->post();
                 // Enqueue a message for the user
                 ML()->add_notice(sprintf('%s: <a href="%s" target="_blank">%s</a>', __('The product was successfully published on MercadoLivre', ML()->textdomain), $new_ml_product->permalink, $new_ml_product->permalink), 'success');
             } catch (ML_Exception $e) {
                 ML()->add_notice(sprintf('%s: %s', __('The product could not be posted on MercadoLivre', ML()->textdomain), $e->getMessage()), 'error');
             }
         }
     }
 }
}
//Modifiable with conditions
woocommerce_wp_select(array('id' => 'ml_listing_type_id', 'label' => __('Listing Type', $textdomain), 'description' => __('Determines how your product will be listed on MercadoLivre', $textdomain), 'desc_tip' => true, 'options' => wp_list_pluck(ML()->ml_communication->get_listing_types(), 'name', 'id'), 'value' => isset($_POST['ml_listing_type_id']) ? $_POST['ml_listing_type_id'] : $ml_product->listing_type_id));
?>
	</div>
	<div class="options_group">
		<?php 
// Modifiable
woocommerce_wp_text_input(array('id' => 'ml_video_id', 'label' => __('Video ID or URL', $textdomain), 'description' => __('Use the URL or the ID of the video on youtube', $textdomain), 'desc_tip' => true, 'value' => isset($_POST['ml_video_id']) ? $_POST['ml_video_id'] : $ml_product->video_id));
//depending on sold_quantity == 0 to modify
woocommerce_wp_textarea_input(array('id' => 'ml_warranty', 'label' => __('Warranty', $textdomain), 'description' => __('Describe the product warranty for buyers on MercadoLivre', $textdomain), 'desc_tip' => true, 'value' => isset($_POST['ml_warranty']) ? $_POST['ml_warranty'] : $ml_product->warranty, 'custom_attributes' => $ml_product->can_update_special_fields() ? array() : array('disabled' => 'disabled')));
?>
	</div>
	<div class="options_group shipment_fields">
		<?php 
woocommerce_wp_select(array('id' => 'ml_shipping_mode', 'label' => __('Shipping', $textdomain), 'description' => __('Determine how your product will be delivered for buyers on MercadoLivre', $textdomain), 'desc_tip' => true, 'options' => ML()->ml_communication->get_shipping_modes(empty($ml_product->category_id) ? null : $ml_product->category_id), 'value' => isset($_POST['ml_shipping_mode']) ? $_POST['ml_shipping_mode'] : $ml_product->shipping_mode, 'custom_attributes' => $ml_product->can_update_special_fields() ? array() : array('disabled' => 'disabled')));
if (!empty($ml_product->shipping_mode) && $ml_product->shipping_mode != 'not_specified') {
    $category_id = $ml_product->category_id;
    include_once "html-{$ml_product->shipping_mode}-shipment.php";
}
?>
	</div>
	<script type="text/javascript">
		jQuery(document).ready(function($) {
			$('#ml_shipping_mode').change(function() {
				// Remove previous shipping mode content
				$('#ml_shipment_content').remove();
				// append image
				$('.shipment_fields').append('<img src="' + "<?php 
echo WooCommerce_MercadoLivre::get_plugin_url('/assets/img/ajax-loader.gif');
?>
				$('#ml_variations_table').block({
					message: null,
					overlayCSS: {
						background: '#fff',
						opacity: 0.6
					}
				});

				//$('#ml_category_id').parent().append('<img src="' + obj.image_url + '" class="check_variation">');
				$.getJSON("<?php 
echo add_query_arg(array('action' => 'add_variation_line', 'security' => wp_create_nonce('ml-variation-line-action'), 'product_id' => isset($_GET['product_id']) ? $_GET['product_id'] : $ml_product->get_wc_product()->id, 'category' => isset($_GET['category']) ? $_GET['category'] : $ml_product->category_id), admin_url('admin-ajax.php'));
?>
", function(variation_line){
					$('#ml_variations_table tbody').append(variation_line);
					$('#ml_variations_table tbody tr:last').find('select[name^="ml_variations"]').select2({placeholder: "<?php 
_e('Not Required', ML()->textdomain);
?>
"});
					$('a.delete_ml_variation_button:last').click(function(){
						$(this).parent().parent().remove();
						return false;
					});
					$('#ml_variations_table').unblock();
				});
				return false;
			});
		});
	</script>
</div>
<!--img class="tip_variation help_tip" data-tip="<?php 
//echo ( ( isset( $variation->tags->required ) && ( $variation->tags->required == 1 ) )? __( 'Required' , ML()->textdomain ) : __( 'Not Required' , ML()->textdomain ) );
" <?php 
    echo isset($saved_variation) && $variation_id == $child_product->get_wc_product()->variation_id ? 'selected' : '';
    ?>
><?php 
    echo '#' . $variation_id;
    ?>
</option>
			<?php 
}
?>
		</select>
	</td>
	<td>
		<input type="text" class="wc_input_price" name="ml_variations[price][]" style="float:none; width: 90px;" value="<?php 
echo isset($saved_variation) && $child_product->is_published() ? $child_product->price : '';
?>
">
	</td>
	<td>
		<?php 
if (!(isset($saved_variation) && $child_product->is_published())) {
    ?>
			<a href="#" class="button-secondary delete_ml_variation_button"><?php 
    _e('Delete', ML()->textdomain);
    ?>
</a>
		<?php 
}
?>
	</td>
</tr>
 /**
  * Atach the ML pictures structure to products body
  *
  * @param  WC_Product   Product to get pictures
  * @param  array        ML product body
  * @param  int          Position of the variation, or -1 for non-variable products
  * @return void
  */
 private function set_pictures_to_body(&$product, &$ml_data, $for_variation = -1)
 {
     $array_id = array();
     $main_image = $product->get_image_id();
     if (!empty($main_image)) {
         $array_id[] = $product->get_image_id();
     }
     $attachments = $product->get_gallery_attachment_ids();
     if (empty($attachments)) {
         $attachments = explode(',', wc_clean($_POST['product_image_gallery']));
     }
     $array_id = array_filter(array_merge($array_id, $attachments));
     foreach ($array_id as $id) {
         $image_meta = ML()->ml_communication->upload_picture($id);
         $img_properties = wp_get_attachment_image_src($id, 'full');
         if (empty($image_meta['image_meta']['ml_id']) && empty($img_properties)) {
             continue;
         }
         if ($for_variation >= 0) {
             $ml_data['variations'][$for_variation]['picture_ids'][] = isset($image_meta['image_meta']['ml_id']) ? $image_meta['image_meta']['ml_id'] : $img_properties[0];
         } else {
             $ml_data['pictures'][] = isset($image_meta['image_meta']['ml_id']) ? array('id' => $image_meta['image_meta']['ml_id']) : array('source' => $img_properties[0]);
         }
     }
 }
		<a href="<?php 
        echo add_query_arg(array('action' => 'change_status_ml_product', 'post_id' => $post_id, 'status' => 'paused', 'security' => wp_create_nonce('ml-change-status-action')), admin_url('admin-ajax.php'));
        ?>
" class="button tips ml_pause ml_button" data-tip="<?php 
        _e('Pause', ML()->textdomain);
        ?>
"></a>
	<?php 
    } elseif ($ml_product->status == 'paused') {
        ?>
		<a href="<?php 
        echo add_query_arg(array('action' => 'change_status_ml_product', 'post_id' => $post_id, 'status' => 'active', 'security' => wp_create_nonce('ml-change-status-action')), admin_url('admin-ajax.php'));
        ?>
" class="button tips ml_activate ml_button" data-tip="<?php 
        _e('Activate', ML()->textdomain);
        ?>
"></a>
	<?php 
    }
}
if (isset($ml_product->permalink)) {
    ?>
	<a href="<?php 
    echo $ml_product->permalink;
    ?>
" target="_blank" class="button tips ml_view ml_button" data-tip="<?php 
    _e('View at ML', ML()->textdomain);
    ?>
"></a>
<?php 
}
 public static function get_subcategories($category)
 {
     if (!is_string($category) || empty($category)) {
         return '';
     }
     $params = array('attributes' => 'children_categories');
     $categories = ML()->ml_communication->get_resource("/categories/{$category}", $params);
     if (empty($categories)) {
         return '';
     }
     return $categories->children_categories;
 }
 public static function answer_question($question_id, $answer_text)
 {
     $params = array('question_id' => $question_id, 'text' => $answer_text);
     return ML()->ml_communication->post_resource('answers', $params);
 }
 /**
  * Executes a generic request to ML
  * 
  * @param  string        Method name
  * @param  string        Resource name
  * @param  Object        Resource body
  * @param  array         Params for the request
  * @throws ML_Exception  In case of bad response
  * @return Object        Data body
  */
 private function execute($method, $resource_name, &$params = array(), &$resource_body = null)
 {
     if (!isset($params['access_token']) && isset(ML()->ml_access_token)) {
         $params['access_token'] = ML()->ml_access_token;
     }
     $method_params = array($resource_name);
     if (!is_null($resource_body)) {
         $method_params[] = $resource_body;
     }
     $method_params[] = $params;
     $data = call_user_func_array(array($this->meli, $method), $method_params);
     if (!isset($data['httpCode'], $data['body']) || $data === false) {
         throw new ML_Exception(__('Empty response from ML', ML()->textdomain));
     }
     if (!in_array($data['httpCode'], array(200, 201, 204))) {
         throw new ML_Exception($data['body']);
     }
     return $data['body'];
 }