dolibarr  13.0.2
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 {
22  include_once DOL_DOCUMENT_ROOT.'/admin/dolistore/class/PSWebServiceLibrary.class.php';
23 }
24 
25 
29 class Dolistore
30 {
35  public $start;
36 
41  public $end;
42 
43  public $per_page; // pagination: display per page
44  public $categorie; // the current categorie
45  public $search; // the search keywords
46 
47  // setups
48  public $url; // the url of this page
49  public $shop_url; // the url of the shop
50  public $lang; // the integer representing the lang in the store
51  public $debug_api; // usefull if no dialog
52 
53 
59  public function __construct($debug = false)
60  {
61  global $conf, $langs;
62 
63  $this->url = DOL_URL_ROOT.'/admin/modules.php?mode=marketplace';
64  $this->shop_url = 'https://www.dolistore.com/index.php?controller=product&id_product=';
65  $this->debug_api = $debug;
66 
67  $langtmp = explode('_', $langs->defaultlang);
68  $lang = $langtmp[0];
69  $lang_array = array('en'=>1, 'fr'=>2, 'es'=>3, 'it'=>4, 'de'=>5); // Into table ps_lang of Prestashop - 1
70  if (!in_array($lang, array_keys($lang_array))) $lang = 'en';
71  $this->lang = $lang_array[$lang];
72  }
73 
80  public function getRemoteCategories()
81  {
82  global $conf;
83 
84  try {
85  $this->api = new PrestaShopWebservice($conf->global->MAIN_MODULE_DOLISTORE_API_SRV, $conf->global->MAIN_MODULE_DOLISTORE_API_KEY, $this->debug_api);
86  dol_syslog("Call API with MAIN_MODULE_DOLISTORE_API_SRV = ".$conf->global->MAIN_MODULE_DOLISTORE_API_SRV);
87  // $conf->global->MAIN_MODULE_DOLISTORE_API_KEY is for the login of basic auth. There is no password as it is public data.
88 
89  // Here we set the option array for the Webservice : we want categories resources
90  $opt = array();
91  $opt['resource'] = 'categories';
92  $opt['display'] = '[id,id_parent,nb_products_recursive,active,is_root_category,name,description]';
93  $opt['sort'] = 'id_asc';
94 
95  // Call
96  dol_syslog("Call API with opt = ".var_export($opt, true));
97  $xml = $this->api->get($opt);
98  $this->categories = $xml->categories->children();
99  } catch (PrestaShopWebserviceException $e) {
100  // Here we are dealing with errors
101  $trace = $e->getTrace();
102  if ($trace[0]['args'][0] == 404) die('Bad ID');
103  elseif ($trace[0]['args'][0] == 401) die('Bad auth key');
104  else {
105  print 'Can not access to '.$conf->global->MAIN_MODULE_DOLISTORE_API_SRV.'<br>';
106  print $e->getMessage();
107  }
108  }
109  }
110 
118  public function getRemoteProducts($options = array('start' => 0, 'end' => 10, 'per_page' => 50, 'categorie' => 0, 'search' => ''))
119  {
120  global $conf;
121 
122  $this->start = $options['start'];
123  $this->end = $options['end'];
124  $this->per_page = $options['per_page'];
125  $this->categorie = $options['categorie'];
126  $this->search = $options['search'];
127 
128  if ($this->end == 0) {
129  $this->end = $this->per_page;
130  }
131 
132  try {
133  $this->api = new PrestaShopWebservice($conf->global->MAIN_MODULE_DOLISTORE_API_SRV, $conf->global->MAIN_MODULE_DOLISTORE_API_KEY, $this->debug_api);
134  dol_syslog("Call API with MAIN_MODULE_DOLISTORE_API_SRV = ".$conf->global->MAIN_MODULE_DOLISTORE_API_SRV);
135  // $conf->global->MAIN_MODULE_DOLISTORE_API_KEY is for the login of basic auth. There is no password as it is public data.
136 
137  // Here we set the option array for the Webservice : we want products resources
138  $opt = array();
139  $opt['resource'] = 'products';
140  $opt2 = array();
141 
142  // make a search to limit the id returned.
143  if ($this->search != '') {
144  $opt2['url'] = $conf->global->MAIN_MODULE_DOLISTORE_API_SRV.'/api/search?query='.$this->search.'&language='.$this->lang; // It seems for search, key start with
145 
146  // Call
147  dol_syslog("Call API with opt2 = ".var_export($opt2, true));
148  $xml = $this->api->get($opt2);
149 
150  $products = array();
151  foreach ($xml->products->children() as $product) {
152  $products[] = (int) $product['id'];
153  }
154  $opt['filter[id]'] = '['.implode('|', $products).']';
155  } elseif ($this->categorie != 0) { // We filter on category, so we first get list of product id in this category
156  // $opt2['url'] is set by default to $this->url.'/api/'.$options['resource'];
157  $opt2['resource'] = 'categories';
158  $opt2['id'] = $this->categorie;
159 
160  // Call
161  dol_syslog("Call API with opt2 = ".var_export($opt2, true));
162  $xml = $this->api->get($opt2);
163 
164  $products = array();
165  foreach ($xml->category->associations->products->children() as $product) {
166  $products[] = (int) $product->id;
167  }
168  $opt['filter[id]'] = '['.implode('|', $products).']';
169  }
170  $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]';
171  $opt['sort'] = 'id_desc';
172  $opt['filter[active]'] = '[1]';
173  $opt['limit'] = "$this->start,$this->end";
174  // $opt['filter[id]'] contais list of product id that are result of search
175 
176  // Call API to get the detail
177  dol_syslog("Call API with opt = ".var_export($opt, true));
178  $xml = $this->api->get($opt);
179  $this->products = $xml->products->children();
180  } catch (PrestaShopWebserviceException $e) {
181  // Here we are dealing with errors
182  $trace = $e->getTrace();
183  if ($trace[0]['args'][0] == 404) die('Bad ID');
184  elseif ($trace[0]['args'][0] == 401) die('Bad auth key');
185  else {
186  print 'Can not access to '.$conf->global->MAIN_MODULE_DOLISTORE_API_SRV.'<br>';
187  print $e->getMessage();
188  }
189  }
190  }
191 
192  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
199  public function get_categories($parent = 0)
200  {
201  // phpcs:enable
202  if (!isset($this->categories)) die('not possible');
203  if ($parent != 0) {
204  $html = '<ul>';
205  } else {
206  $html = '';
207  }
208 
209  $nbofcateg = count($this->categories);
210  for ($i = 0; $i < $nbofcateg; $i++)
211  {
212  $cat = $this->categories[$i];
213  if ($cat->is_root_category == 1 && $parent == 0) {
214  $html .= '<li class="root"><h3 class="nomargesupinf"><a class="nomargesupinf link2cat" href="?mode=marketplace&categorie='.$cat->id.'" ';
215  $html .= 'title="'.dol_escape_htmltag(strip_tags($cat->description->language[$this->lang - 1])).'">'.$cat->name->language[$this->lang - 1].' <sup>'.$cat->nb_products_recursive.'</sup></a></h3>';
216  $html .= self::get_categories($cat->id);
217  $html .= "</li>\n";
218  } elseif (trim($cat->id_parent) == $parent && $cat->active == 1 && trim($cat->id_parent) != 0) { // si cat est de ce niveau
219  $select = ($cat->id == $this->categorie) ? ' selected' : '';
220  $html .= '<li><a class="link2cat'.$select.'" href="?mode=marketplace&categorie='.$cat->id.'"';
221  $html .= ' title="'.dol_escape_htmltag(strip_tags($cat->description->language[$this->lang - 1])).'" ';
222  $html .= '>'.$cat->name->language[$this->lang - 1].' <sup>'.$cat->nb_products_recursive.'</sup></a>';
223  $html .= self::get_categories($cat->id);
224  $html .= "</li>\n";
225  }
226  }
227 
228  if ($html == '<ul>') {
229  return '';
230  }
231  if ($parent != 0) {
232  return $html.'</ul>';
233  } else {
234  return $html;
235  }
236  }
237 
238  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
244  public function get_products()
245  {
246  // phpcs:enable
247  global $langs, $conf;
248  $html = "";
249  $last_month = time() - (30 * 24 * 60 * 60);
250  foreach ($this->products as $product) {
251  // check new product ?
252  $newapp = '';
253  if ($last_month < strtotime($product->date_add)) {
254  $newapp .= '<span class="newApp">'.$langs->trans('New').'</span> ';
255  }
256 
257  // check updated ?
258  if ($last_month < strtotime($product->date_upd) && $newapp == '') {
259  $newapp .= '<span class="updatedApp">'.$langs->trans('Updated').'</span> ';
260  }
261 
262  // add image or default ?
263  if ($product->id_default_image != '') {
264  $image_url = DOL_URL_ROOT.'/admin/dolistore/ajax/image.php?id_product='.$product->id.'&id_image='.$product->id_default_image;
265  $images = '<a href="'.$image_url.'" class="documentpreview" target="_blank" mime="image/png" title="'.$product->name->language[$this->lang - 1].', '.$langs->trans('Version').' '.$product->module_version.'">';
266  $images .= '<img src="'.$image_url.'&quality=home_default" style="max-height:250px;max-width: 210px;" alt="" /></a>';
267  } else {
268  $images = '<img src="'.DOL_URL_ROOT.'/admin/dolistore/img/NoImageAvailable.png" />';
269  }
270 
271  // free or pay ?
272  if ($product->price > 0) {
273  $price = '<h3>'.price(price2num($product->price, 'MT'), 0, $langs, 1, -1, -1, 'EUR').' '.$langs->trans("HT").'</h3>';
274  $download_link = '<a target="_blank" href="'.$this->shop_url.$product->id.'"><img width="32" src="'.DOL_URL_ROOT.'/admin/dolistore/img/follow.png" /></a>';
275  } else {
276  $price = '<h3>'.$langs->trans('Free').'</h3>';
277  $download_link = '<a target="_blank" href="'.$this->shop_url.$product->id.'"><img width="32" src="'.DOL_URL_ROOT.'/admin/dolistore/img/Download-128.png" /></a>';
278  $download_link .= '<br><br><a target="_blank" href="'.$this->shop_url.$product->id.'"><img width="32" src="'.DOL_URL_ROOT.'/admin/dolistore/img/follow.png" /></a>';
279  }
280 
281  //checking versions
282  if ($this->version_compare($product->dolibarr_min, DOL_VERSION) <= 0) {
283  if ($this->version_compare($product->dolibarr_max, DOL_VERSION) >= 0) {
284  //compatible
285  $version = '<span class="compatible">'.$langs->trans('CompatibleUpTo', $product->dolibarr_max,
286  $product->dolibarr_min, $product->dolibarr_max).'</span>';
287  $compatible = '';
288  } else {
289  //never compatible, module expired
290  $version = '<span class="notcompatible">'.$langs->trans('NotCompatible', DOL_VERSION,
291  $product->dolibarr_min, $product->dolibarr_max).'</span>';
292  $compatible = 'NotCompatible';
293  }
294  } else {
295  //need update
296  $version = '<span class="compatibleafterupdate">'.$langs->trans('CompatibleAfterUpdate', DOL_VERSION,
297  $product->dolibarr_min, $product->dolibarr_max).'</span>';
298  $compatible = 'NotCompatible';
299  }
300 
301  //.'<br><a class="inline-block valignmiddle" target="_blank" href="'.$this->shop_url.$product->id.'"><span class="details button">'.$langs->trans("SeeInMarkerPlace").'</span></a>
302 
303  //output template
304  $html .= '<tr class="app oddeven '.$compatible.'">
305  <td class="center" width="210"><div class="newAppParent">'.$newapp.$images.'</div></td>
306  <td class="margeCote"><h2 class="appTitle">'.$product->name->language[$this->lang - 1]
307  .'<br/><small>'.$version.'</small></h2>
308  <small> '.dol_print_date(dol_stringtotime($product->date_upd), 'dayhour').' - '.$langs->trans('Ref').': '.$product->reference.' - '.$langs->trans('Id').': '.$product->id.'</small><br><br>'.$product->description_short->language[$this->lang - 1].'</td>';
309  // do not load if display none
310  //$html .= '<td style="display:none;" class="long_description">'.$product->description->language[$this->lang - 1].'</td>';
311  $html .= '<td class="margeCote center">'.$price.'</td>';
312  $html .= '<td class="margeCote">'.$download_link.'</td>';
313  $html .= '</tr>';
314  }
315  return $html;
316  }
317 
318  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
325  public function get_previous_link($text = '<<')
326  {
327  // phpcs:enable
328  return '<a href="'.$this->get_previous_url().'" class="button">'.$text.'</a>';
329  }
330 
331  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
338  public function get_next_link($text = '>>')
339  {
340  // phpcs:enable
341  return '<a href="'.$this->get_next_url().'" class="button">'.$text.'</a>';
342  }
343 
344  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
350  public function get_previous_url()
351  {
352  // phpcs:enable
353  $param_array = array();
354  if ($this->start < $this->per_page) {
355  $sub = 0;
356  } else {
357  $sub = $this->per_page;
358  }
359  $param_array['start'] = $this->start - $sub;
360  $param_array['end'] = $this->end - $sub;
361  if ($this->categorie != 0) {
362  $param_array['categorie'] = $this->categorie;
363  }
364  $param = http_build_query($param_array);
365  return $this->url."&".$param;
366  }
367 
368  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
374  public function get_next_url()
375  {
376  // phpcs:enable
377  $param_array = array();
378  if (count($this->products) < $this->per_page) {
379  $add = 0;
380  } else {
381  $add = $this->per_page;
382  }
383  $param_array['start'] = $this->start + $add;
384  $param_array['end'] = $this->end + $add;
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
400  public function version_compare($v1, $v2)
401  {
402  // phpcs:enable
403  $v1 = explode('.', $v1);
404  $v2 = explode('.', $v2);
405  $ret = 0;
406  $level = 0;
407  $count1 = count($v1);
408  $count2 = count($v2);
409  $maxcount = max($count1, $count2);
410  while ($level < $maxcount) {
411  $operande1 = isset($v1[$level]) ? $v1[$level] : 'x';
412  $operande2 = isset($v2[$level]) ? $v2[$level] : 'x';
413  $level++;
414  if (strtoupper($operande1) == 'X' || strtoupper($operande2) == 'X' || $operande1 == '*' || $operande2 == '*') {
415  break;
416  }
417  if ($operande1 < $operande2) {
418  $ret = -$level;
419  break;
420  }
421  if ($operande1 > $operande2) {
422  $ret = $level;
423  break;
424  }
425  }
426  //print join('.',$versionarray1).'('.count($versionarray1).') / '.join('.',$versionarray2).'('.count($versionarray2).') => '.$ret.'<br>'."\n";
427  return $ret;
428  }
429 }
__construct($debug=false)
Constructor.
get_previous_url()
get previous url
get_next_link($text= '>>')
get next link
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:319
version_compare($v1, $v2)
version compare
getRemoteCategories()
Load data from remote Dolistore market place.
get_products()
Return list of product formated for output.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
get_next_url()
get next url
print
Draft customers invoices.
Definition: index.php:89
Class Dolistore.
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
get_categories($parent=0)
Return tree of Dolistore categories.
getRemoteProducts($options=array('start'=> 0, 'end'=> 10, 'per_page'=> 50, 'categorie'=> 0, 'search'=> ''))
Load data from remote Dolistore market place.
get_previous_link($text= '<<')
get previous link