dolibarr  17.0.3
dolistore.class.php
1 <?php
2 /*
3  * Copyright (C) 2017 Oscss-Shop <support@oscss-shop.fr>.
4  *
5  * This program is free software; you can redistribute it and/or modifyion 2.0 (the "License");
6  * it under the terms of the GNU General Public License as published bypliance with the License.
7  * the Free Software Foundation; either version 3 of the License, or
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  * or see https://www.gnu.org/
17  */
18 
19 include_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
20 if (!class_exists('PrestaShopWebservice')) { // We keep this because some modules add this lib too into a different path. This is to avoid "Cannot declare class PrestaShopWebservice" errors.
21  include_once DOL_DOCUMENT_ROOT.'/admin/dolistore/class/PSWebServiceLibrary.class.php';
22 }
23 
24 
28 class Dolistore
29 {
34  public $start;
35 
40  public $end;
41 
42  public $per_page; // pagination: display per page
43  public $categorie; // the current categorie
44  public $search; // the search keywords
45 
46  // setups
47  public $url; // the url of this page
48  public $shop_url; // the url of the shop
49  public $lang; // the integer representing the lang in the store
50  public $debug_api; // usefull if no dialog
51 
52 
58  public function __construct($debug = false)
59  {
60  global $conf, $langs;
61 
62  $this->url = DOL_URL_ROOT.'/admin/modules.php?mode=marketplace';
63  $this->shop_url = 'https://www.dolistore.com/index.php?controller=product&id_product=';
64  $this->debug_api = $debug;
65 
66  $langtmp = explode('_', $langs->defaultlang);
67  $lang = $langtmp[0];
68  $lang_array = array('en'=>1, 'fr'=>2, 'es'=>3, 'it'=>4, 'de'=>5); // Into table ps_lang of Prestashop - 1
69  if (!in_array($lang, array_keys($lang_array))) {
70  $lang = 'en';
71  }
72  $this->lang = $lang_array[$lang];
73  }
74 
81  public function getRemoteCategories()
82  {
83  global $conf;
84 
85  try {
86  $this->api = new PrestaShopWebservice($conf->global->MAIN_MODULE_DOLISTORE_API_SRV, $conf->global->MAIN_MODULE_DOLISTORE_API_KEY, $this->debug_api);
87  dol_syslog("Call API with MAIN_MODULE_DOLISTORE_API_SRV = ".getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV'));
88  // $conf->global->MAIN_MODULE_DOLISTORE_API_KEY is for the login of basic auth. There is no password as it is public data.
89 
90  // Here we set the option array for the Webservice : we want categories resources
91  $opt = array();
92  $opt['resource'] = 'categories';
93  $opt['display'] = '[id,id_parent,nb_products_recursive,active,is_root_category,name,description]';
94  $opt['sort'] = 'id_asc';
95 
96  // Call
97  dol_syslog("Call API with opt = ".var_export($opt, true));
98  $xml = $this->api->get($opt);
99  $this->categories = $xml->categories->children();
100  } catch (PrestaShopWebserviceException $e) {
101  // Here we are dealing with errors
102  $trace = $e->getTrace();
103  if ($trace[0]['args'][0] == 404) {
104  die('Bad ID');
105  } elseif ($trace[0]['args'][0] == 401) {
106  die('Bad auth key');
107  } else {
108  print 'Can not access to '.$conf->global->MAIN_MODULE_DOLISTORE_API_SRV.'<br>';
109  print $e->getMessage();
110  }
111  }
112  }
113 
121  public function getRemoteProducts($options = array('start' => 0, 'end' => 10, 'per_page' => 50, 'categorie' => 0, 'search' => ''))
122  {
123  global $conf;
124 
125  $this->start = $options['start'];
126  $this->end = $options['end'];
127  $this->per_page = $options['per_page'];
128  $this->categorie = $options['categorie'];
129  $this->search = $options['search'];
130 
131  if ($this->end == 0) {
132  $this->end = $this->per_page;
133  }
134 
135  try {
136  $this->api = new PrestaShopWebservice($conf->global->MAIN_MODULE_DOLISTORE_API_SRV, $conf->global->MAIN_MODULE_DOLISTORE_API_KEY, $this->debug_api);
137  dol_syslog("Call API with MAIN_MODULE_DOLISTORE_API_SRV = ".getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV'));
138  // $conf->global->MAIN_MODULE_DOLISTORE_API_KEY is for the login of basic auth. There is no password as it is public data.
139 
140  // Here we set the option array for the Webservice : we want products resources
141  $opt = array();
142  $opt['resource'] = 'products';
143  $opt2 = array();
144 
145  // make a search to limit the id returned.
146  if ($this->search != '') {
147  $opt2['url'] = $conf->global->MAIN_MODULE_DOLISTORE_API_SRV.'/api/search?query='.$this->search.'&language='.$this->lang; // It seems for search, key start with
148 
149  // Call
150  dol_syslog("Call API with opt2 = ".var_export($opt2, true));
151  $xml = $this->api->get($opt2);
152 
153  $products = array();
154  foreach ($xml->products->children() as $product) {
155  $products[] = (int) $product['id'];
156  }
157  $opt['filter[id]'] = '['.implode('|', $products).']';
158  } elseif ($this->categorie != 0) { // We filter on category, so we first get list of product id in this category
159  // $opt2['url'] is set by default to $this->url.'/api/'.$options['resource'];
160  $opt2['resource'] = 'categories';
161  $opt2['id'] = $this->categorie;
162 
163  // Call
164  dol_syslog("Call API with opt2 = ".var_export($opt2, true));
165  $xml = $this->api->get($opt2);
166 
167  $products = array();
168  foreach ($xml->category->associations->products->children() as $product) {
169  $products[] = (int) $product->id;
170  }
171  $opt['filter[id]'] = '['.implode('|', $products).']';
172  }
173  $opt['display'] = '[id,name,id_default_image,id_category_default,reference,price,condition,show_price,date_add,date_upd,description_short,description,module_version,dolibarr_min,dolibarr_max]';
174  $opt['sort'] = 'id_desc';
175  $opt['filter[active]'] = '[1]';
176  $opt['limit'] = "$this->start,$this->end";
177  // $opt['filter[id]'] contais list of product id that are result of search
178 
179  // Call API to get the detail
180  dol_syslog("Call API with opt = ".var_export($opt, true));
181  $xml = $this->api->get($opt);
182  $this->products = $xml->products->children();
183  } catch (PrestaShopWebserviceException $e) {
184  // Here we are dealing with errors
185  $trace = $e->getTrace();
186  if ($trace[0]['args'][0] == 404) {
187  die('Bad ID');
188  } elseif ($trace[0]['args'][0] == 401) {
189  die('Bad auth key');
190  } else {
191  print 'Can not access to '.$conf->global->MAIN_MODULE_DOLISTORE_API_SRV.'<br>';
192  print $e->getMessage();
193  }
194  }
195  }
196 
197  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
204  public function get_categories($parent = 0)
205  {
206  // phpcs:enable
207  if (!isset($this->categories)) {
208  die('not possible');
209  }
210  if ($parent != 0) {
211  $html = '<ul>';
212  } else {
213  $html = '';
214  }
215 
216  $nbofcateg = count($this->categories);
217  for ($i = 0; $i < $nbofcateg; $i++) {
218  $cat = $this->categories[$i];
219  if ($cat->is_root_category == 1 && $parent == 0) {
220  $html .= '<li class="root"><h3 class="nomargesupinf"><a class="nomargesupinf link2cat" href="?mode=marketplace&categorie='.((int) $cat->id).'" ';
221  $html .= 'title="'.dol_escape_htmltag(strip_tags($cat->description->language[$this->lang - 1])).'">'.dol_escape_htmltag($cat->name->language[$this->lang - 1]).' <sup>'.dol_escape_htmltag($cat->nb_products_recursive).'</sup></a></h3>';
222  $html .= self::get_categories($cat->id);
223  $html .= "</li>\n";
224  } elseif (trim($cat->id_parent) == $parent && $cat->active == 1 && trim($cat->id_parent) != 0) { // si cat est de ce niveau
225  $select = ($cat->id == $this->categorie) ? ' selected' : '';
226  $html .= '<li><a class="link2cat'.$select.'" href="?mode=marketplace&categorie='.((int) $cat->id).'"';
227  $html .= ' title="'.dol_escape_htmltag(strip_tags($cat->description->language[$this->lang - 1])).'" ';
228  $html .= '>'.dol_escape_htmltag($cat->name->language[$this->lang - 1]).' <sup>'.dol_escape_htmltag($cat->nb_products_recursive).'</sup></a>';
229  $html .= self::get_categories($cat->id);
230  $html .= "</li>\n";
231  }
232  }
233 
234  if ($html == '<ul>') {
235  return '';
236  }
237  if ($parent != 0) {
238  return $html.'</ul>';
239  } else {
240  return $html;
241  }
242  }
243 
244  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
250  public function get_products()
251  {
252  // phpcs:enable
253  global $langs, $conf;
254  $html = "";
255  $last_month = time() - (30 * 24 * 60 * 60);
256  foreach ($this->products as $product) {
257  // check new product ?
258  $newapp = '';
259  if ($last_month < strtotime($product->date_add)) {
260  $newapp .= '<span class="newApp">'.$langs->trans('New').'</span> ';
261  }
262 
263  // check updated ?
264  if ($last_month < strtotime($product->date_upd) && $newapp == '') {
265  $newapp .= '<span class="updatedApp">'.$langs->trans('Updated').'</span> ';
266  }
267 
268  // add image or default ?
269  if ($product->id_default_image != '') {
270  $image_url = DOL_URL_ROOT.'/admin/dolistore/ajax/image.php?id_product='.urlencode(((int) $product->id)).'&id_image='.urlencode(((int) $product->id_default_image));
271  $images = '<a href="'.$image_url.'" class="documentpreview" target="_blank" rel="noopener noreferrer" mime="image/png" title="'.dol_escape_htmltag($product->name->language[$this->lang - 1].', '.$langs->trans('Version').' '.$product->module_version).'">';
272  $images .= '<img src="'.$image_url.'&quality=home_default" style="max-height:250px;max-width: 210px;" alt="" /></a>';
273  } else {
274  $images = '<img src="'.DOL_URL_ROOT.'/admin/dolistore/img/NoImageAvailable.png" />';
275  }
276 
277  // free or pay ?
278  if ($product->price > 0) {
279  $price = '<h3>'.price(price2num($product->price, 'MT'), 0, $langs, 1, -1, -1, 'EUR').' '.$langs->trans("HT").'</h3>';
280  $download_link = '<a target="_blank" href="'.$this->shop_url.urlencode($product->id).'"><img width="32" src="'.DOL_URL_ROOT.'/admin/dolistore/img/follow.png" /></a>';
281  } else {
282  $price = '<h3>'.$langs->trans('Free').'</h3>';
283  $download_link = '<a target="_blank" rel="noopener noreferrer" href="'.$this->shop_url.urlencode($product->id).'"><img width="32" src="'.DOL_URL_ROOT.'/admin/dolistore/img/Download-128.png" /></a>';
284  $download_link .= '<br><br><a target="_blank" href="'.$this->shop_url.urlencode($product->id).'"><img width="32" src="'.DOL_URL_ROOT.'/admin/dolistore/img/follow.png" /></a>';
285  }
286 
287  // Set and check version
288  $version = '';
289  if ($this->version_compare($product->dolibarr_min, DOL_VERSION) <= 0) {
290  if ($this->version_compare($product->dolibarr_max, DOL_VERSION) >= 0) {
291  //compatible
292  $version = '<span class="compatible">'.$langs->trans(
293  'CompatibleUpTo',
294  $product->dolibarr_max,
295  $product->dolibarr_min,
296  $product->dolibarr_max
297  ).'</span>';
298  $compatible = '';
299  } else {
300  //never compatible, module expired
301  $version = '<span class="notcompatible">'.$langs->trans(
302  'NotCompatible',
303  DOL_VERSION,
304  $product->dolibarr_min,
305  $product->dolibarr_max
306  ).'</span>';
307  $compatible = 'NotCompatible';
308  }
309  } else {
310  //need update
311  $version = '<span class="compatibleafterupdate">'.$langs->trans(
312  'CompatibleAfterUpdate',
313  DOL_VERSION,
314  $product->dolibarr_min,
315  $product->dolibarr_max
316  ).'</span>';
317  $compatible = 'NotCompatible';
318  }
319 
320  //output template
321  $html .= '<tr class="app oddeven '.dol_escape_htmltag($compatible).'">';
322  $html .= '<td class="center" width="210"><div class="newAppParent">';
323  $html .= $newapp.$images; // No dol_escape_htmltag, it is already escape html
324  $html .= '</div></td>';
325  $html .= '<td class="margeCote"><h2 class="appTitle">';
326  $html .= dol_escape_htmltag($product->name->language[$this->lang - 1]);
327  $html .= '<br><small>';
328  $html .= $version; // No dol_escape_htmltag, it is already escape html
329  $html .= '</small></h2>';
330  $html .= '<small> '.dol_print_date(dol_stringtotime($product->date_upd), 'dayhour').' - '.$langs->trans('Ref').': '.dol_escape_htmltag($product->reference).' - '.dol_escape_htmltag($langs->trans('Id')).': '.((int) $product->id).'</small><br><br>'.dol_escape_htmltag($product->description_short->language[$this->lang - 1]).'</td>';
331  // do not load if display none
332  //$html .= '<td style="display:none;" class="long_description">'.$product->description->language[$this->lang - 1].'</td>';
333  $html .= '<td class="margeCote center">';
334  $html .= $price;
335  $html .= '</td>';
336  $html .= '<td class="margeCote">'.$download_link.'</td>';
337  $html .= '</tr>';
338  }
339  return $html;
340  }
341 
342  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
349  public function get_previous_link($text = '<<')
350  {
351  // phpcs:enable
352  return '<a href="'.$this->get_previous_url().'" class="button">'.dol_escape_htmltag($text).'</a>';
353  }
354 
355  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
362  public function get_next_link($text = '>>')
363  {
364  // phpcs:enable
365  return '<a href="'.$this->get_next_url().'" class="button">'.dol_escape_htmltag($text).'</a>';
366  }
367 
368  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
374  public function get_previous_url()
375  {
376  // phpcs:enable
377  $param_array = array();
378  if ($this->start < $this->per_page) {
379  $sub = 0;
380  } else {
381  $sub = $this->per_page;
382  }
383  $param_array['start'] = $this->start - $sub;
384  $param_array['end'] = $this->end - $sub;
385  if ($this->categorie != 0) {
386  $param_array['categorie'] = $this->categorie;
387  }
388  $param = http_build_query($param_array);
389  return $this->url."&".$param;
390  }
391 
392  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
398  public function get_next_url()
399  {
400  // phpcs:enable
401  $param_array = array();
402  if (count($this->products) < $this->per_page) {
403  $add = 0;
404  } else {
405  $add = $this->per_page;
406  }
407  $param_array['start'] = $this->start + $add;
408  $param_array['end'] = $this->end + $add;
409  if ($this->categorie != 0) {
410  $param_array['categorie'] = $this->categorie;
411  }
412  $param = http_build_query($param_array);
413  return $this->url."&".$param;
414  }
415 
416  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
424  public function version_compare($v1, $v2)
425  {
426  // phpcs:enable
427  $v1 = explode('.', $v1);
428  $v2 = explode('.', $v2);
429  $ret = 0;
430  $level = 0;
431  $count1 = count($v1);
432  $count2 = count($v2);
433  $maxcount = max($count1, $count2);
434  while ($level < $maxcount) {
435  $operande1 = isset($v1[$level]) ? $v1[$level] : 'x';
436  $operande2 = isset($v2[$level]) ? $v2[$level] : 'x';
437  $level++;
438  if (strtoupper($operande1) == 'X' || strtoupper($operande2) == 'X' || $operande1 == '*' || $operande2 == '*') {
439  break;
440  }
441  if ($operande1 < $operande2) {
442  $ret = -$level;
443  break;
444  }
445  if ($operande1 > $operande2) {
446  $ret = $level;
447  break;
448  }
449  }
450  //print join('.',$versionarray1).'('.count($versionarray1).') / '.join('.',$versionarray2).'('.count($versionarray2).') => '.$ret.'<br>'."\n";
451  return $ret;
452  }
453 }
Dolistore
Class Dolistore.
Definition: dolistore.class.php:28
dol_escape_htmltag
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
Definition: functions.lib.php:1493
Dolistore\get_next_url
get_next_url()
get next url
Definition: dolistore.class.php:398
Dolistore\get_categories
get_categories($parent=0)
Return tree of Dolistore categories.
Definition: dolistore.class.php:204
Dolistore\getRemoteProducts
getRemoteProducts($options=array('start'=> 0, 'end'=> 10, 'per_page'=> 50, 'categorie'=> 0, 'search'=> ''))
Load data from remote Dolistore market place.
Definition: dolistore.class.php:121
PrestaShopWebserviceException
Definition: PSWebServiceLibrary.class.php:425
Dolistore\get_products
get_products()
Return list of product formated for output.
Definition: dolistore.class.php:250
Dolistore\get_previous_link
get_previous_link($text='<<')
get previous link
Definition: dolistore.class.php:349
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5823
PrestaShopWebservice
Definition: PSWebServiceLibrary.class.php:32
Dolistore\__construct
__construct($debug=false)
Constructor.
Definition: dolistore.class.php:58
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1628
Dolistore\getRemoteCategories
getRemoteCategories()
Load data from remote Dolistore market place.
Definition: dolistore.class.php:81
Dolistore\get_next_link
get_next_link($text='>>')
get next link
Definition: dolistore.class.php:362
getDolGlobalString
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
Definition: functions.lib.php:82
Dolistore\get_previous_url
get_previous_url()
get previous url
Definition: dolistore.class.php:374
start
padding inline start
Definition: style.css.php:820
Dolistore\version_compare
version_compare($v1, $v2)
version compare
Definition: dolistore.class.php:424
dol_stringtotime
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition: date.lib.php:407