dolibarr 21.0.0-beta
dolistore.class.php
1<?php
2/*
3 * Copyright (C) 2017 Oscss-Shop <support@oscss-shop.fr>.
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 *
6 * This program is free software; you can redistribute it and/or modifyion 2.0 (the "License");
7 * it under the terms of the GNU General Public License as published bypliance with the License.
8 * the Free Software Foundation; either version 3 of the License, or
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 * or see https://www.gnu.org/
18 */
19
20include_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
21if (!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.
22 include_once DOL_DOCUMENT_ROOT.'/admin/remotestore/class/PSWebServiceLibrary.class.php';
23}
24
25
30{
35 public $start;
36
41 public $end;
42
46 public $per_page;
50 public $categorie;
54 public $categories; // an array of categories
55
59 public $search;
60
61 // setups
65 public $url; // the url of this page
69 public $shop_url; // the url of the shop
73 public $lang; // the integer representing the lang in the store
77 public $debug_api; // useful if no dialog
81 public $api;
85 public $products;
86
92 public function __construct($debug = false)
93 {
94 global $langs;
95
96 $this->url = DOL_URL_ROOT.'/admin/modules.php?mode=marketplace';
97 $this->shop_url = 'https://www.dolistore.com/index.php?controller=product&id_product=';
98 $this->debug_api = $debug;
99
100 $langtmp = explode('_', $langs->defaultlang);
101 $lang = $langtmp[0];
102 $lang_array = array('en' => 1, 'fr' => 2, 'es' => 3, 'it' => 4, 'de' => 5); // Into table ps_lang of Prestashop - 1
103 if (!in_array($lang, array_keys($lang_array))) {
104 $lang = 'en';
105 }
106 $this->lang = $lang_array[$lang];
107 }
108
115 public function getRemoteCategories()
116 {
117 global $conf;
118
119 try {
120 $this->api = new PrestaShopWebservice(getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV'), getDolGlobalString('MAIN_MODULE_DOLISTORE_API_KEY'), $this->debug_api);
121 dol_syslog("Call API with MAIN_MODULE_DOLISTORE_API_SRV = ".getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV'));
122 // conf MAIN_MODULE_DOLISTORE_API_KEY is for the login of basic auth. There is no password as it is public data.
123
124 // Here we set the option array for the Webservice : we want categories resources
125 $opt = array();
126 $opt['resource'] = 'categories';
127 $opt['display'] = '[id,id_parent,nb_products_recursive,active,is_root_category,name,description]';
128 $opt['sort'] = 'id_asc';
129
130 // Call
131 dol_syslog("Call API with opt = ".var_export($opt, true));
132 $xml = $this->api->get($opt);
133 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
134 $this->categories = $xml->categories->children();
135 } catch (PrestaShopWebserviceException $e) {
136 // Here we are dealing with errors
137 $trace = $e->getTrace();
138 if ($trace[0]['args'][0] == 404) {
139 die('Bad ID');
140 } elseif ($trace[0]['args'][0] == 401) {
141 die('Bad auth key');
142 } else {
143 print 'Can not access to ' . getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV').'<br>';
144 print $e->getMessage();
145 }
146 }
147 }
148
156 public function getRemoteProducts($options = array('start' => 0, 'end' => 10, 'per_page' => 50, 'categorie' => 0, 'search' => ''))
157 {
158 global $conf;
159
160 $this->start = $options['start'];
161 $this->end = $options['end'];
162 $this->per_page = $options['per_page'];
163 $this->categorie = $options['categorie'];
164 $this->search = $options['search'];
165
166 if ($this->end == 0) {
167 $this->end = $this->per_page;
168 }
169
170 try {
171 $this->api = new PrestaShopWebservice(getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV'), getDolGlobalString('MAIN_MODULE_DOLISTORE_API_KEY'), $this->debug_api);
172 dol_syslog("Call API with MAIN_MODULE_DOLISTORE_API_SRV = ".getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV'));
173 // conf MAIN_MODULE_DOLISTORE_API_KEY is for the login of basic auth. There is no password as it is public data.
174
175 // Here we set the option array for the Webservice : we want products resources
176 $opt = array();
177 $opt['resource'] = 'products';
178 $opt2 = array();
179
180 // make a search to limit the id returned.
181 if ($this->search != '') {
182 $opt2['url'] = getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV') . '/api/search?query='.$this->search.'&language='.$this->lang; // It seems for search, key start with
183
184 // Call
185 dol_syslog("Call API with opt2 = ".var_export($opt2, true));
186 $xml = $this->api->get($opt2);
187
188 $products = array();
189 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
190 foreach ($xml->products->children() as $product) {
191 $products[] = (int) $product['id'];
192 }
193 $opt['filter[id]'] = '['.implode('|', $products).']';
194 } elseif ($this->categorie != 0) { // We filter on category, so we first get list of product id in this category
195 // $opt2['url'] is set by default to $this->url.'/api/'.$options['resource'];
196 $opt2['resource'] = 'categories';
197 $opt2['id'] = $this->categorie;
198
199 // Call
200 dol_syslog("Call API with opt2 = ".var_export($opt2, true));
201 $xml = $this->api->get($opt2);
202
203 $products = array();
204 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
205 foreach ($xml->category->associations->products->children() as $product) {
206 $products[] = (int) $product->id;
207 }
208 $opt['filter[id]'] = '['.implode('|', $products).']';
209 }
210 $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]';
211 $opt['sort'] = 'id_desc';
212 $opt['filter[active]'] = '[1]';
213 $opt['limit'] = "$this->start,$this->end";
214 // $opt['filter[id]'] contains list of product id that are result of search
215
216 // Call API to get the detail
217 dol_syslog("Call API with opt = ".var_export($opt, true));
218 $xml = $this->api->get($opt);
219 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
220 $this->products = $xml->products->children();
221 } catch (PrestaShopWebserviceException $e) {
222 // Here we are dealing with errors
223 $trace = $e->getTrace();
224 if ($trace[0]['args'][0] == 404) {
225 die('Bad ID');
226 } elseif ($trace[0]['args'][0] == 401) {
227 die('Bad auth key');
228 } else {
229 print 'Can not access to ' . getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV').'<br>';
230 print $e->getMessage();
231 }
232 }
233 }
234
235 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
242 public function get_categories($parent = 0)
243 {
244 // phpcs:enable
245 if (!isset($this->categories)) {
246 die('not possible');
247 }
248 if ($parent != 0) {
249 $html = '<ul>';
250 } else {
251 $html = '';
252 }
253
254 $nbofcateg = count($this->categories);
255 for ($i = 0; $i < $nbofcateg; $i++) {
256 $cat = $this->categories[$i];
257
258 if ((string) $cat->name->language[$this->lang - 1] == 'Goodies') {
259 continue;
260 }
261
262 if ($cat->is_root_category == 1 && $parent == 0) {
263 $html .= '<li class="root"><h3 class="nomargesupinf marginleftonly"><a class="nomargesupinf link2cat" href="?mode=marketplace&categorie='.((int) $cat->id).'" ';
264 $html .= 'title="'.dol_escape_htmltag(strip_tags($cat->description->language[$this->lang - 1])).'">';
265 //$html .= dol_escape_htmltag($cat->name->language[$this->lang - 1]);
266 $html .= 'DoliStore';
267 $html .= ' &nbsp;<span class="opacitymedium small valignmiddle">('.dol_escape_htmltag($cat->nb_products_recursive).')</span></a></h3>';
268 $html .= self::get_categories((int) $cat->id);
269 $html .= "</li>\n";
270 } elseif (trim($cat->id_parent) == $parent && $cat->active == 1 && trim($cat->id_parent) != 0) { // si cat est de ce niveau
271 $select = ($cat->id == $this->categorie) ? ' selected' : '';
272 $html .= '<li><a class="link2cat'.$select.'" href="?mode=marketplace&categorie='.((int) $cat->id).'"';
273 $html .= ' title="'.dol_escape_htmltag(strip_tags($cat->description->language[$this->lang - 1])).'" ';
274 $html .= '>'.dol_escape_htmltag($cat->name->language[$this->lang - 1]);
275 $html .= ' &nbsp;<span class="opacitymedium small valignmiddle">('.dol_escape_htmltag($cat->nb_products_recursive).')</span></a>';
276 $html .= self::get_categories((int) $cat->id);
277 $html .= "</li>\n";
278 }
279 }
280
281 if ($html == '<ul>') {
282 return '';
283 }
284 if ($parent != 0) {
285 return $html.'</ul>';
286 } else {
287 return $html;
288 }
289 }
290
291 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
298 public function get_products($nbmaxtoshow = 10)
299 {
300 // phpcs:enable
301 global $langs;
302
303 $html = "";
304 $last_month = dol_now() - (30 * 24 * 60 * 60);
305 $dolibarrversiontouse = DOL_VERSION;
306 //$dolibarrversiontouse = 20.0;
307
308 $i = 0;
309 foreach ($this->products as $product) {
310 $i++;
311 if ($i > $nbmaxtoshow) {
312 break;
313 }
314
315 // check new product ?
316 $newapp = '';
317 if ($last_month < strtotime($product->date_add)) {
318 $newapp .= '<span class="newApp">'.$langs->trans('New').'</span> ';
319 }
320
321 // check updated ?
322 if ($last_month < strtotime($product->date_upd) && $newapp == '') {
323 $newapp .= '<span class="updatedApp">'.$langs->trans('Updated').'</span> ';
324 }
325
326 // add image or default ?
327 if ($product->id_default_image != '') {
328 $image_url = DOL_URL_ROOT.'/admin/remotestore/ajax/image.php?id_product='.urlencode((string) (((int) $product->id))).'&id_image='.urlencode((string) (((int) $product->id_default_image)));
329 $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).'">';
330 $images .= '<img class="imgstore" src="'.$image_url.'&quality=home_default" alt="" /></a>';
331 } else {
332 $images = '<img class="imgstore" src="'.DOL_URL_ROOT.'/admin/dolistore/img/NoImageAvailable.png" />';
333 }
334
335 // free or pay ?
336 if ($product->price > 0) {
337 $price = '<h3>'.price(price2num($product->price, 'MT'), 0, $langs, 1, -1, -1, 'EUR').' '.$langs->trans("HT").'</h3>';
338 $download_link = '<a target="_blank" href="'.$this->shop_url.urlencode($product->id).'"><img width="32" src="'.DOL_URL_ROOT.'/admin/remotestore/img/follow.png" /></a>';
339 } else {
340 $price = '<h3>'.$langs->trans('Free').'</h3>';
341 $download_link = '<a class="paddingleft paddingright" target="_blank" href="'.$this->shop_url.urlencode($product->id).'"><img width="32" src="'.DOL_URL_ROOT.'/admin/remotestore/img/follow.png" /></a>';
342 $download_link .= '<a class="paddingleft paddingright" 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>';
343 }
344
345 // Set and check version
346 $version = '';
347 if ($this->version_compare($product->dolibarr_min, $dolibarrversiontouse) <= 0) {
348 if ($this->version_compare($product->dolibarr_max, $dolibarrversiontouse) >= 0) {
349 //compatible
350 $version = '<span class="compatible">'.$langs->trans(
351 'CompatibleUpTo',
352 $product->dolibarr_max,
353 $product->dolibarr_min,
354 $product->dolibarr_max
355 ).'</span>';
356 $compatible = '';
357 } else {
358 //never compatible, module expired
359 $version = '<span class="notcompatible">'.$langs->trans(
360 'NotCompatible',
361 $dolibarrversiontouse,
362 $product->dolibarr_min,
363 $product->dolibarr_max
364 ).'</span>';
365 $compatible = 'NotCompatible';
366 }
367 } else {
368 //need update
369 $version = '<span class="compatibleafterupdate">'.$langs->trans(
370 'CompatibleAfterUpdate',
371 $dolibarrversiontouse,
372 $product->dolibarr_min,
373 $product->dolibarr_max
374 ).'</span>';
375 $compatible = 'NotCompatible';
376 }
377
378 //output template
379 $html .= '<tr class="app oddeven '.dol_escape_htmltag($compatible).'">';
380 $html .= '<td class="center" width="160"><div class="newAppParent">';
381 $html .= $newapp.$images; // No dol_escape_htmltag, it is already escape html
382 $html .= '</div></td>';
383 $html .= '<td class="margeCote"><h2 class="appTitle">';
384 $html .= dol_escape_htmltag(dol_string_nohtmltag($product->name->language[$this->lang - 1]));
385 $html .= '<br><small>';
386 $html .= $version; // No dol_escape_htmltag, it is already escape html
387 $html .= '</small></h2>';
388 $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>';
389 $html .= '<br>'.dol_escape_htmltag(dol_string_nohtmltag($product->description_short->language[$this->lang - 1]));
390 $html.= '</td>';
391 // do not load if display none
392 $html .= '<td class="margeCote center amount">';
393 $html .= $price;
394 $html .= '</td>';
395 $html .= '<td class="margeCote nowraponall">'.$download_link.'</td>';
396 $html .= '</tr>';
397 }
398
399 if (empty($this->products)) {
400 $html .= '<tr class=""><td colspan="3" class="center">';
401 $html .= '<br><br>';
402 $langs->load("website");
403 $html .= $langs->trans("noResultsWereFound").'...';
404 $html .= '<br><br>';
405 $html .= '</td></tr>';
406 }
407
408 if (count($this->products) > $nbmaxtoshow) {
409 $html .= '<tr class=""><td colspan="3" class="center">';
410 $html .= '<br><br>';
411 $html .= $langs->trans("ThereIsMoreThanXAnswers", $nbmaxtoshow).'...';
412 $html .= '<br><br>';
413 $html .= '</td></tr>';
414 }
415
416 return $html;
417 }
418
419 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
426 public function get_previous_link($text = '<<')
427 {
428 // phpcs:enable
429 return '<a href="'.$this->get_previous_url().'" class="button">'.dol_escape_htmltag($text).'</a>';
430 }
431
432 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
439 public function get_next_link($text = '>>')
440 {
441 // phpcs:enable
442 return '<a href="'.$this->get_next_url().'" class="button">'.dol_escape_htmltag($text).'</a>';
443 }
444
445 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
451 public function get_previous_url()
452 {
453 // phpcs:enable
454 $param_array = array();
455 if ($this->start < $this->per_page) {
456 $sub = 0;
457 } else {
458 $sub = $this->per_page;
459 }
460 $param_array['start'] = $this->start - $sub;
461 $param_array['end'] = $this->end - $sub;
462 if ($this->categorie != 0) {
463 $param_array['categorie'] = $this->categorie;
464 }
465 $param = http_build_query($param_array);
466 return $this->url."&".$param;
467 }
468
469 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
475 public function get_next_url()
476 {
477 // phpcs:enable
478 $param_array = array();
479 if ($this->products !== null && count($this->products) < $this->per_page) {
480 $add = 0;
481 } else {
482 $add = $this->per_page;
483 }
484 $param_array['start'] = $this->start + $add;
485 $param_array['end'] = $this->end + $add;
486 if ($this->categorie != 0) {
487 $param_array['categorie'] = $this->categorie;
488 }
489 $param = http_build_query($param_array);
490 return $this->url."&".$param;
491 }
492
493 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
501 public function version_compare($v1, $v2)
502 {
503 // phpcs:enable
504 $v1 = explode('.', $v1);
505 $v2 = explode('.', $v2);
506 $ret = 0;
507 $level = 0;
508 $count1 = count($v1);
509 $count2 = count($v2);
510 $maxcount = max($count1, $count2);
511 while ($level < $maxcount) {
512 $operande1 = isset($v1[$level]) ? $v1[$level] : 'x';
513 $operande2 = isset($v2[$level]) ? $v2[$level] : 'x';
514 $level++;
515 if (strtoupper($operande1) == 'X' || strtoupper($operande2) == 'X' || $operande1 == '*' || $operande2 == '*') {
516 break;
517 }
518 if ($operande1 < $operande2) {
519 $ret = -$level;
520 break;
521 }
522 if ($operande1 > $operande2) {
523 $ret = $level;
524 break;
525 }
526 }
527 //print join('.',$versionarray1).'('.count($versionarray1).') / '.join('.',$versionarray2).'('.count($versionarray2).') => '.$ret.'<br>'."\n";
528 return $ret;
529 }
530}
Class Dolistore.
getRemoteCategories()
Load data from remote Dolistore market place.
get_next_url()
get next url
__construct($debug=false)
Constructor.
get_categories($parent=0)
Return tree of Dolistore categories.
get_next_link($text='> >')
get next link
version_compare($v1, $v2)
version compare
get_previous_url()
get previous url
get_products($nbmaxtoshow=10)
Return list of product formatted for output.
get_previous_link($text='<<')
get previous link
getRemoteProducts($options=array('start'=> 0, 'end'=> 10, 'per_page'=> 50, 'categorie'=> 0, 'search'=> ''))
Load data from remote Dolistore market place.
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:431
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_now($mode='auto')
Return date for now.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79