PageRenderTime 52ms CodeModel.GetById 17ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/yotpo/yotpo.php

https://github.com/DaveBenNoah/PrestaShop-modules
PHP | 801 lines | 741 code | 57 blank | 3 comment | 98 complexity | 573d7abc305004bf162f4e714d0e0d72 MD5 | raw file
  1<?php
  2
  3if (!defined('_PS_VERSION_'))
  4	exit;
  5
  6class Yotpo extends Module
  7{
  8	const PAST_ORDERS_DAYS_BACK = 90;
  9	const PAST_ORDERS_LIMIT = 10000;
 10	const BULK_SIZE = 1000;	
 11	private $_html = '';
 12	private $_httpClient = null;
 13	private $_yotpo_module_path = '';
 14	private static $_MAP_STATUS = null;
 15
 16	private $_required_files = array('/YotpoHttpClient.php', '/YotpoSnippetCache.php'); 
 17	
 18	private $_is_smarty_product_vars_assigned = false;
 19	
 20	public function __construct()
 21	{
 22		$version_mask = explode('.', _PS_VERSION_, 3);
 23		$version_test = $version_mask[0] > 0 && $version_mask[1] > 4;
 24		$this->name = 'yotpo';
 25		$this->tab = $version_test ? 'advertising_marketing' : 'Reviews';
 26		$this->version = '1.4';
 27		if ($version_test)
 28			$this->author = 'Yotpo';
 29		$this->need_instance = 1;
 30
 31		parent::__construct();
 32		 
 33		$this->displayName = $this->l('Yotpo - Social Reviews and Testimonials');
 34		$this->description = $this->l('The #1 reviews add-on for SMBs. Generate beautiful, trusted reviews for your shop.');
 35
 36		$this->_yotpo_module_path = _PS_MODULE_DIR_.$this->name;
 37
 38		if (!Configuration::get('yotpo_app_key'))
 39			$this->warning = $this->l('Set your API key in order the Yotpo module to work correctly');	
 40
 41		if (!defined('_PS_BASE_URL_'))
 42			define('_PS_BASE_URL_', 'http://'.(isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']));
 43		if(file_exists($this->_yotpo_module_path . '/YotpoSnippetCache.php')) {
 44			include_once($this->_yotpo_module_path.'/YotpoSnippetCache.php');	
 45		}	
 46			    /* Backward compatibility */
 47		if (version_compare(_PS_VERSION_, '1.5') < 0) {
 48    		require(_PS_MODULE_DIR_.$this->name.'/backward_compatibility/backward.php');
 49    	}				
 50	}
 51
 52	public function getAcceptedMapStatuses()
 53	{
 54		if(method_exists('Tools', "unSerialize")) {
 55			$selected_statuses = Tools::unSerialize(Configuration::get('yotpo_map_status'));	
 56		}
 57		else {
 58			$selected_statuses = @unserialize(Configuration::get('yotpo_map_status'));	
 59		}
 60		
 61		if(!is_null($selected_statuses) && !empty($selected_statuses)) {
 62			return $selected_statuses;
 63		}
 64		if (is_null(self::$_MAP_STATUS))
 65		{
 66			self::$_MAP_STATUS = array();
 67			$statuses = array('PS_OS_WS_PAYMENT', 'PS_OS_PAYMENT', 'PS_OS_DELIVERED', 'PS_OS_SHIPPING');
 68			foreach ($statuses as $status)
 69			{
 70				if (defined($status))
 71					self::$_MAP_STATUS[] = (int)Configuration::get($status);
 72				elseif (defined('_'.$status.'_')) 
 73					self::$_MAP_STATUS[] = constant('_'.$status.'_');
 74			}
 75		}
 76		return self::$_MAP_STATUS;
 77	}
 78
 79	public function install()
 80	{
 81		if (!function_exists('curl_init'))
 82			$this->setError($this->l('Yotpo needs the PHP Curl extension, please ask your hosting provider to enable it prior to install this module.'));
 83
 84		
 85		if(version_compare(_PS_VERSION_, '1.3') < 0)
 86			$this->setError($this->l('Minimum version required for Yotpo module is Prestashop 1.3'));
 87
 88		foreach ($this->_required_files as $file)
 89			if(!file_exists($this->_yotpo_module_path .$file))
 90				$this->setError($this->l('Can\'t include file '.$this->_yotpo_module_path .$file));
 91
 92		if ((is_array($this->_errors) && count($this->_errors) > 0) || parent::install() == false 	||
 93			!$this->registerHook('productfooter') 	|| !$this->registerHook('postUpdateOrderStatus')||
 94			!$this->registerHook('extraLeft') 		|| !$this->registerHook('extraRight') 			||
 95			!$this->registerHook('productTab') 		|| !$this->registerHook('productTabContent') 	|| 
 96			!$this->registerHook('header')			|| !$this->registerHook('orderConfirmation')	|| !YotpoSnippetCache::createDB()) 
 97			return false;
 98
 99		/* Default language: English; Default widget location: Product page Footer; Default widget tab name: "Reviews" 
100		 * Default bottom line location: product page left column Default bottom line enabled : true*/	
101		
102		Configuration::updateValue('yotpo_language', 'en', false);
103		Configuration::updateValue('yotpo_widget_location', 'footer', false);
104		Configuration::updateValue('yotpo_widget_tab_name', 'Reviews', false);
105		Configuration::updateValue('yotpo_bottom_line_enabled', 1, false);
106		Configuration::updateValue('yotpo_bottom_line_location', 'left_column', false);
107		Configuration::updateValue('yotpo_widget_language_code', 'en', false);
108		Configuration::updateValue('yotpo_language_as_site', 0, false);
109		Configuration::updateValue('yotpo_rich_snippets', 1, false);
110		
111		Configuration::updateValue('yotpo_rich_snippet_cache_created', 1, true);
112		
113		Configuration::updateValue('yotpo_map_status', serialize($this->getAcceptedMapStatuses()), false);
114		return true;
115	}
116
117	public function hookheader()
118	{
119		$smarty = $this->context->smarty;
120		$smarty->assign(array('yotpoAppkey' => Configuration::get('yotpo_app_key'), 
121							  'yotpoDomain' => $this->getShopDomain(),
122							  'yotpoLanguage' => $this->getLanguage()));
123		
124		if(isset($this->context->controller)) {
125			$this->context->controller->addJS(($this->_path).'/js/headerScript.js');
126		}
127		else {
128			return '<script type="text/javascript" src="'.$this->_path.'/js/headerScript.js"></script>';				
129		}
130	}
131
132	public function hookproductfooter($params)
133	{
134		$widgetLocation = Configuration::get('yotpo_widget_location');
135		return ($widgetLocation == 'footer' || $widgetLocation == 'other') ? $this->showWidget($params['product']) : null;
136	}
137
138	public function hookpostUpdateOrderStatus($params)
139	{
140		if (in_array($params['newOrderStatus']->id, $this->getAcceptedMapStatuses()))
141		{
142			$data = $this->prepareMapData($params);
143			if (Configuration::get('yotpo_app_key') != '' && Configuration::get('yotpo_oauth_token') != '' && !is_null($data))
144				$this->httpClient()->makeMapRequest($data, Configuration::get('yotpo_app_key'), Configuration::get('yotpo_oauth_token'));				
145		}
146	}
147
148	public function hookProductTab()
149	{
150		if ($this->parseProductId() != null && Configuration::get('yotpo_widget_location') == 'tab') {
151			if (version_compare(_PS_VERSION_, '1.6') >= 0) {
152				return '<h3 class="page-product-heading"><a href="#idTab-yotpo">'.Configuration::get('yotpo_widget_tab_name').'</a></h3>';	
153			}
154			return '<li><a href="#idTab-yotpo">'.Configuration::get('yotpo_widget_tab_name').'</a></li>';
155		}
156		return null;
157	}
158
159	public function hookProductTabContent()
160	{
161		$product = $this->getPageProduct(null);
162		if ($product != null && Configuration::get('yotpo_widget_location') == 'tab')
163			return '<div id="idTab-yotpo">'.$this->showWidget($product).'</div>';
164	}
165
166	public function hookextraLeft()
167	{
168		return $this->showBottomLine('left_column');	
169	}
170	
171	public function hookextraRight()
172	{		
173		return $this->showBottomLine('right_column');	
174	}
175		
176	public function hookorderConfirmation($params)
177	{
178		$app_key = Configuration::get('yotpo_app_key');
179		$order_id = !empty($params['objOrder']) && !empty($params['objOrder']->id) ? $params['objOrder']->id : null;
180		$order_amount = !empty($params['total_to_pay']) ? $params['total_to_pay'] : '';
181		$order_currency = !empty($params['currencyObj']) && !empty($params['currencyObj']->iso_code) ? $params['currencyObj']->iso_code : '';
182
183		if(!empty($app_key) && !is_null($order_id)) {
184			$smarty = $this->context->smarty;
185			$conversion_params = "app_key="      .$app_key.
186                 				 "&order_id="    .$order_id.
187                 				 "&order_amount=".$order_amount.
188                 				 "&order_currency="  .$order_currency;
189			$conversion_url = "https://api.yotpo.com/conversion_tracking.gif?$conversion_params";
190			$smarty->assign('yotpoConversionUrl', $conversion_url);
191			return $this->display(__FILE__,'views/templates/front/conversionImage.tpl');
192		}
193	}
194
195	public function uninstall()
196	{
197		Configuration::deleteByName('yotpo_app_key');
198		Configuration::deleteByName('yotpo_oauth_token');
199		Configuration::deleteByName('yotpo_widget_location');
200		Configuration::deleteByName('yotpo_widget_tab_name');
201		Configuration::deleteByName('yotpo_past_orders');
202	    Configuration::deleteByName('yotpo_language');
203    	Configuration::deleteByName('yotpo_language_as_site');
204    	Configuration::deleteByName('yotpo_rich_snippets');
205    	Configuration::deleteByName('yotpo_rich_snippet_cache_created');
206    	Configuration::deleteByName('yotpo_map_status');
207    	YotpoSnippetCache::dropDB();    	
208		return parent::uninstall();
209	}
210	
211	public function getContent()
212	{
213		if (isset($this->context->controller))
214			$this->context->controller->addCSS($this->_path.'/css/form.css', 'all');		
215		else
216			echo '<link rel="stylesheet" type="text/css" href="../modules/yotpo/css/form.css" />';	
217
218		$force_settings = $this->processRegistrationForm() == 'b2c';
219		$this->processSettingsForm();
220		$this->displayForm($force_settings);
221
222		return '<img src="http://www.prestashop.com/modules/yotpo.png?url_site='.Tools::safeOutput($_SERVER['SERVER_NAME']).'" alt="" style="display: none;" />'.$this->_html;
223	}
224
225	private function getProductImageUrl($id_product)
226	{
227		$id_image = Product::getCover($id_product);
228		if (count($id_image) > 0)
229		{
230			$image = new Image($id_image['id_image']);
231			return method_exists($image, 'getExistingImgPath') ? _PS_BASE_URL_._THEME_PROD_DIR_.$image->getExistingImgPath().".jpg" : $this->getExistingImgPath($image);
232		}
233		return null;
234	}
235
236	private function getExistingImgPath($image)
237	{
238		if (!$image->id)
239			return null;
240		if (file_exists(_PS_PROD_IMG_DIR_.(int)$image->id_product.'-'.(int)$image->id.'.jpg'))
241			return _PS_BASE_URL_._THEME_PROD_DIR_.(int)$image->id_product.'-'.(int)$image->id.'.'.'jpg';	
242	}
243
244	private function getProductLink($product_id)
245	{
246		$link = $this->context->link;
247		if (isset($link) && method_exists($link, 'getProductLink'))
248			return $link->getProductLink((int)$product_id);
249		else
250		{
251			$link = new Link();
252			return $link->getProductLink((int)$product_id);	
253		}
254	}
255
256	private function getDescritpion($product,$lang_id)
257	{
258		if (!empty($product['description_short']))
259			return strip_tags($product['description_short']);
260
261		$full_product = new Product((int)$product['id_product'], false, (int)$lang_id);
262		return strip_tags($full_product->description);
263	}
264
265	private function setError($error)
266	{
267		if (!$this->_errors)
268			$this->_errors = array();
269		$this->_errors[] = $error;
270	}
271
272	private function httpClient()
273	{
274		if (is_null($this->_httpClient))
275		{
276			include_once($this->_yotpo_module_path.'/YotpoHttpClient.php');
277			$this->_httpClient = new YotpoHttpClient($this->name);
278		}
279		return $this->_httpClient;
280	}
281
282	private function parseProductId()
283	{
284		$product_id = (int)Tools::getValue('id_product');
285
286		if (!empty($product_id))
287			return (int)$product_id;
288		else
289		{
290			parse_str($_SERVER['QUERY_STRING'], $query);
291			if (!empty($query['id_product']))
292				return (int)$query['id_product'];
293		}
294		return null;
295	}
296
297	private function showWidget($product)
298	{
299		$rich_snippets = '';
300		if(Configuration::get('yotpo_rich_snippets') == true) {
301			$rich_snippets .= $this->getRichSnippet($this->parseProductId());
302		}
303		$smarty = $this->context->smarty;		
304		$smarty->assign('richSnippetsCode', $rich_snippets);
305		
306		$this->assignProductVars($product);
307		if (Configuration::get('yotpo_widget_location') != 'other')
308			return $this->display(__FILE__, 'views/templates/front/widgetDiv.tpl');
309
310		return null;
311	}
312
313	private function assignProductVars($product = null)
314	{
315		if(!$this->_is_smarty_product_vars_assigned)
316		{
317			if (is_null($product))
318			$product = $this->getPageProduct();
319			$this->_is_smarty_product_vars_assigned = true;
320
321			$smarty = $this->context->smarty;
322			$smarty->assign(array('yotpoProductId' => (int)$product->id,
323			'yotpoProductName' => strip_tags($product->name),
324			'yotpoProductDescription' => strip_tags($product->description),
325			'yotpoProductModel' => $this->getProductModel($product),
326			'yotpoProductImageUrl' => $this->getProductImageUrl($product->id),
327			'yotpoProductBreadCrumbs' => $this->getBreadCrumbs($product),
328			'yotpoProductLink' => $this->getProductLink((int)$product->id),
329			'yotpoLanguage' => $this->getLanguage()));
330		}
331	}
332	
333	private function showBottomLine($bottom_line_location)
334	{		
335		if(Configuration::get('yotpo_bottom_line_enabled') == true && Configuration::get('yotpo_bottom_line_location') === $bottom_line_location
336			&& Configuration::get('yotpo_bottom_line_location') != 'other')
337		{
338			$this->assignProductVars(null);
339			
340			return $this->display(__FILE__,'views/templates/front/bottomLineDiv.tpl');
341		}
342	}
343	
344	private function getShopDomain()
345	{
346		return method_exists('Tools', 'getShopDomain') ? Tools::getShopDomain(false,false) : str_replace('www.', '', $_SERVER['HTTP_HOST']);
347	}
348
349	private function processRegistrationForm()
350	{
351		if (Tools::isSubmit('yotpo_register'))
352		{
353			$email = Tools::getValue('yotpo_user_email');
354			$name = Tools::getValue('yotpo_user_name');
355			$password = Tools::getValue('yotpo_user_password');
356			$confirm = Tools::getValue('yotpo_user_confirm_password');
357			if ($email === false || $email === '')
358				return $this->prepareError($this->l('Provide valid email address'));	
359			if (Tools::strlen($password) < 6 || Tools::strlen($password) > 128)
360				return $this->prepareError($this->l('Password must be at least 6 characters'));	
361			if ($password != $confirm)
362				return $this->prepareError($this->l('Passwords are not identical'));	
363			if ($name === false || $name === '')
364				return $this->prepareError($this->l('Name is missing'));	
365
366				
367				
368			$is_mail_valid = $this->httpClient()->checkeMailAvailability($email);
369			if ($is_mail_valid['status_code'] == 200 && 
370			  	($is_mail_valid['json'] == true && $is_mail_valid['response']['available'] == true) || 
371			  	($is_mail_valid['json'] == false && preg_match("/available[\W]*(true)/",$is_mail_valid['response']) == 1))
372			{
373				$response = $this->httpClient()->check_if_b2c_user($email);
374                if (empty($response['response']['data']))
375                {
376					$registerResponse = $this->httpClient()->register($email, $name, $password, _PS_BASE_URL_);
377					
378					if ($registerResponse['status_code'] == 200)
379					{
380						$app_key ='';
381						$secret = '';
382						if ($registerResponse['json'] == true)
383							$app_key = $registerResponse['response']['app_key'];
384						else 
385						{
386							preg_match("/app_key[\W]*[\"'](.*?)[\"']/",$registerResponse['response'], $matches);
387							$app_key = $matches[1];
388							unset($matches);
389						}
390						$secret ='';
391						if ($registerResponse['json'] == true)
392							$secret = $registerResponse['response']['secret'];
393						else 
394						{
395							preg_match("/secret[\W]*[\"'](.*?)[\"']/",$registerResponse['response'], $matches);
396							$secret = $matches[1];
397						}					
398						$accountPlatformResponse = $this->httpClient()->createAcountPlatform($app_key, $secret, _PS_BASE_URL_);
399						if ($accountPlatformResponse['status_code'] == 200)
400						{
401							Configuration::updateValue('yotpo_app_key', $app_key, false);
402							Configuration::updateValue('yotpo_oauth_token', $secret, false);
403							return $this->prepareSuccess($this->l('Account successfully created'));
404						}
405						else
406							return $this->prepareError($accountPlatformResponse['status_message']);	
407					}
408					else
409						return $this->prepareError($registerResponse['status_message']);
410                }
411                else
412                {
413                    $id = $response['response']['data']['id'];
414                    $data = array(
415                        'password'=> $password,
416                        'display_name'=> $name,
417                        'account' => array(
418                            'url' => _PS_BASE_URL_,
419                            'custom_platform_name'=>null,
420                            'install_step'=>8,
421                            'account_platform' => array(
422                                'shop_domain'=> _PS_BASE_URL_,
423                                'platform_type_id'=>8,
424                            )
425                        )
426                    );
427                    $this->httpClient()->create_user_migration($id,$data);
428                    $this->httpClient()->notify_user_migration($id);
429                    $this->prepareError($this->l('We have sent you a confirmation email. Please check and click on the link to get your app key and secret token to fill out below.'));
430                    return 'b2c';
431                }
432			}
433			else
434				return $is_mail_valid['status_code'] == 200 ? $this->prepareError($this->l('This e-mail address is already taken.')) : $this->prepareError();
435		}
436	}
437
438	private function processSettingsForm()
439	{
440		if (Tools::isSubmit('yotpo_settings'))
441		{
442			$api_key = Tools::getValue('yotpo_app_key');
443			$secret_token = Tools::getValue('yotpo_oauth_token');
444			$location = Tools::getValue('yotpo_widget_location');
445			$tabName = Tools::getValue('yotpo_widget_tab_name');
446			$bottomLineEnabled = Tools::getValue('yotpo_bottom_line_enabled');
447			$bottomLineLocation = Tools::getValue('yotpo_bottom_line_location');
448		    $language_as_site = Tools::getValue('yotpo_language_as_site');
449		    $widget_language_code = Tools::getValue('yotpo_widget_language_code');
450			$rich_snippet = Tools::getValue('yotpo_rich_snippets');
451			$map_statuses = Tools::getValue('yotpo_map_status');  			
452			if ($api_key == '')
453				return $this->prepareError($this->l('Api key is missing'));	
454			if ($secret_token == '')
455				return $this->prepareError($this->l('Please fill out the secret token'));
456			Configuration::updateValue('yotpo_app_key', Tools::getValue('yotpo_app_key'), false);
457			Configuration::updateValue('yotpo_oauth_token', Tools::getValue('yotpo_oauth_token'), false);
458			Configuration::updateValue('yotpo_widget_location', $location, false);
459			Configuration::updateValue('yotpo_widget_tab_name', $tabName, false);
460			Configuration::updateValue('yotpo_bottom_line_enabled', $bottomLineEnabled, false);
461			Configuration::updateValue('yotpo_bottom_line_location', $bottomLineLocation, false);	
462	        Configuration::updateValue('yotpo_language', $widget_language_code, false);
463            Configuration::updateValue('yotpo_language_as_site', $language_as_site, false); 		
464            Configuration::updateValue('yotpo_rich_snippets', $rich_snippet, false);
465            Configuration::updateValue('yotpo_map_status', serialize($map_statuses), false);
466			return $this->prepareSuccess();
467		}
468		elseif (Tools::isSubmit('yotpo_past_orders'))
469		{
470			$api_key = Tools::getValue('yotpo_app_key');
471			$secret_token = Tools::getValue('yotpo_oauth_token');
472			if ($api_key != '' && $secret_token != '')
473			{
474				$past_orders = $this->getPastOrders();
475				$is_success = true;
476				foreach ($past_orders as $post_bulk) 
477					if (!is_null($post_bulk))
478					{
479						$response = $this->httpClient()->makePastOrdersRequest($post_bulk, $api_key, $secret_token);
480						if ($response['status_code'] != 200 && $is_success)
481						{
482							$is_success = false;
483							$this->prepareError($this->l($response['status_message']));
484						}
485					}
486
487				if ($is_success)
488				{
489					Configuration::updateValue('yotpo_past_orders', 1, false);
490					Configuration::updateValue('YOTPO_CONFIGURATION_OK', true);
491					$this->prepareSuccess('Past orders sent successfully');
492				}	
493			}
494			else
495				$this->prepareError($this->l('You need to set your app key and secret token to post past orders'));
496		}
497	}
498
499	private function displayForm($force_settings = false)
500	{
501		$smarty = $this->context->smarty;
502
503		$smarty->assign(array('yotpo_finishedRegistration' => false, 'yotpo_allreadyUsingYotpo' => false));
504		if (Tools::isSubmit('log_in_button'))
505		{
506			$smarty->assign('yotpo_allreadyUsingYotpo', true);
507			return $this->displaySettingsForm();
508		}
509		if (Tools::isSubmit('yotpo_register'))
510			$smarty->assign('yotpo_finishedRegistration', true);
511
512		return Configuration::get('yotpo_app_key') != '' || $force_settings ? $this->displaySettingsForm() : $this->displayRegistrationForm();
513	}
514
515	private function displayRegistrationForm()
516	{
517		$smarty = $this->context->smarty;
518
519		$smarty->assign(array('yotpo_action' => $_SERVER['REQUEST_URI'], 'yotpo_email' => Tools::getValue('yotpo_user_email'),
520		'yotpo_userName' => Tools::getValue('yotpo_user_name')));
521
522		$this->_html .= $this->display(__FILE__, 'views/templates/admin/registrationForm.tpl');
523
524		return $this->_html;
525	}
526
527	private function displaySettingsForm()
528	{
529		if(!Configuration::get('yotpo_rich_snippet_cache_created')) {
530			$created = YotpoSnippetCache::createDB();
531			Configuration::updateValue('yotpo_rich_snippet_cache_created', 1, $created);
532		}
533		$smarty = $this->context->smarty;
534		$all_statuses = OrderState::getOrderStates($this->getLanguageId());
535		
536			//no configuration found -- use default
537		if(Configuration::get('yotpo_map_status') == false) {
538			Configuration::updateValue('yotpo_map_status', serialize($this->getAcceptedMapStatuses()), false);			
539		}
540		
541		if(method_exists('Tools', "unSerialize")) {
542			$selected_statuses = Tools::unSerialize(Configuration::get('yotpo_map_status'));	
543		}
544		else {
545			$selected_statuses = @unserialize(Configuration::get('yotpo_map_status'));	
546		}
547		foreach ($all_statuses as &$status) {
548			$status['selected'] = in_array($status['id_order_state'], $selected_statuses) ? '1' : '0';
549		}
550		$smarty->assign(array(
551		'yotpo_action' => $_SERVER['REQUEST_URI'],
552		'yotpo_appKey' => Tools::getValue('yotpo_app_key',Configuration::get('yotpo_app_key')),
553		'yotpo_oauthToken' => Tools::getValue('yotpo_oauth_token',Configuration::get('yotpo_oauth_token')),      
554		'yotpo_widgetLocation' => Configuration::get('yotpo_widget_location'),
555		'yotpo_showPastOrdersButton' => Configuration::get('yotpo_past_orders') != 1 ? true : false,         
556		'yotpo_tabName' => Configuration::get('yotpo_widget_tab_name'),
557		'yotpo_bottomLineEnabled' => Configuration::get('yotpo_bottom_line_enabled'), 
558		'yotpo_bottomLineLocation' => Configuration::get('yotpo_bottom_line_location'),
559	    'yotpo_widget_language_code' => Configuration::get('yotpo_language'),
560	    'yotpo_language_as_site' => Configuration::get('yotpo_language_as_site'),
561		'yotpo_rich_snippets' => Configuration::get('yotpo_rich_snippets'),
562		'yotpo_all_statuses' => $all_statuses));
563
564		$settings_template = $this->display(__FILE__, 'views/templates/admin/settingsForm.tpl');
565		if (strpos($settings_template, 'yotpo_map_enabled') != false || strpos($settings_template, 'yotpo_language_as_site') == false || strpos($settings_template, 'yotpo_rich_snippets') == false)
566		{
567			if(method_exists($smarty, 'clearCompiledTemplate'))
568			{
569				$smarty->clearCompiledTemplate(_PS_MODULE_DIR_ . $this->name .'/views/templates/admin/settingsForm.tpl');	
570				$settings_template = $this->display(__FILE__, 'views/templates/admin/settingsForm.tpl');
571			}
572			elseif (method_exists($smarty, 'clear_compiled_tpl'))
573			{
574				$smarty->clear_compiled_tpl(_PS_MODULE_DIR_ . $this->name .'/views/templates/admin/settingsForm.tpl');
575				$settings_template = $this->display(__FILE__, 'views/templates/admin/settingsForm.tpl');
576			}
577			elseif (isset($smarty->force_compile)) {
578				$value = $smarty->force_compile;
579				$smarty->force_compile = true;
580				$settings_template = $this->display(__FILE__, 'views/templates/admin/settingsForm.tpl');
581				$smarty->force_compile = $value;
582			}
583		}
584		$this->_html .= $settings_template;
585	}
586
587	private function getProductModel($product)
588	{
589		if (Validate::isEan13($product->ean13))
590			return $product->ean13;
591		elseif (Validate::isUpc($product->upc))
592			return $product->upc;
593
594		return null;
595	}
596
597	private function getBreadCrumbs($product)
598	{
599		if (!method_exists('Product', 'getProductCategoriesFull'))
600			return '';	
601
602		$result = array();
603		$lang_id = $this->getLanguageId(); 
604		$all_product_subs = Product::getProductCategoriesFull((int)$product->id, (int)$lang_id);
605		if (isset($all_product_subs) && count($all_product_subs) > 0)
606			foreach($all_product_subs as $subcat)
607			{
608				$sub_category = new Category((int)$subcat['id_category'], (int)$lang_id);
609				$sub_category_path = $sub_category->getParentsCategories();
610				foreach ($sub_category_path as $key)
611					$result[] = $key['name'];
612			}
613
614		return implode(';', $result);
615	}
616
617	private function prepareError($message = '')
618	{
619		$this->_html .= sprintf('<div class="bootstrap"><div class="alert">%s</div></div>', $message == '' ? $this->l('Error occured') : $message);
620	}
621
622	private function prepareSuccess($message = '')
623	{
624		$this->_html .= sprintf('<div class="conf confirm">%s</div>', $message == '' ? $this->l('Settings updated') : $message);
625	}
626
627	private function prepareMapData($params)
628	{
629		$order = new Order((int)$params['id_order']);
630		$customer = new Customer((int)$order->id_customer);
631		$id_lang = !is_null($params['cookie']) && !is_null($params['cookie']->id_lang) ? (int)$params['cookie']->id_lang : (int)Configuration::get('PS_LANG_DEFAULT');
632		if (Validate::isLoadedObject($order) && Validate::isLoadedObject($customer))
633		{
634			$singleMapParams = array('id_order' => (int)$params['id_order'], 'date_add' => $order->date_add,
635			'email' => $customer->email, 'firstname'=> $customer->firstname, 'lastname' => $customer->lastname,
636			'id_lang' => $id_lang);
637
638			$result = $this->getSingleMapData($singleMapParams);
639			if (!is_null($result) && is_array($result))
640			{
641				$result['platform'] = 'prestashop';
642				return $result;
643			}
644		}
645	 	return null;
646	}
647
648	private function getSingleMapData($params)
649	{
650		$cart = Cart::getCartByOrderId((int)$params['id_order']);
651		if(Validate::isLoadedObject($cart))
652		{
653			$products = $cart->getProducts();
654			if(count($products) == 0 && method_exists('Shop','getContextShopID') && Shop::getContextShopID() != (int)$cart->id_shop) 
655			{
656				Shop::initialize();
657				$products = $cart->getProducts(true);
658			}					
659			$currency = Currency::getCurrencyInstance((int)$cart->id_currency);
660			if (!is_null($products) && is_array($products) && Validate::isLoadedObject($currency))
661			{
662				$data = array();
663				$data['order_date'] = $params['date_add'];
664				$data['email'] = $params['email'];
665				$data['customer_name'] = $params['firstname'].' '.$params['lastname'];
666				$data['order_id'] = (int)$params['id_order'];
667				$data['currency_iso'] = $currency->iso_code;			    
668				$products_arr = array();
669				foreach ($products as $product) 
670				{
671					$product_data = array();    
672					$product_data['url'] = $this->getProductLink($product['id_product']); 
673					$product_data['name'] = $product['name'];
674					$product_data['image'] = $this->getProductImageUrl((int)$product['id_product']);
675					$product_data['description'] = $this->getDescritpion($product, (int)$params['id_lang']);
676					$product_data['price'] = $product['price'];
677					$products_arr[(int)$product['id_product']] = $product_data;
678				}
679				$data['products'] = $products_arr;
680				return $data;
681			}
682		}
683	 	return null;
684	}	
685	
686	private function getPastOrders()
687	{
688		$result = Db::getInstance()->ExecuteS('SELECT  o.`id_order`,o.`id_lang`, o.`date_add`, c.`firstname`, c.`lastname`, c.`email` 
689		FROM `'._DB_PREFIX_.'order_history` oh
690		LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = oh.`id_order`)
691		LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = o.`id_customer`)
692		WHERE oh.`id_order_history` IN (SELECT MAX(`id_order_history`) FROM `'._DB_PREFIX_.'order_history` GROUP BY `id_order`) AND
693		o.`date_add` <  NOW() AND 
694		DATE_SUB(NOW(), INTERVAL '.self::PAST_ORDERS_DAYS_BACK.' day) < o.`date_add` AND 
695		oh.`id_order_state` IN ('.join(',', $this->getAcceptedMapStatuses()).')
696		LIMIT 0,'.self::PAST_ORDERS_LIMIT.'');
697
698		if (is_array($result))
699		{
700			$orders = array();
701			foreach ($result as $singleMap)
702			{
703				$res = $this->getSingleMapData($singleMap);
704				if (!is_null($res))
705					$orders[] = $res;
706			}
707			$post_bulk_orders = array_chunk($orders, self::BULK_SIZE);
708			$data = array();
709			foreach ($post_bulk_orders as $index => $bulk)
710			{
711				$data[$index] = array();
712				$data[$index]['orders'] = $bulk;
713				$data[$index]['platform'] = 'prestashop';			
714			}
715			return $data;
716		}
717		return null;
718	}
719
720	private function getPageProduct($product_id = null)
721	{
722		if($product_id == null)
723			$product_id = $this->parseProductId();
724			
725		$product = new Product((int)($product_id), false, Configuration::get('PS_LANG_DEFAULT'));
726		if(Validate::isLoadedObject($product))
727			return $product;
728			
729		return null;
730	}
731	
732	private function getLanguage() {
733		$language = Configuration::get('yotpo_language');
734		if (Configuration::get('yotpo_language_as_site') == true) {
735			if (isset($this->context->language) && isset($this->context->language->iso_code)) {
736				$language = $this->context->language->iso_code;
737			}
738			else {
739				$language = Language::getIsoById( (int)$this->context->cookie->id_lang );
740			}	
741		}
742		return $language;
743	}
744	
745	private function getRichSnippet($product_id) {
746		$result = '';		
747		if (Configuration::get('yotpo_app_key') != '' && Configuration::get('yotpo_oauth_token') != '' && is_int($product_id)) {
748			try {
749				$result = YotpoSnippetCache::getRichSnippet($product_id);
750				$should_update_row = is_array($result) && !YotpoSnippetCache::isValidCache($result); 			
751				if($result == false || $should_update_row) {			
752					$result = '';
753					$expiration_time = null;
754					$request_result = $this->httpClient()->makeRichSnippetRequest(Configuration::get('yotpo_app_key'), $product_id);
755					if($request_result['status_code'] == 200) {
756						if ($request_result['json'] == true) {
757							$result .= $request_result['response']['rich_snippet']['html_code'];
758							$expiration_time = $request_result['response']['rich_snippet']['ttl'];
759						}
760						else 
761						{
762							preg_match("/html_code[\"']:[\"'](.*)[\"'],[\"']ttl/",$request_result['response'], $matches);
763							$result = $matches[1];
764							unset($matches);
765							$result = str_replace('\"','"',$result);
766							$result = str_replace('\n','',$result);
767							
768							preg_match("/ttl[\"']:(.*)}/",$request_result['response'], $matches);
769							$expiration_time = $matches[1];						 
770							unset($matches);
771						}	
772						if(Tools::strlen($result) > 0 && Tools::strlen($expiration_time) > 0 && is_numeric($expiration_time)) {
773							if($should_update_row) {
774								YotpoSnippetCache::updateCahce($product_id, $result, $expiration_time);
775							}
776							else {
777								YotpoSnippetCache::addRichSnippetToCahce($product_id, $result, $expiration_time);	
778							}
779								
780						}
781					}
782				}
783				elseif (is_array($result) && !$should_update_row) {
784					$result = $result['rich_snippet_code'];
785				}
786			}
787			catch (Exception $e) {
788				error_log($e->getMessage());
789			}				
790		}
791		return $result;		
792	}
793	private function getLanguageId(){
794		if (isset($this->context->language) && isset($this->context->language->id)) {
795			return $this->context->language->id;
796		}
797		else {
798			return $this->context->cookie->id_lang;
799		}
800	}		
801}