WC_GZD_Ekomi

EKomi Implementation - This Class adds eKomi Rating functionality.

Defined (1)

The class is defined in the following location(s).

/includes/class-wc-gzd-ekomi.php  
  1. class WC_GZD_Ekomi { 
  2.  
  3. /** 
  4. * API Version 
  5. * @var string 
  6. */ 
  7. public $version; 
  8. /** 
  9. * Shop ID 
  10. * @var integer 
  11. */ 
  12. public $id; 
  13. /** 
  14. * A user is needed to add the eKomi Reviews 
  15. * @var object 
  16. */ 
  17. public $user; 
  18.  
  19. private $api = null; 
  20.  
  21. /** 
  22. * Creates a new User if the eKomi user does not already exist. Adds hooks to schedules to manage review updates and Email notifications 
  23. */ 
  24. public function __construct() { 
  25.  
  26. $this->version = 'v3'; 
  27. $this->id = $this->shop_id; 
  28.  
  29. if ( $this->is_enabled() ) 
  30. add_action( 'init', array( $this, 'init' ) ); 
  31.  
  32. // Register sections 
  33. add_filter( 'woocommerce_gzd_settings_sections', array( $this, 'register_section' ), 5 ); 
  34. add_filter( 'woocommerce_gzd_get_settings_ekomi', array( $this, 'get_settings' ) ); 
  35.  
  36. public function init() { 
  37.  
  38. if ( ! username_exists( 'ekomi' ) ) { 
  39. wp_create_user( __( 'eKomi Customer', 'woocommerce-germanized' ), wp_generate_password(), 'ekomi@loremipsumdolorom.com' ); 
  40. $this->user = get_user_by( 'email', 'ekomi@loremipsumdolorom.com' ); 
  41. wp_update_user( array( 'ID' => $this->user->ID, 'role' => 'customer' ) ); 
  42.  
  43. // Cronjobs & Hooks 
  44. $this->user = get_user_by( 'email', 'ekomi@loremipsumdolorom.com' ); 
  45.  
  46. $this->api = new Ekomi\Api( $this->interface_id, $this->interface_password, 'GET' ); 
  47.  
  48. add_action( 'woocommerce_gzd_ekomi', array( $this, 'put_products' ), 5 ); 
  49. add_action( 'woocommerce_gzd_ekomi', array( $this, 'send_mails' ), 10 ); 
  50. add_action( 'woocommerce_gzd_ekomi', array( $this, 'get_reviews' ), 15 ); 
  51. add_action( 'woocommerce_order_status_completed', array( $this, 'put_order' ), 0, 1 ); 
  52. add_action( 'wp_footer', array( $this, 'add_scripts' ), 10 ); 
  53.  
  54. /** 
  55. * Gets eKomi Options 
  56. * @param string $key 
  57. * @return mixed 
  58. */ 
  59. public function __get( $key ) { 
  60. return get_option( 'woocommerce_gzd_ekomi_' . $key ); 
  61.  
  62. /** 
  63. * Checks whether a certain eKomi Option isset 
  64. * @param string $key 
  65. * @return boolean 
  66. */ 
  67. public function __isset( $key ) { 
  68. return ( ! get_option( 'woocommerce_gzd_ekomi_' . $key ) ) ? false : true; 
  69.  
  70. /** 
  71. * Checks whether eKomi API is enabled 
  72. * @return boolean 
  73. */ 
  74. public function is_enabled() { 
  75. return ( empty( $this->id ) || empty( $this->interface_id ) || empty( $this->interface_password ) || empty( $this->certificate_link ) || empty( $this->partner_id ) ) ? false : true; 
  76.  
  77. /** 
  78. * Transfers all Shop Products including IDs and Titles to eKomi 
  79. */ 
  80. public function put_products() { 
  81.  
  82. $posts = new WP_Query( array(  
  83. 'post_type' => array( 'product', 'product_variation' ),  
  84. 'post_status' => 'publish',  
  85. 'showposts' => -1,  
  86. 'meta_query' => array( 
  87. array( 
  88. 'key' => '_wc_gzd_ekomi_added',  
  89. 'compare' => 'NOT EXISTS',  
  90. ),  
  91. ) ); 
  92.  
  93. if ( $posts->have_posts() ) { 
  94. while ( $posts->have_posts() ) { 
  95.  
  96. global $post; 
  97. $posts->the_post(); 
  98.  
  99. $product = wc_get_product( $post->ID ); 
  100.  
  101. if ( $product ) { 
  102. $this->put_product( $product ); 
  103.  
  104. /** 
  105. * Transfers a single Product to eKomi 
  106. * @param object $product 
  107. */ 
  108. public function put_product( $product ) { 
  109.  
  110. $ekomi_product = new Ekomi\Request\PutProduct(); 
  111. $ekomi_product->setProductId( $this->get_product_id( $product ) ); 
  112. $ekomi_product->setProductName( $this->get_product_name( $product ) ); 
  113. $ekomi_product->getOther()->addLinks( $this->get_product_link( $product ), 'html' ); 
  114.  
  115. $result = $this->api->exec( apply_filters( 'woocommerce_gzd_ekomi_product', $ekomi_product, $this ) ); 
  116.  
  117. if ( $result && $result->done ) { 
  118. update_post_meta( $this->get_product_id( $product ), '_wc_gzd_ekomi_added', 'yes' ); 
  119.  
  120. return ( $result ? $result->done : false ); 
  121.  
  122. /** 
  123. * Returns the product id. If is variation returns variation id instead. 
  124. *  
  125. * @param object $product  
  126. * @return integer  
  127. */ 
  128. public function get_product_id( $product ) { 
  129. return wc_gzd_get_crud_data( $product, 'id' ); 
  130.  
  131. /** 
  132. * Gets the Product's name based on it's type 
  133. * @param object $product 
  134. * @return string 
  135. */ 
  136. public function get_product_name( $product ) { 
  137. return get_the_title( wc_gzd_get_crud_data( $product, 'id' ) ); 
  138.  
  139. /** 
  140. * Gets the Product's name based on it's type 
  141. * @param object $product 
  142. * @return string 
  143. */ 
  144. public function get_product_link( $product ) { 
  145. return get_permalink( wc_gzd_get_crud_data( $product, 'id' ) ); 
  146.  
  147. /** 
  148. * Transfers a single Order to eKomi 
  149. * @param integer $order_id 
  150. * @return boolean 
  151. */ 
  152. public function put_order( $order_id ) { 
  153.  
  154. $order = wc_get_order( $order_id ); 
  155. $review_link = wc_gzd_get_crud_data( $order, 'ekomi_review_link' ); 
  156.  
  157. if ( empty( $review_link ) ) { 
  158.  
  159. $ekomi_order = new Ekomi\Request\PutOrder(); 
  160.  
  161. $items = $order->get_items(); 
  162. $product_ids = array(); 
  163.  
  164. if ( ! empty( $items ) ) { 
  165. foreach ( $items as $item ) { 
  166. if ( is_object( $item ) && is_callable( array( $item, 'get_product_id' ) ) ) 
  167. $product_ids[] = $item->get_product_id(); 
  168. else 
  169. $product_ids[] = ( empty( $item[ 'variation_id' ] ) ? $item[ 'product_id' ] : $item[ 'variation_id' ] ); 
  170.  
  171. $ekomi_order->setOrderId( $order_id ); 
  172. $ekomi_order->setProductIds( implode( ', ', $product_ids ) ); 
  173. $ekomi_order->setProductIdsUpdateMethod( 'replace' ); 
  174.  
  175. $result = $this->api->exec( $ekomi_order ); 
  176.  
  177. if ( $result->done === 1 && isset( $result->link ) ) { 
  178. update_post_meta( $order_id, '_ekomi_review_link', $result->link ); 
  179. return true; 
  180.  
  181. return false; 
  182.  
  183. /** 
  184. * Send Customer Email notifications if necessary (loops through orders and checks day difference after completion) 
  185. */ 
  186. public function send_mails() { 
  187.  
  188. $order_query = new WP_Query( 
  189. array( 
  190. 'showposts' => -1,  
  191. 'post_type' => 'shop_order',  
  192. 'post_status' => 'wc-completed',  
  193. 'meta_query' => array( 
  194. array( 
  195. 'key' => '_ekomi_review_link',  
  196. 'compare' => 'EXISTS',  
  197. ),  
  198. array( 
  199. 'key' => '_ekomi_review_mail_sent',  
  200. 'compare' => 'NOT EXISTS',  
  201. ),  
  202. ),  
  203. ); 
  204.  
  205. while ( $order_query->have_posts() ) { 
  206.  
  207. global $post; 
  208. $order_query->the_post(); 
  209.  
  210. $order = wc_get_order( $post->ID ); 
  211.  
  212. $diff = WC_germanized()->get_date_diff( date( 'Y-m-d H:i:s', wc_gzd_get_crud_data( $order, 'completed_date' ) ), date( 'Y-m-d H:i:s' ) ); 
  213.  
  214. if ( $diff[ 'd' ] >= (int) get_option( 'woocommerce_gzd_ekomi_day_diff' ) ) { 
  215. if ( $mail = WC_germanized()->emails->get_email_instance_by_id( 'customer_ekomi' ) ) { 
  216. $mail->trigger( wc_gzd_get_crud_data( $order, 'id' ) ); 
  217.  
  218. update_post_meta( wc_gzd_get_crud_data( $order, 'id' ), '_ekomi_review_mail_sent', 1 ); 
  219. update_post_meta( wc_gzd_get_crud_data( $order, 'id' ), '_ekomi_review_link', '' ); 
  220.  
  221. /** 
  222. * Grabs the reviews from eKomi and saves them as review within the Shop 
  223. * @return boolean 
  224. */ 
  225. public function get_reviews() { 
  226.  
  227. $ekomi_feedback = new Ekomi\Request\GetProductFeedback(); 
  228.  
  229. // Check if reviews have already been fetched once. If yes, do only select latest reviews. 
  230. if ( get_option( 'woocommerce_gzd_ekomi_product_reviews_checked', false ) ) { 
  231. $ekomi_feedback->setRange( '1m' ); 
  232.  
  233. $results = $this->api->exec( $ekomi_feedback ); 
  234.  
  235. if ( ! empty( $results ) ) { 
  236.  
  237. foreach( $results as $result ) { 
  238.  
  239. if ( ! $this->review_exists( $result ) && $this->is_product( $result->product_id ) ) { 
  240.  
  241. $product = wc_get_product( $result->product_id ); 
  242.  
  243. $data = array( 
  244. 'comment_post_ID' => wc_gzd_get_crud_data( $product, 'id' ),  
  245. 'comment_author' => $this->user->user_login,  
  246. 'comment_author_email' => $this->user->user_email,  
  247. 'comment_content' => preg_replace( '/\v+|\\\[rn]/', '<br/>', esc_attr( $result->review ) ),  
  248. 'comment_date' => date( 'Y-m-d H:i:s', (int) esc_attr( $result->submitted ) ),  
  249. 'comment_approved' => 1,  
  250. ); 
  251.  
  252. $comment_id = wp_insert_comment( apply_filters( 'woocommerce_gzd_ekomi_review_comment', $data, $result ) ); 
  253.  
  254. if ( $comment_id ) { 
  255.  
  256. add_comment_meta( $comment_id, 'rating', esc_attr( absint( $result->rating ) ), true ); 
  257. add_comment_meta( $comment_id, 'order_id', esc_attr( absint( $result->order_id ) ), true ); 
  258.  
  259. do_action( 'woocommerce_gzd_ekomi_review_comment_inserted', $comment_id, $result ); 
  260.  
  261. // Make sure next time we do not need to fetch all reviews (but only recent reviews). 
  262. update_option( 'woocommerce_gzd_ekomi_product_reviews_checked', 'yes' ); 
  263.  
  264. public function is_product( $id ) { 
  265. return ( get_post_status( $id ) === 'publish' ) ? true : false; 
  266.  
  267. /** 
  268. * Checks if a review already exists by using a eKomi order ID 
  269. * @param string $review_order_id 
  270. * @return boolean 
  271. */ 
  272. public function review_exists( $review ) { 
  273. $comments_query = new WP_Comment_Query; 
  274. $comments = $comments_query->query( array(  
  275. 'meta_key' => 'order_id',  
  276. 'meta_value' => $review->order_id,  
  277. 'post_id' => $review->product_id,  
  278. ) ); 
  279.  
  280. return empty( $comments ) ? false : true; 
  281.  
  282. /** 
  283. * Returns the eKomi Widget html 
  284. * @param array $atts 
  285. * @return string 
  286. */ 
  287. public function get_widget( $atts = array() ) { 
  288. return ( $this->is_enabled() ) ? '<div id="eKomiWidget_default"></div>' : ''; 
  289.  
  290. /** 
  291. * Returns the eKomi Badge html 
  292. * @param array $atts 
  293. * @return string 
  294. */ 
  295. public function get_badge( $atts = array() ) { 
  296. extract( shortcode_atts( array( 'width' => '', ), $atts ) ); 
  297. return ( $this->is_enabled() ) ? '<div id="eKomiSeal_default" style="' . ( $width ? 'width:' . $width . 'px;height:' . $width . 'px;' : '' ) . '"></div>' : ''; 
  298.  
  299. /** 
  300. * Adds necessary scripts to the Footer to enable badge + widget generation 
  301. */ 
  302. public function add_scripts() { 
  303. echo ' 
  304. <script type="text/javascript"> 
  305. (function() { 
  306. eKomiIntegrationConfig = new Array( 
  307. {certId:\'' . get_option( 'woocommerce_gzd_ekomi_partner_id' ) . '\'} 
  308. ); 
  309. if(typeof eKomiIntegrationConfig != "undefined") {for(var eKomiIntegrationLoop=0;eKomiIntegrationLoop<eKomiIntegrationConfig.length;eKomiIntegrationLoop++) { 
  310. var eKomiIntegrationContainer = document.createElement(\'script\'); 
  311. eKomiIntegrationContainer.type = \'text/javascript\'; eKomiIntegrationContainer.defer = true; 
  312. eKomiIntegrationContainer.src = (document.location.protocol==\'https:\'?\'https:\':\'http:\') +"//connect.ekomi.de/integration_1409045085/" + eKomiIntegrationConfig[eKomiIntegrationLoop].certId + ".js"; 
  313. document.getElementsByTagName("head")[0].appendChild(eKomiIntegrationContainer); 
  314. }}else{if(\'console\' in window) { console.error(\'connectEkomiIntegration - Cannot read eKomiIntegrationConfig\'); }} 
  315. })(); 
  316. </script> 
  317. '; 
  318.  
  319. /** 
  320. * Returns eKomi Settings for Admin Interface 
  321. * @return array 
  322. */ 
  323. public function get_settings() { 
  324.  
  325. return array( 
  326.  
  327. array( 'title' => _x( 'Ekomi Integration', 'ekomi', 'woocommerce-germanized' ), 'type' => 'title', 'id' => 'ekomi_options' ),  
  328.  
  329. array( 
  330. 'title' => _x( 'Shop ID', 'ekomi', 'woocommerce-germanized' ),  
  331. 'desc' => _x( 'Insert your Shop ID here.', 'ekomi', 'woocommerce-germanized' ),  
  332. 'desc_tip' => true,  
  333. 'id' => 'woocommerce_gzd_ekomi_shop_id',  
  334. 'type' => 'text',  
  335. 'css' => 'min-width:300px;',  
  336. ),  
  337.  
  338. array( 
  339. 'title' => _x( 'Link to Certificate', 'ekomi', 'woocommerce-germanized' ),  
  340. 'desc' => _x( 'Insert the link to your Certificate', 'ekomi', 'woocommerce-germanized' ),  
  341. 'desc_tip' => true,  
  342. 'id' => 'woocommerce_gzd_ekomi_certificate_link',  
  343. 'type' => 'text',  
  344. 'css' => 'min-width:300px;',  
  345. ),  
  346.  
  347. array( 
  348. 'title' => _x( 'Partner ID', 'ekomi', 'woocommerce-germanized' ),  
  349. 'desc' => _x( 'Insert your Partner ID here (you may find that ID on your certificate website)', 'ekomi', 'woocommerce-germanized' ),  
  350. 'desc_tip' => true,  
  351. 'id' => 'woocommerce_gzd_ekomi_partner_id',  
  352. 'type' => 'text',  
  353. 'css' => 'min-width:300px;',  
  354. ),  
  355.  
  356. array( 
  357. 'title' => _x( 'Interface ID', 'ekomi', 'woocommerce-germanized' ),  
  358. 'desc' => _x( 'Insert your Interface ID here.', 'ekomi', 'woocommerce-germanized' ),  
  359. 'desc_tip' => true,  
  360. 'id' => 'woocommerce_gzd_ekomi_interface_id',  
  361. 'type' => 'text',  
  362. 'css' => 'min-width:300px;',  
  363. ),  
  364.  
  365. array( 
  366. 'title' => _x( 'Interface Password', 'ekomi', 'woocommerce-germanized' ),  
  367. 'desc' => _x( 'Insert your Interface Password here.', 'ekomi', 'woocommerce-germanized' ),  
  368. 'desc_tip' => true,  
  369. 'id' => 'woocommerce_gzd_ekomi_interface_password',  
  370. 'type' => 'text',  
  371. 'css' => 'min-width:300px;',  
  372. ),  
  373.  
  374. array( 
  375. 'title' => _x( 'Days until Email', 'ekomi', 'woocommerce-germanized' ),  
  376. 'desc' => _x( 'Number of days between an order being marked as completed and review email to customer.', 'ekomi', 'woocommerce-germanized' ),  
  377. 'desc_tip' => true,  
  378. 'id' => 'woocommerce_gzd_ekomi_day_diff',  
  379. 'type' => 'number',  
  380. 'custom_attributes' => array( 'min' => 0, 'step' => 1 ),  
  381. 'default' => 7,  
  382. ),  
  383.  
  384. array( 'type' => 'sectionend', 'id' => 'ekomi_options' ),  
  385.  
  386. ); 
  387.  
  388.  
  389. public function register_section( $sections ) { 
  390. $sections[ 'ekomi' ] = _x( 'eKomi Options', 'ekomi', 'woocommerce-germanized' ); 
  391. return $sections; 
  392.