/classes/class.putler-connector.php

  1. <?php 
  2. if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly 
  3.  
  4. if ( ! class_exists( 'Putler_Connector' ) ) { 
  5.  
  6. class Putler_Connector { 
  7.  
  8. private $email_address = ''; 
  9. private $api_token = ''; 
  10. private $version = 1.0; 
  11. private $batch_size = 100; 
  12. public $text_domain; 
  13. private $api_url; 
  14. public $settings_url; 
  15.  
  16. protected static $instance = null; 
  17.  
  18. /** 
  19. * Call this method to get singleton 
  20. * 
  21. * @return Putler_Connector 
  22. */ 
  23. public static function getInstance() { 
  24. if(is_null(self::$instance)) 
  25. self::$instance = new self(); 
  26. return self::$instance; 
  27.  
  28. /** 
  29. * Putler_Connector Constructor. 
  30. * 
  31. * @access public 
  32. * @return void 
  33. */ 
  34. private function __construct() { 
  35.  
  36. $this->text_domain = 'putler_connector'; 
  37. $this->api_url = 'https://api.putler.com/inbound/'; 
  38.  
  39. if ( is_admin() ) { 
  40. $this->settings_url = admin_url('tools.php?page=putler_connector'); 
  41. add_action( 'admin_menu', array(&$this, 'add_admin_menu_page') ); 
  42. add_action ( 'wp_ajax_putler_connector_save', array (&$this, 'validate_and_save_settings') ); 
  43. add_action ( 'wp_ajax_putler_connector_delete', array (&$this, 'delete_tokens') ); 
  44.  
  45. $settings = get_option('putler_connector_settings', null); 
  46. if ( !empty($settings) ) { 
  47. $this->api_token = (!empty($settings['api_token'])) ? $settings['api_token'] : null; 
  48. $this->email_address = (!empty($settings['email_address'])) ? $settings['email_address'] : null;  
  49. if (is_admin() ) { 
  50. add_action ( 'wp_ajax_putler_connector_send_batch', array (&$this, 'send_batch') );  
  51.  
  52. if (empty($this->api_token) || empty($this->email_address) ) { 
  53. // Show a message to add API information 
  54. add_action ( 'admin_notices', array (&$this, 'admin_notices_api_not_configured_yet') ); 
  55.  
  56.  
  57.  
  58. public function add_admin_menu_page() { 
  59. add_management_page( __('Putler Connector', $this->text_domain) , __('Putler Connector', $this->text_domain), 'manage_options', 'putler_connector', array(&$this, 'display_settings_page') ); 
  60.  
  61. public function admin_notices_api_not_configured_yet() { 
  62. echo '<div id="putler_configure_message" class="updated fade"><p>'.sprintf( __('Please <a href="%s">configure your Putler Email Address and API Token</a> to begin transaction sync.', $this->text_domain ), $this->settings_url ).'</p></div>';  
  63.  
  64. public function display_settings_page() { 
  65.  
  66. // Enque JS file 
  67. wp_enqueue_script( 'putler-connector-js', plugins_url( '../assets/putler-connector.js', __FILE__) , array( 'jquery', 'jquery-ui-progressbar' ), $this->version, true ); 
  68.  
  69. $putler_params = array ('image_url' => plugins_url('../assets/images/', __FILE__) ); 
  70. wp_localize_script( 'putler-connector-js', 'putler_params', $putler_params ); 
  71.  
  72. // Enque CSS file 
  73. wp_enqueue_style( 'putler-connector-css', plugins_url( '../assets/putler-connector.css', __FILE__) , array( ) );  
  74.  
  75. // Now show form 
  76. ?> 
  77. <div class="wrap" id="putler_connector_settings_page"> 
  78. <h2><?php _e("Putler Connector Settings", $this->text_domain); ?></h2> 
  79. <div id="putler_message" class="updated fade" style="display:none;"><p></p></div> 
  80. <form id="putler_connector_settings_form" action="" method="post"> 
  81. <div id="putler_connector_settings"> 
  82. <label for="putler_email_address"><?php _e("Your Putler Email Address", $this->text_domain); ?></label> 
  83. <input id="putler_email_address" placeholder="test@test.com" type="text" size="30" style="margin-left:10px;" name="putler_email_address" value="<?php echo $this->email_address; ?>"/> 
  84.  
  85. <br/><br/> 
  86.  
  87. <?php if ( !empty($this->api_token) ) { ?> 
  88.  
  89. <div> 
  90. <label for="putler_api_token"><?php _e("Putler API Tokens", $this->text_domain); ?></label> 
  91.  
  92. <br/><br/> 
  93.  
  94. <?php  
  95.  
  96. $api_tokens = explode(", ", $this->api_token); 
  97.  
  98. echo '<div id="api_token_list">  
  99. <div style="margin-top:7px;"> <input type="checkbox" name="all" value="all"> '.__("Select All", $this->text_domain).' </div>'; 
  100.  
  101. foreach ($api_tokens as $api_token) { 
  102. echo '<div class="api_token" style="margin-top:7px;cursor:pointer;"> <input type="checkbox" name="'.trim($api_token).'" value="'.trim($api_token).'"> '.trim($api_token).'  
  103. <span id="delete_'.trim($api_token).'" title="Delete" class="dashicons dashicons-trash" style="color:#FF5B5E !important;display:none;font-size:17px;margin-top:1px;"></span> 
  104. </div>'; 
  105. echo '</div>'; 
  106. ?> 
  107. <br/> 
  108.  
  109. <a id='add_token_link' style="cursor:pointer;"><?php _e("Add a new token?", $this->text_domain); ?></a> 
  110.  
  111. <div id='add_token' style="width:50%;padding-left:20px;padding-top:5px;margin:auto 0;display:none;"> 
  112. <input id="add_api_token" placeholder="New Token1, New Token2, ..." type="text" size="25" name="add_api_token" /> 
  113. <!-- <span id="add_token_btn" title="Add" class="dashicons dashicons-plus" style="color:#12B41F !important;font-size: 23px;margin-top:5px;cursor:pointer;"></span> --> 
  114. </div> 
  115. </div> 
  116.  
  117. <?php } else { ?> 
  118.  
  119. <label for="add_api_token"><?php _e("Your Putler API Token", $this->text_domain); ?></label> 
  120. <input id="add_api_token" placeholder="New Token1, New Token2, ..." type="text" size="30" name="add_api_token" style="margin-left:36px;" /> 
  121.  
  122. <br/> 
  123.  
  124. <?php } ?> 
  125.  
  126. <br/>  
  127.  
  128. <input type="submit" id="api_token_sync" class="button-primary" value="<?php _e("Save & Sync", $this->text_domain); ?>"> 
  129. <div id="putler_connector_progressbar" class="putler_connector_progressbar" style="display:none;margin-top:10px;width:45%;"><div id="putler_connector_progress_label" ><?php _e('Saving Settings...', $this->text_domain );?></div></div> 
  130.  
  131.  
  132.  
  133. <!-- <tr><th> </th> 
  134. <td><input type="submit" id="putler_connector_submit" class="button-primary" value="<?php _e("Save & Send Past Orders to Putler", $this->text_domain); ?>"><br/><br/> 
  135. </td> 
  136. </tr> 
  137. <tr><th> </th> 
  138. <td></td> 
  139. </tr> --> 
  140. </div> 
  141. </form> 
  142. </div> 
  143. <?php 
  144.  
  145. public function validate_and_save_settings () { 
  146. $response = array( 'status' => 'ERR', 'message' => __('Invalid Token or Email Address. Please try again.', $this->text_domain) ); 
  147.  
  148. if ( !empty($_POST['putler_api_tokens']) && !empty($_POST['putler_email_address']) ) { 
  149. $token = trim($_POST['putler_api_tokens']); 
  150. $token_selected = trim($_POST['putler_api_tokens_sync']); 
  151. $email = trim($_POST['putler_email_address']); 
  152.  
  153. $result = $this->validate_api_info( $token, $email ); 
  154. if ( $result === true ) { 
  155.  
  156. $token_unique = implode(", ", array_map('trim', (array_unique(array_filter(explode(", ", trim($_POST['putler_api_tokens']))))))); // to save only unique token keys 
  157.  
  158.  
  159. $this->email_address = $settings['email_address'] = $email; 
  160. $this->api_token = $settings['api_token'] = $token_unique; 
  161.  
  162. // Save settings 
  163. update_option( 'putler_connector_settings', $settings ); 
  164.  
  165. // Get total orders 
  166. $order_count = (!empty($token_selected)) ? apply_filters( 'putler_connector_get_order_count', 0 ) : 0; 
  167.  
  168. // Send response 
  169. $response = array( 'status' => 'OK', 'message' => '', 'order_count' => $order_count ) ; 
  170. } else if ( is_wp_error( $result ) ) { 
  171. $response['message'] = $result->get_error_message(); 
  172.  
  173. $err_data = $result->get_error_data(); 
  174.  
  175. if (!empty($err_data)) { 
  176. $response['message'] .= ". '". $err_data ."' token(s) are unauthorized."; 
  177.  
  178. die( json_encode( $response )); 
  179.  
  180. // Function to delete tokens 
  181. public function delete_tokens() { 
  182.  
  183. $settings = get_option('putler_connector_settings', null); 
  184. $settings['api_token'] = (!empty($_POST['putler_api_tokens'])) ? trim($_POST['putler_api_tokens']) : ''; 
  185. update_option( 'putler_connector_settings', $settings ); // Save settings 
  186.  
  187.  
  188. private function validate_api_info( $token, $email ) { 
  189. // Validate with API server 
  190.  
  191. $result = wp_remote_head( $this->api_url,  
  192. array( 'headers' => array( 
  193. 'Authorization' => 'Basic ' . base64_encode( $email . ':' . $token ),  
  194. 'User-Agent' => 'Putler Connector/'.$this->version 
  195. ); 
  196.  
  197.  
  198.  
  199. if (is_wp_error( $result )) { 
  200. return $result; 
  201. else if ( !empty($result['response']['code']) && $result['response']['code'] == 200 ) { 
  202. return true; 
  203. } else { 
  204. if ( !empty($result['response']['code']) && !empty($result['response']['message'])) { 
  205. $unauthorized_tokens = (!empty($result['headers']['x-putler-invalid-token'])) ? $result['headers']['x-putler-invalid-token'] : $token; 
  206.  
  207. if( !empty($unauthorized_tokens) ) { 
  208. $tokens = explode(", ", $unauthorized_tokens); 
  209.  
  210. $temp = explode(", ", $_POST['putler_api_tokens']); 
  211.  
  212. foreach( $tokens as $key => &$token ) {  
  213. if(substr($token, 0, 4) != 'web-') { 
  214.  
  215. $index = array_search($token, $temp); 
  216. $token = 'web-'.$token; 
  217. if( $index !== false ) { 
  218. $temp[$index] = $token; 
  219. } else{ 
  220. unset($tokens[$key]); 
  221.  
  222. $_POST['putler_api_tokens'] = implode(", ", $temp); 
  223.  
  224. if( !empty($tokens) ) { 
  225. return $this->validate_api_info( implode(", ", $tokens), $email );  
  226. } else { 
  227. return new WP_Error( $result['response']['code'], $result['response']['message'], $unauthorized_tokens ); 
  228. }  
  229. return false; 
  230.  
  231. public function post_order ( $args ) { 
  232.  
  233. if( !empty($args['sub_id']) ) { // for handling sub update related actions 
  234. $params = apply_filters( 'putler_connector_sub_updated', $args ); 
  235. } else { 
  236.  
  237. $params = array(); 
  238.  
  239. $params ['order_id'] = $args['order_id']; 
  240.  
  241. //For handling manual refunds 
  242. if( !empty($args['refund_id']) ) { 
  243. $params ['order_id'] = $args['refund_id']; 
  244. $params ['refund_parent_id'] = $args['order_id']; 
  245.  
  246. $params = apply_filters( 'putler_connector_get_orders', $params ); 
  247.  
  248. $post_result = $this->post_orders_to_putler( $params['data'] ); 
  249.  
  250. public function send_batch ( ) { 
  251. $response = array( 'status' => 'OK', 'message' => '', 'results' => array() ) ;  
  252.  
  253. $this->api_token = (!empty($_POST['putler_api_tokens_sync'])) ? $_POST['putler_api_tokens_sync'] : ''; 
  254.  
  255. $params = (!empty($_POST['params'])) ? json_decode( stripslashes($_POST['params']), true) : array(); 
  256. $params['limit'] = $this->batch_size; 
  257.  
  258. //Getting the data from ecommerce plugins 
  259. $params = apply_filters( 'putler_connector_get_orders', $params ); 
  260.  
  261. // Check if all orders are received... 
  262. foreach ( (array) $params as $connector => $orders ) { 
  263.  
  264. // Send one batch to the server 
  265. if (!empty($orders['data']) && is_array($orders['data']) && count($orders['data']) > 0) { 
  266.  
  267. $count += $orders['count']; 
  268. $start_limit = $this->batch_size + $orders['last_start_limit']; 
  269.  
  270. $post_result = $this->post_orders_to_putler( $orders['data'] ); 
  271.  
  272. $error_response = array(); 
  273.  
  274. if (is_wp_error( $post_result ) ) { 
  275. $error_response[ $connector ]['status'] = 'ERR';  
  276. $error_response[ $connector ]['message'] = $post_result->get_error_message(); 
  277. $response = array( 'status' => 'ERR', 'message' => '', 'results' => $error_response );  
  278. } else { 
  279. $response['results'][ $connector ] = array('status' => 'OK', 'start_limit' => $start_limit ); 
  280.  
  281. if ( $count < $this->batch_size ) { 
  282. $all_done = true; 
  283. } else { 
  284. $all_done = false; 
  285. break; 
  286.  
  287. if ($all_done === true) { 
  288. $response = array( 'status' => 'ALL_DONE', 'message' => '' ) ;  
  289. } else { 
  290. $response['sent_count'] = $count; 
  291.  
  292. die( json_encode( $response )); 
  293.  
  294. public function post_orders_to_putler ( &$orders ) { 
  295.  
  296. if (empty($orders)) { 
  297. return true; 
  298.  
  299. $oid = ob_start(); 
  300. $fp = fopen('php://output', 'a+'); 
  301. foreach ( (array) $orders as $index => $row) { 
  302. if ($index == 0) { 
  303. fputcsv($fp, array_keys($row));  
  304. fputcsv($fp, $row); 
  305. fclose($fp); 
  306. $csv_data = ob_get_clean(); 
  307. if( ob_get_clean() > 0 ) { ob_end_clean(); } 
  308.  
  309. $result = wp_remote_post( $this->api_url,  
  310. array('headers' => array( 
  311. 'Content-Type' => 'text/csv',  
  312. 'Authorization' => 'Basic ' . base64_encode( $this->email_address . ':' . $this->api_token ),  
  313. 'User-Agent' => 'Putler Connector/'.$this->version 
  314. ),  
  315. 'timeout' => 120,  
  316. 'body' => $csv_data 
  317. ); 
  318.  
  319. if (is_wp_error( $result )) { 
  320. return $result; 
  321. } else { 
  322. $server_response_default = array('ACK' => 'Failure', 'MESSAGE' => __('Unknown Response', $this->text_domain) ); 
  323. $server_response = json_decode( $result['body'], true); 
  324. $server_response = array_merge( $server_response_default, $server_response ); 
  325. $server_response_code = $result['response']['code']; 
  326.  
  327. if ($server_response_code == 200 && $server_response['ACK'] == "Success") { 
  328. return true; 
  329. return new WP_Error( $server_response_code, $server_response['MESSAGE']); 
.