You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

prix_objets_fonctions.php 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. <?php
  2. /**
  3. * Fonctions utiles au plugin Prix Objets
  4. *
  5. * @plugin Prix Objets
  6. * @copyright 2012 - 2019
  7. * @author Rainer Müller
  8. * @licence GNU/GPL
  9. * @package SPIP\Promotions_commandes\Fonctions
  10. */
  11. // Sécurité
  12. if (!defined('_ECRIRE_INC_VERSION'))
  13. return;
  14. include_spip('base/abstract_sql');
  15. /**
  16. * Un tableau des devises dispoibles.
  17. *
  18. * @return array
  19. * Les devises disponibles.
  20. */
  21. function devises() {
  22. $devises = array(
  23. // A
  24. 'AUD' => 'AUD',
  25. // B
  26. 'BRL' => 'Real',
  27. // C
  28. 'CAD' => 'CAD',
  29. 'CHF' => 'CHF',
  30. 'CNY' => 'Yuan',
  31. 'CSD' => 'CSD',
  32. 'CZK' => 'CZK',
  33. // D
  34. 'DKK' => 'DKK',
  35. // E
  36. 'EUR' => '€',
  37. // G
  38. 'GBP' => '£',
  39. // H
  40. 'HKD' => 'HKD',
  41. 'HUF' => 'HUF',
  42. // I
  43. 'IDR' => 'IDR',
  44. 'ILS' => 'Shekel',
  45. 'IQD' => 'IQD',
  46. 'IRR' => 'IRR',
  47. 'ISK' => 'ISK',
  48. // J
  49. 'JEP' => 'JEP',
  50. 'JOD' => 'JOD',
  51. 'JMD' => 'JMD',
  52. 'JPY' => '¥',
  53. // K
  54. 'KES' => 'KES',
  55. 'KGS' => 'KGS',
  56. 'KWD' => 'KWD',
  57. 'KZT' => 'Tenge',
  58. // L
  59. 'LAK' => 'Kip',
  60. 'LBP' => 'LBP',
  61. 'LKR' => 'LKR',
  62. 'LRD' => 'LRD',
  63. 'LTL' => 'Litas',
  64. 'LVL' => 'Lat',
  65. // M
  66. 'MAD' => 'Dirham',
  67. 'MDL' => 'MDL',
  68. 'MGA' => 'Ariary',
  69. 'MKD' => 'MKD',
  70. 'MNT' => 'Tughrik',
  71. 'MRO' => 'Ouguiya',
  72. 'MUR' => 'MUR',
  73. 'MVR' => 'Rufiyaa',
  74. 'MWK' => 'MWK',
  75. 'MXN' => 'MXN',
  76. 'MYR' => 'Ringgit',
  77. 'MZN' => 'Metical',
  78. // N
  79. 'NAD' => 'NAD',
  80. 'NGN' => 'Naira',
  81. 'NIO' => 'Cordoba',
  82. 'NPR' => 'NPR',
  83. 'NOK' => 'NOK',
  84. 'NZD' => 'NZD',
  85. // O
  86. 'OMR' => 'OMR',
  87. 'QAR' => 'Riyal',
  88. // P
  89. 'PGK' => 'Kina',
  90. 'PHP' => 'PHP',
  91. 'PKR' => 'PKR',
  92. 'PLN' => 'Zloty',
  93. 'RON' => 'RON',
  94. 'RUB' => 'Rouble',
  95. 'RWF' => 'RWF',
  96. // S
  97. 'SCR' => 'SCR',
  98. 'SDD' => 'SDD',
  99. 'SEK' => 'SEK',
  100. 'SGD' => 'SGD',
  101. 'SOS' => 'SOS',
  102. 'SLL' => 'Leone',
  103. 'SRD' => 'SRD',
  104. 'STD' => 'Dobra',
  105. 'SVC' => 'Colon',
  106. 'SYP' => 'SYP',
  107. // T
  108. 'THB' => 'Baht',
  109. 'TJS' => 'Somoni',
  110. 'TND' => 'TND',
  111. 'TMM' => 'TMM',
  112. 'TRY' => 'Lirasi',
  113. 'TTD' => 'TTD',
  114. 'TWD' => 'TWD',
  115. 'TZS' => 'TZS',
  116. // U
  117. 'UAH' => 'Hryvna',
  118. 'UGX' => 'UGX',
  119. 'USD' => 'USD',
  120. 'UZS' => 'UZS',
  121. // V
  122. 'VND' => 'Dong',
  123. // X
  124. 'XAF' => 'XAF',
  125. 'XOF' => 'XOF',
  126. // Y
  127. 'YER' => 'Rial',
  128. // Z
  129. 'ZMK' => 'ZMK',
  130. 'ZWN' => 'ZWN'
  131. );
  132. return $devises;
  133. }
  134. /**
  135. * Affiche le symbole de la devise si disponible
  136. *
  137. * @param string $code_devise
  138. * @return string
  139. */
  140. function traduire_devise($code_devise) {
  141. include_spip('inc/devises');
  142. $devises = devises();
  143. $trad = $devises[$code_devise];
  144. return $trad;
  145. }
  146. /**
  147. * Donne le prix d'un objet avec sa devise.
  148. *
  149. * @deprecated 2.3.0 Utilisez prix_objet_formate($id_objet, $objet = 'article');
  150. * @param integer $id_objet
  151. * L'identifiant de l'objet
  152. * @param string $objet
  153. * L'objet
  154. *
  155. * @return string
  156. * Le prix formaté.
  157. */
  158. function prix_defaut($id_objet, $objet = 'article') {
  159. prix_objet_formate($id_objet, $objet);
  160. }
  161. /**
  162. * Donne le prix d'un objet avec sa devise
  163. *
  164. * @param integer $id_objet
  165. * L'identifiant de l'objet
  166. * @param string $objet
  167. * L'objet
  168. *
  169. * @return string
  170. * Le prix formaté.
  171. */
  172. function prix_objet_formate($id_objet, $objet = 'article') {
  173. $req = sql_fetsel('code_devise,prix', 'spip_prix_objets', 'id_objet=' . $id_objet . ' AND objet=' . sql_quote($objet));
  174. $devise = isset($reg['code_devise']) ? $reg['code_devise'] : '';
  175. $prix = filtres_prix_formater($req['prix'], $devise));
  176. return $prix;
  177. }
  178. /**
  179. * Ajoute la devise à un prix
  180. *
  181. * @param mixed $prix
  182. * Le prix
  183. * @param boolean $traduire
  184. * Afficher le symbole de la devis, défaut true.
  185. *
  186. * @return string
  187. * Le prix avec la devise
  188. */
  189. function devise_defaut_prix($prix = '', $traduire = true) {
  190. if ($_COOKIE['spip_devise']) {
  191. $devise_defaut = $_COOKIE['spip_devise'];
  192. }
  193. else {
  194. $devise_defaut = $devise_defaut = prix_objets_devise_defaut();
  195. }
  196. $devise_defaut = traduire_devise($devise_defaut);
  197. if ($prix) {
  198. $devise_defaut = $prix . ' ' . $devise_defaut;
  199. }
  200. return $devise_defaut;
  201. }
  202. /**
  203. * Donne le prix d'un objet avec sa devise.
  204. *
  205. * @deprecated 2.3.0 Utilisez prix_objet_formate($id_objet, $objet = 'article');
  206. * @param integer $id_objet
  207. * L'identifiant de l'objet
  208. * @param string $objet
  209. * L'objet
  210. *
  211. * @return string
  212. * Le prix formaté.
  213. */
  214. function devise_defaut_objet($id_objet, $objet = 'article') {
  215. prix_objet_formate($id_objet, $objet);
  216. }
  217. function rubrique_prix($id = '', $objet = 'article', $sousrubriques = false) {
  218. include_spip('inc/config');
  219. include_spip('prive/formulaires/selecteur/generique_fonctions');
  220. $rubrique_produit = picker_selected(lire_config('prix_objets/rubrique_prix', array()), 'rubrique');
  221. if ($rubrique_produit) {
  222. $id_parent = $rubrique_produit;
  223. if (!$sousrubriques) {
  224. $rubriques = $id_parent;
  225. }
  226. else {
  227. $rubriques = array();
  228. }
  229. $rubriques = rubriques_enfant($id_parent, $rubriques);
  230. if ($id) {
  231. $retour = sql_getfetsel('id_' . $objet, 'spip_' . $objet . 's', 'id_' . $objet . '=' . $id . ' AND id_rubrique IN (' . implode(',', $rubriques) . ')');
  232. }
  233. else {
  234. $retour = $rubriques;
  235. }
  236. }
  237. else {
  238. return false;
  239. }
  240. return $retour;
  241. }
  242. function rubriques_enfant($id_parent, $rubriques = array()) {
  243. $id_p = '';
  244. if (is_array($id_parent)) {
  245. $id_parent = implode(',', $id_parent);
  246. }
  247. if ($id_parent) {
  248. $sql = sql_select('id_rubrique', 'spip_rubriques', 'id_parent IN (' . $id_parent . ')');
  249. }
  250. $id_p = array();
  251. while ($row = sql_fetch($sql)) {
  252. $id_p[] = $row['id_rubrique'];
  253. $rubriques[] = $row['id_rubrique'];
  254. }
  255. if (count($id_p) > 0) {
  256. $rubriques = rubriques_enfant($id_p, $rubriques);
  257. }
  258. return $rubriques;
  259. }
  260. /**
  261. * Surcharge de la fonction filtres_prix_formater_dist du plugin prix.
  262. * Formate le prix en y ajoutant la devise.
  263. *
  264. * @param string $prix
  265. * @param string $devise
  266. * @param integer $decimals
  267. * @return string
  268. */
  269. function filtres_prix_formater($prix, $devise = '') {
  270. include_spip('inc/config');
  271. include_spip('inc/cookie');
  272. $config = lire_config('prix_objets');
  273. if (!$devise) {
  274. $devises = isset($config['devises']) ? $config['devises'] : array();
  275. // Si il y a un cookie 'devise_selectionnee' et qu'il figure parmis les devises disponibles on le prend
  276. if (isset($_COOKIE['devise_selectionnee']) and in_array($_COOKIE['devise_selectionnee'], $devises)) {
  277. $devise = $_COOKIE['devise_selectionnee'];
  278. $GLOBALS['devise_defaut'] = $devise;
  279. } // Sinon on regarde si il ya une devise defaut valable
  280. else {
  281. $devise = prix_objets_devise_defaut($config);
  282. }
  283. }
  284. // On met le cookie
  285. spip_setcookie('devise_selectionnee', $devise, time() + 3660 * 24 * 365, '/');
  286. // On détermine la langue du contexte
  287. if (isset($_COOKIE['spip_lang'])) {
  288. $lang = $_COOKIE['spip_lang'];
  289. }
  290. else {
  291. $lang = lire_config('langue_site');
  292. }
  293. // Si PECL intl est présent on dermine le format de l'affichage de la devise selon la langue du contexte
  294. if (function_exists('numfmt_create') and is_float($prix)) {
  295. $fmt = numfmt_create($lang, NumberFormatter::CURRENCY);
  296. $prix = numfmt_format_currency($fmt, $prix, $devise);
  297. } // Sinon à la française
  298. else {
  299. $prix = $prix . '&nbsp;' . traduire_devise($devise);
  300. }
  301. return $prix;
  302. }
  303. /**
  304. * Détermine la devise par défaut
  305. *
  306. * @param array $config
  307. * Les donnes de configuration de prix_objets
  308. * @return string Code de la devise
  309. */
  310. function prix_objets_devise_defaut($config = '') {
  311. if (!$config) {
  312. include_spip('inc/config');
  313. $config = lire_config('prix_objets');
  314. }
  315. $devises = isset($config['devises']) ? $config['devises'] : array();
  316. // Sinon on regarde si il ya une devise defaut valable
  317. if ($config['devise_default']) {
  318. $devise_defaut = $config['devise_default'];
  319. } // Sinon on prend la première des devises choisies
  320. elseif (isset($devises[0])) {
  321. $devise_defaut = $devises[0];
  322. } // Sinon on met l'Euro
  323. else {
  324. $devise_defaut = 'EUR';
  325. }
  326. return $devise_defaut;
  327. }
  328. /**
  329. * Donne le prix pour un objet
  330. *
  331. * @param string $objet
  332. * Objet dont on cherche le prix
  333. * @param string $id_objet
  334. * Identifiant de l'objet dont on cherche le prix
  335. * @param array $contexte
  336. * Les variables de l'environnement utilisées dans le calcul du prix.
  337. * @param string $type
  338. * prix (ttc) ou prix_ht
  339. * @param array $options
  340. * mode: 'global' ou 'prorata'
  341. *
  342. * @return string Le prix applicable.
  343. */
  344. function prix_par_objet($objet, $id_objet, $contexte, $type = 'prix_ht', $options = array()) {
  345. $prix = 0;
  346. if ($type == 'prix_ht') {
  347. $fonction_prix = charger_fonction('ht', 'inc/prix');
  348. }
  349. else {
  350. $fonction_prix = charger_fonction('prix', 'inc');
  351. }
  352. // Le mode de calcul de prix, ou passé dans les options, ou depuis la config.
  353. if (isset($options['mode']) and !empty($options['mode'])) {
  354. $mode = $options['mode'];
  355. }
  356. else {
  357. include_spip('inc/config');
  358. $mode = lire_config('prix_objets/prix_par_objet_mode', 'global');
  359. }
  360. if ($mode == 'prorata') {
  361. $horaire = isset($options['horaire']) ? $options['horaire'] : '';
  362. $format = isset($options['date_format']) ? $options['date_format'] : '';
  363. $sequence = isset($options['sequence']) ? $options['sequence'] : '';
  364. if (!$sequence) {
  365. // Séquence composé de dates.
  366. if (isset($contexte['date_debut']) and
  367. isset($contexte['date_fin']) and
  368. include_spip('filtres/dates_outils') and
  369. function_exists('dates_intervalle')) {
  370. $sequence = dates_intervalle($contexte['date_debut'], $contexte['date_fin'], 0, -1, $horaire, $format);
  371. }
  372. else {
  373. $sequence = array();
  374. }
  375. }
  376. $nr_elements_sequence = count($sequence);
  377. $contexte['date_fin'] = $contexte['date_debut'];
  378. }
  379. else {
  380. $nr_elements_sequence = 0;
  381. }
  382. $prix_source = sql_allfetsel(
  383. 'id_prix_objet,prix_total,titre',
  384. 'spip_prix_objets',
  385. 'id_prix_objet_source=0 AND objet LIKE ' . sql_quote(trim($objet)) . ' AND id_objet=' . $id_objet, '',
  386. array(
  387. 'rang_lien',
  388. 'titre',
  389. 'prix_ht'
  390. )
  391. );
  392. // On parcours les extension pour chaque prix principal.
  393. $prix_elements = array();
  394. foreach ($prix_source as $index => $data_source) {
  395. $id_prix_objet = $data_source['id_prix_objet'];
  396. // passer l'info sur le prix total dans l'environnement
  397. set_request('prix_total', $data_source['prix_total']);
  398. $extensions = sql_allfetsel('extension,id_extension,titre', 'spip_prix_objets', 'id_prix_objet_source=' . $id_prix_objet);
  399. $prix = $fonction_prix('prix_objet', $id_prix_objet);
  400. $count_sextensions = count($extensions);
  401. // Si il y a des extensions.
  402. if ($count_sextensions > 0) {
  403. $i = 0;
  404. $applicables = array();
  405. $dates_applicables = array();
  406. // On établit l'extension qui définit le prix.
  407. foreach ($extensions as $data_extension) {
  408. $i ++;
  409. $id_extension = $data_extension['id_extension'];
  410. if ($extension = charger_fonction($data_extension['extension'], 'prix_objet/', TRUE)) {
  411. switch ($mode) {
  412. // Si global on met les resultats positiv dans un simple tableau.
  413. case 'global':
  414. if ($applicable = $extension($id_extension, $contexte, $mode)) {
  415. $applicables[] = $applicable;
  416. }
  417. break;
  418. // Si prorata on détermine quels éléments de séquences sont applicables.
  419. case 'prorata':
  420. if (is_array($sequence)) {
  421. foreach ($sequence as $index => $element) {
  422. $contexte['date_debut'] = $element;
  423. $contexte['date_fin'] = $element;
  424. if ($applicable = $extension($id_extension, $contexte, $mode)) {
  425. $dates_applicables[$element][$index][] = $applicable;
  426. }
  427. }
  428. }
  429. break;
  430. }
  431. }
  432. else {
  433. $applicables[] = 1;
  434. }
  435. }
  436. // mode de calcul global
  437. if ($mode == 'global') {
  438. // On choisit le premier prix qui est applicable pour chaque extension.
  439. if (count($applicables) == $count_sextensions) {
  440. break;
  441. }
  442. }
  443. // mode de calcul prorata
  444. elseif ($mode == "prorata" and is_array($dates_applicables)) {
  445. // On établit un prix pour éléement de séquence, puis on enlève l'élément de la séquence.
  446. foreach ($dates_applicables as $element => $applicables) {
  447. foreach ($applicables as $index => $counter) {
  448. if (array_sum($counter) >= $count_sextensions) {
  449. $prix_elements[$element] = $prix;
  450. unset($sequence[$index]);
  451. }
  452. }
  453. }
  454. }
  455. }
  456. }
  457. // Si mode prorata on calcule le prix à partir des prix par élément
  458. if ($mode == "prorata") {
  459. $nr_prix_prorata = count($prix_elements);
  460. $sum_prix_prorata = array_sum($prix_elements);
  461. // Si on a un prix pour chaque élément de séquence
  462. if ($nr_prix_prorata == $nr_elements_sequence) {
  463. // Si il y a des éléments de séquence, on divise la somme par le nombre d'élément.
  464. if ($nr_elements_sequence > 0) {
  465. $prix = $sum_prix_prorata / $nr_elements_sequence;
  466. }
  467. }
  468. // Sinon on divise la somme par le nombre de prix, on ajoute le prix par défaut (le dernier)
  469. // et on divise par deux
  470. elseif ($nr_prix_prorata > 0) {
  471. $prix = (($sum_prix_prorata / $nr_prix_prorata) + $prix) / 2;
  472. }
  473. }
  474. // Permettre d'intervenir sur le prix
  475. return pipeline('prix_par_objet', array(
  476. 'data' => $prix,
  477. 'args' => array(
  478. 'objet' => $objet,
  479. 'id_objet' => $id_objet,
  480. 'contexte' => $contexte,
  481. 'type' => $type,
  482. 'options' => $options
  483. )
  484. ));
  485. }