· 4 years ago · Apr 26, 2021, 08:02 PM
1<?php
2/***************************************************************************
3* *
4* (c) 2018 powerES *
5****************************************************************************/
6
7use Tygh\BlockManager\Layout;
8use Tygh\Development;
9use Tygh\Embedded;
10use Tygh\Exceptions\PHPErrorException;
11use Tygh\Exceptions\InitException;
12use Tygh\Registry;
13use Tygh\Debugger;
14use Tygh\Storage;
15use Tygh\Settings;
16use Tygh\Snapshot;
17use Tygh\SmartyEngine\Core as SmartyCore;
18use Tygh\Ajax;
19use Tygh\Api;
20use Tygh\Api\Response;
21use Tygh\Themes\Styles;
22use Tygh\Tools\DateTimeHelper;
23
24if (!defined('BOOTSTRAP')) { die('Access denied'); }
25
26/**
27 * Init template engine
28 *
29 * @return boolean always true
30 */
31function fn_init_templater($area = AREA)
32{
33 $auth = Tygh::$app['session']['auth'];
34 $view = new SmartyCore();
35 \SmartyException::$escape = false;
36
37 /**
38 * Change templater pre-init parameters
39 *
40 * @param object $view Templater object
41 */
42 fn_set_hook('init_templater', $view);
43
44 $view->_dir_perms = DEFAULT_DIR_PERMISSIONS;
45 $view->_file_perms = DEFAULT_FILE_PERMISSIONS;
46
47 $view->registerResource('tygh', new Tygh\SmartyEngine\FileResource());
48
49 // resource for shared templates loaded from backend
50 $view->registerResource('backend', new Tygh\SmartyEngine\BackendResource());
51
52 if ($area == 'A') {
53
54 if (!empty($auth['user_id'])) {
55 // Auto-tooltips for admin panel
56 $view->registerFilter('pre', array('Tygh\SmartyEngine\Filters', 'preFormTooltip'));
57
58 if (fn_allowed_for('ULTIMATE')) {
59 // Enable sharing for objects
60 $view->registerFilter('output', array('Tygh\SmartyEngine\Filters', 'outputSharing'));
61 }
62 }
63
64 $view->registerFilter('pre', array('Tygh\SmartyEngine\Filters', 'preScript'));
65 }
66
67 if ($area == 'C') {
68 $view->registerFilter('pre', array('Tygh\SmartyEngine\Filters', 'preTemplateWrapper'));
69
70 if (Registry::get('runtime.customization_mode.design')) {
71 $view->registerFilter('output', array('Tygh\SmartyEngine\Filters', 'outputTemplateIds'));
72 }
73
74 if (Registry::get('runtime.customization_mode.live_editor')) {
75 $view->registerFilter('output', array('Tygh\SmartyEngine\Filters', 'outputLiveEditorWrapper'));
76 }
77
78 $view->registerFilter('output', array('Tygh\SmartyEngine\Filters', 'outputScript'));
79 }
80
81 if (Embedded::isEnabled()) {
82 $view->registerFilter('output', array('Tygh\SmartyEngine\Filters', 'outputEmbeddedUrl'));
83 }
84
85 // CSRF form protection
86 if (fn_is_csrf_protection_enabled($auth)) {
87 $view->registerFilter('output', array('Tygh\SmartyEngine\Filters', 'outputSecurityHash'));
88 }
89
90 // Language variable retrieval optimization
91 $view->registerFilter('post', array('Tygh\SmartyEngine\Filters', 'postTranslation'));
92
93 $smarty_plugins_dir = $view->getPluginsDir();
94 $view->setPluginsDir(Registry::get('config.dir.functions') . 'smarty_plugins');
95 $view->addPluginsDir($smarty_plugins_dir);
96
97 $view->error_reporting = E_ALL & ~E_NOTICE;
98
99 $view->registerDefaultPluginHandler(array('Tygh\SmartyEngine\Filters', 'smartyDefaultHandler'));
100
101 $view->setArea($area);
102 $view->use_sub_dirs = false;
103 $view->compile_check = (Development::isEnabled('compile_check') || Debugger::isActive() || fn_is_development()) ? true : false;
104 $view->setLanguage(CART_LANGUAGE);
105
106 $view->assign('ldelim', '{');
107 $view->assign('rdelim', '}');
108
109 $view->assign('currencies', Registry::get('currencies'), false);
110 $view->assign('primary_currency', CART_PRIMARY_CURRENCY, false);
111 $view->assign('secondary_currency', CART_SECONDARY_CURRENCY, false);
112 $view->assign('languages', Registry::get('languages'));
113
114 if ($area == 'A') {
115 $view->assign('addon_permissions_text', fn_get_addon_permissions_text());
116 }
117
118 if (!fn_allowed_for('ULTIMATE:FREE')) {
119 $view->assign('localizations', fn_get_localizations(CART_LANGUAGE , true));
120 if (defined('CART_LOCALIZATION')) {
121 $view->assign('localization', fn_get_localization_data(CART_LOCALIZATION));
122 }
123 }
124
125 if (defined('THEMES_PANEL')) {
126 if (fn_allowed_for('ULTIMATE')) {
127 $storefronts = db_get_array('SELECT storefront, company, company_id FROM ?:companies');
128 Registry::set('demo_theme.storefronts', $storefronts);
129 }
130 $view->assign('demo_theme', Registry::get('demo_theme'));
131 }
132
133 $view->assignByRef('app', Tygh::$app);
134 Tygh::$app['view'] = $view;
135
136 /**
137 * Change templater parameters
138 *
139 * @param object $view Templater object
140 */
141 fn_set_hook('init_templater_post', $view);
142
143 return array(INIT_STATUS_OK);
144}
145
146/**
147 * Init crypt engine
148 *
149 * @return boolean always true
150 */
151function fn_init_crypt()
152{
153 Tygh::$app['crypt'] = function ($app) {
154 return new Crypt_Blowfish(Registry::get('config.crypt_key'));
155 };
156
157 return true;
158}
159
160/**
161 * Init ajax engine
162 *
163 * @return boolean true if current request is ajax, false - otherwise
164 */
165function fn_init_ajax()
166{
167 if (defined('AJAX_REQUEST')) {
168 return array(INIT_STATUS_OK);
169 }
170
171 Embedded::init();
172
173 if (Ajax::validateRequest($_REQUEST)) {
174 Tygh::$app['ajax'] = new Ajax($_REQUEST);
175 fn_define('AJAX_REQUEST', true);
176 }
177
178 return array(INIT_STATUS_OK);
179}
180
181/**
182 * Init languages
183 *
184 * @param array $params request parameters
185 * @return boolean always true
186 */
187function fn_init_language($params, $area = AREA)
188{
189 $default_language = Registry::get('settings.Appearance.' . fn_get_area_name($area) . '_default_language');
190 $session_language = fn_get_session_data('cart_language' . $area);
191
192 $show_hidden_languages = $area != 'C' ? true : false;
193 $avail_languages = fn_get_avail_languages($area, $show_hidden_languages);
194
195 if (!empty($params['sl']) && !empty($avail_languages[$params['sl']])) {
196 fn_define('CART_LANGUAGE', $params['sl']);
197 } elseif ($session_language && !empty($avail_languages[$session_language])) {
198 fn_define('CART_LANGUAGE', $session_language);
199 } elseif ($_lc = fn_get_browser_language($avail_languages)) {
200 fn_define('CART_LANGUAGE', $_lc);
201 } elseif (!empty($avail_languages[$default_language])) {
202 fn_define('CART_LANGUAGE', $default_language);
203 } else {
204 reset($avail_languages);
205 fn_define('CART_LANGUAGE', key($avail_languages));
206 }
207
208 // For the backend, set description language
209 if (!empty($params['descr_sl']) && !empty($avail_languages[$params['descr_sl']])) {
210 fn_define('DESCR_SL', $params['descr_sl']);
211 fn_set_session_data('descr_sl', $params['descr_sl'], COOKIE_ALIVE_TIME);
212 } elseif (($d = fn_get_session_data('descr_sl')) && !empty($avail_languages[$d])) {
213 fn_define('DESCR_SL', $d);
214 } else {
215 fn_define('DESCR_SL', CART_LANGUAGE);
216 }
217
218 if (CART_LANGUAGE != $session_language) {
219 fn_set_session_data('cart_language' . $area, CART_LANGUAGE, COOKIE_ALIVE_TIME);
220
221 // set language_changed flag only if $session_language was set before
222 if (Embedded::isEnabled() && defined('AJAX_REQUEST') && $session_language) {
223 Tygh::$app['ajax']->assign('language_changed', true);
224 }
225 }
226
227 Registry::set('languages', $avail_languages);
228
229 return array(INIT_STATUS_OK);
230}
231
232/**
233 * Init company data
234 * Company data array will be saved in the registry runtime.company_data
235 *
236 * @param array $params request parameters
237 * @return array with init data (init status, redirect url in case of redirect)
238 */
239function fn_init_company_data($params)
240{
241 $company_data = array(
242 'company' => __('all_vendors'),
243 );
244
245 $company_id = Registry::get('runtime.company_id');
246 if ($company_id) {
247 $company_data = fn_get_company_data($company_id);
248 }
249
250 fn_set_hook('init_company_data', $params, $company_id, $company_data);
251
252 Registry::set('runtime.company_data', $company_data);
253
254 return array(INIT_STATUS_OK);
255}
256
257/**
258 * Init selected company
259 * Selected company id will be saved in the registry runtime.company_id
260 *
261 * @param array $params request parameters
262 * @return array with init data (init status, redirect url in case of redirect)
263 */
264function fn_init_company_id(&$params)
265{
266 $company_id = 0;
267 $available_company_ids = array();
268 $result = array(INIT_STATUS_OK);
269
270 if (isset($params['switch_company_id'])) {
271 $switch_company_id = intval($params['switch_company_id']);
272 } else {
273 $switch_company_id = false;
274 }
275
276 if (defined('API')) {
277 $api = Tygh::$app['api'];
278 $api_response_status = false;
279 if ($api instanceof Api) {
280 if (AREA == 'A') {
281 if ($user_data = $api->getUserData()) {
282 $company_id = 0;
283
284 if ($user_data['company_id']) {
285 $company_id = $user_data['company_id'];
286 }
287
288 $store = array();
289 if (preg_match('/(stores|vendors)\/(\d+)\/.+/', $api->getRequest()->getResource(), $store)) {
290
291 if ($company_id && $company_id != $store[2]) {
292 $api_response_status = Response::STATUS_FORBIDDEN;
293 }
294
295 $company_id = intval($store[2]);
296 if (!fn_get_available_company_ids($company_id)) {
297 $company_id = 0;
298 }
299 }
300 } else {
301 $api_response_status = Response::STATUS_UNAUTHORIZED;
302 }
303 }
304 } else {
305 $api_response_status = Response::STATUS_FORBIDDEN;
306 }
307
308 if ($api_response_status) {
309 $response = new Response($api_response_status);
310 /**
311 * Here is exit.
312 */
313 $response->send();
314 }
315 }
316 // set company_id for vendor's admin
317 if (AREA == 'A' && !empty(Tygh::$app['session']['auth']['company_id'])) {
318 $company_id = intval(Tygh::$app['session']['auth']['company_id']);
319 $available_company_ids = array($company_id);
320 if (!fn_get_available_company_ids($company_id)) {
321 return fn_init_company_id_redirect($params, 'access_denied');
322 }
323 }
324
325 // admin switching company_id
326 if (!$company_id) {
327 if ($switch_company_id !== false) { // request not empty
328 if ($switch_company_id) {
329 if (fn_get_available_company_ids($switch_company_id)) {
330 $company_id = $switch_company_id;
331 } else {
332 return fn_init_company_id_redirect($params, 'company_not_found');
333 }
334 }
335 fn_set_session_data('company_id', $company_id, COOKIE_ALIVE_TIME);
336 } else {
337 $company_id = fn_init_company_id_find_in_session();
338 }
339 }
340
341 if (empty($available_company_ids)) {
342 $available_company_ids = fn_get_available_company_ids();
343 }
344
345 fn_set_hook('init_company_id', $params, $company_id, $available_company_ids, $result);
346
347 Registry::set('runtime.company_id', $company_id);
348 Registry::set('runtime.companies_available_count', count($available_company_ids));
349
350 unset($params['switch_company_id']);
351
352 return $result;
353}
354
355/**
356 * Form error notice and make redirect. Used in fn_init_company_id
357 *
358 * @param array $params request parameters
359 * @param string $message language variable name for message
360 * @param int $redirect_company_id New company id for redirecting, if null, company id saved in session will be used
361 * @return array with init data (init status, redirect url in case of redirect)
362 */
363function fn_init_company_id_redirect(&$params, $message, $redirect_company_id = null)
364{
365 if ('access_denied' == $message) {
366
367 Tygh::$app['session']['auth'] = array();
368 $redirect_url = 'auth.login_form' . (!empty($params['return_url']) ? '?return_url=' . urldecode($params['return_url']) : '');
369
370 } elseif ('company_not_found' == $message) {
371
372 $dispatch = !empty($params['dispatch']) ? $params['dispatch'] : 'auth.login_form';
373 unset($params['dispatch']);
374 $params['switch_company_id'] = (null === $redirect_company_id) ? fn_init_company_id_find_in_session() : $redirect_company_id;
375
376 $redirect_url = $dispatch . '?' . http_build_query($params);
377 }
378
379 if (!defined('CART_LANGUAGE')) {
380 fn_init_language($params); // we need CART_LANGUAGE in Tygh\Languages\Values::getLangVar()
381 fn_init_currency($params); // we need CART_SECONDARY_CURRENCY in Tygh\Languages\Values::getLangVar()
382 $params['dispatch'] = 'index.index'; // we need dispatch in Tygh\Languages\Values::getLangVar()
383 }
384 fn_set_notification('E', __('error'), __($message));
385
386 return array(INIT_STATUS_REDIRECT, $redirect_url);
387}
388
389/**
390 * Tryes to find company id in session
391 *
392 * @return int Company id if stored in session, 0 otherwise
393 */
394function fn_init_company_id_find_in_session()
395{
396 $session_company_id = intval(fn_get_session_data('company_id'));
397 if ($session_company_id && !fn_get_available_company_ids($session_company_id)) {
398 fn_delete_session_data('company_id');
399 $session_company_id = 0;
400 }
401
402 return $session_company_id;
403}
404
405/**
406 * Init currencies
407 *
408 * @param array $params request parameters
409 * @param string $area Area ('A' for admin or 'C' for customer)
410 * @return boolean always true
411 */
412function fn_init_currency($params, $area = AREA)
413{
414 /**
415 * Performs actions before initializing currencies
416 *
417 * @param array $params request parameters
418 * @param string $area Area ('A' for admin or 'C' for customer)
419 */
420 fn_set_hook('init_currency_pre', $params, $area);
421
422 $_params = array();
423 if (fn_allowed_for('ULTIMATE:FREE')) {
424 $_params['only_primary'] = 'Y';
425 } else {
426 $_params['status'] = array('A', 'H');
427 }
428
429 $currencies = fn_get_currencies_list($_params, $area, CART_LANGUAGE);
430
431 $primary_currency = '';
432
433 foreach ($currencies as $v) {
434 if ($v['is_primary'] == 'Y') {
435 $primary_currency = $v['currency_code'];
436 break;
437 }
438 }
439
440 if (empty($primary_currency)) { // Restore primary currency if it empty
441 $primary_currencies = fn_get_currencies_list(
442 array('only_primary' => true, 'raw_query' => true), $area, CART_LANGUAGE
443 );
444 foreach ($primary_currencies as $key => $currency) {
445 $primary_currencies[$key]['status'] = 'H'; // Hide unavailable currencies
446 }
447 $currencies = fn_sort_array_by_key($currencies + $primary_currencies, 'position');
448 $primary_currency = key($primary_currencies);
449 }
450
451 if (!empty($params['currency']) && !empty($currencies[$params['currency']])) {
452 $secondary_currency = $params['currency'];
453 } elseif (($c = fn_get_session_data('secondary_currency' . $area)) && !empty($currencies[$c])) {
454 $secondary_currency = $c;
455 } else {
456 $secondary_currency = $primary_currency;
457 }
458
459 if (empty($secondary_currency)) {
460 reset($currencies);
461 $secondary_currency = key($currencies);
462 }
463
464 if ($secondary_currency != fn_get_session_data('secondary_currency' . $area)) {
465 fn_set_session_data('secondary_currency' . $area, $secondary_currency, COOKIE_ALIVE_TIME);
466 }
467
468 // Hide secondary currency in frontend if it is hidden
469 if ($area == 'C' && $currencies[$secondary_currency]['status'] != 'A') {
470 $first_currency = '';
471 foreach ($currencies as $key => $currency) {
472 if ($currency['status'] != 'A' && $currency['is_primary'] != 'Y') {
473 unset($currencies[$key]);
474 } elseif ($currency['status'] == 'A' && !$first_currency) {
475 $first_currency = $currency;
476 }
477 }
478 $secondary_currency = $first_currency['currency_code'];
479 }
480
481 /**
482 * Sets currencies
483 *
484 * @param array $params request parameters
485 * @param string $area Area ('A' for admin or 'C' for customer)
486 * @param string $primary_currency Primary currency code
487 * @param string $secondary_currency Secondary currency code
488 */
489 fn_set_hook('init_currency_post', $params, $area, $primary_currency, $secondary_currency);
490
491 define('CART_PRIMARY_CURRENCY', $primary_currency);
492 define('CART_SECONDARY_CURRENCY', $secondary_currency);
493
494 Registry::set('currencies', $currencies);
495
496 return array(INIT_STATUS_OK);
497}
498
499/**
500 * Init layout
501 *
502 * @param array $params request parameters
503 * @return boolean always true
504 */
505function fn_init_layout($params)
506{
507 if (fn_allowed_for('ULTIMATE')) {
508 if (!Registry::get('runtime.company_id') && !Registry::get('runtime.simple_ultimate')) {
509 return array(INIT_STATUS_OK);
510 }
511 }
512
513 $key_name = 'stored_layout' . (Embedded::isEnabled() ? '_embedded' : '');
514 $stored_layout = fn_get_session_data($key_name);
515
516 if (!empty($params['s_layout'])) {
517 $stored_layout = $params['s_layout'];
518
519 fn_set_session_data($key_name, $params['s_layout']);
520 }
521
522 // Replace default theme with selected for current area
523 if (!empty($stored_layout)) {
524 $layout = Layout::instance()->get($stored_layout);
525
526 if (!isset($layout['theme_name']) || $layout['theme_name'] != fn_get_theme_path('[theme]', 'C')) {
527 unset($layout);
528 }
529 }
530
531 if (empty($layout)) {
532 $layout = Layout::instance()->getDefault(); // get default
533 }
534
535 $available_styles = Styles::factory($layout['theme_name'])->getList(array(
536 'short_info' => true
537 ));
538
539 if (!isset($available_styles[$layout['style_id']])) {
540 $layout['style_id'] = Styles::factory($layout['theme_name'])->getDefault();
541 }
542
543 /**
544 * Executes before storing viewed layout data into Registry, allows to modify layout data.
545 *
546 * @param array $params Request parameters
547 * @param array $layout Layout data
548 */
549 fn_set_hook('init_layout', $params, $layout);
550
551 Registry::set('runtime.layout', $layout);
552
553 return array(INIT_STATUS_OK);
554}
555
556/**
557 * Init user
558 *
559 * @return boolean always true
560 */
561function fn_init_user($area = AREA)
562{
563 $user_info = array();
564 if (!empty(Tygh::$app['session']['auth']['user_id'])) {
565 $user_info = fn_get_user_short_info(Tygh::$app['session']['auth']['user_id']);
566 if (empty($user_info)) { // user does not exist in the database, but exists in session
567 Tygh::$app['session']['auth'] = array();
568 } else {
569 Tygh::$app['session']['auth']['usergroup_ids'] = fn_define_usergroups(array(
570 'user_id' => Tygh::$app['session']['auth']['user_id'],
571 'user_type' => $user_info['user_type']
572 ));
573 }
574 }
575
576 $first_init = false;
577 if (empty(Tygh::$app['session']['auth'])) {
578
579 $udata = array();
580 $user_id = fn_get_session_data($area . '_user_id');
581
582 if ($area == 'A' && defined('CONSOLE')) {
583 $user_id = 1;
584 }
585
586 if ($user_id) {
587 fn_define('LOGGED_VIA_COOKIE', true);
588 }
589
590 fn_login_user($user_id);
591
592 if (!defined('NO_SESSION')) {
593 Tygh::$app['session']['cart'] = isset(Tygh::$app['session']['cart']) ? Tygh::$app['session']['cart'] : array();
594 }
595
596 if ((defined('LOGGED_VIA_COOKIE') && !empty(Tygh::$app['session']['auth']['user_id'])) || ($cu_id = fn_get_session_data('cu_id'))) {
597 $first_init = true;
598 if (!empty($cu_id)) {
599 fn_define('COOKIE_CART' , true);
600 }
601
602 // Cleanup cached shipping rates
603
604 unset(Tygh::$app['session']['shipping_rates']);
605
606 $_utype = empty(Tygh::$app['session']['auth']['user_id']) ? 'U' : 'R';
607 $_uid = empty(Tygh::$app['session']['auth']['user_id']) ? $cu_id : Tygh::$app['session']['auth']['user_id'];
608 fn_extract_cart_content(Tygh::$app['session']['cart'], $_uid , 'C' , $_utype);
609 fn_save_cart_content(Tygh::$app['session']['cart'] , $_uid , 'C' , $_utype);
610 if (!empty(Tygh::$app['session']['auth']['user_id'])) {
611 Tygh::$app['session']['cart']['user_data'] = fn_get_user_info(Tygh::$app['session']['auth']['user_id']);
612 $user_info = fn_get_user_short_info(Tygh::$app['session']['auth']['user_id']);
613 }
614 }
615 }
616
617 if (fn_is_expired_storage_data('cart_products_next_check', SECONDS_IN_HOUR * 12)) {
618 db_query("DELETE FROM ?:user_session_products WHERE user_type = 'U' AND timestamp < ?i", (TIME - SECONDS_IN_DAY * 30));
619 }
620
621 if (!fn_allowed_for('ULTIMATE:FREE')) {
622 // If administrative account has usergroup, it means the access restrictions are in action
623 if ($area == 'A' && !empty(Tygh::$app['session']['auth']['usergroup_ids'])) {
624 fn_define('RESTRICTED_ADMIN', true);
625 }
626 }
627
628 if (!empty($user_info) && $user_info['user_type'] == 'A' && (empty($user_info['company_id']) || (fn_allowed_for('ULTIMATE') && $user_info['company_id'] == Registry::get('runtime.company_id')))) {
629 $customization_mode = fn_array_combine(explode(',', Registry::get('settings.customization_mode')), true);
630 if (!empty($customization_mode)) {
631 Registry::set('runtime.customization_mode', $customization_mode);
632
633 if ($area == 'A' || Embedded::isEnabled()) {
634 Registry::set('runtime.customization_mode.live_editor', false);
635 }
636 }
637 }
638
639 fn_set_hook('user_init', Tygh::$app['session']['auth'], $user_info, $first_init);
640
641 Registry::set('user_info', $user_info);
642
643 return array(INIT_STATUS_OK);
644}
645
646/**
647 * Init localizations
648 *
649 * @param array $params request parameters
650 * @return boolean true if localizations exists, false otherwise
651 */
652function fn_init_localization($params)
653{
654 if (AREA != 'C') {
655 return array(INIT_STATUS_OK);
656 }
657
658 $locs = db_get_hash_array("SELECT localization_id, custom_weight_settings, weight_symbol, weight_unit FROM ?:localizations WHERE status = 'A'", 'localization_id');
659
660 if (!empty($locs)) {
661 if (!empty($_REQUEST['lc']) && !empty($locs[$_REQUEST['lc']])) {
662 $cart_localization = $_REQUEST['lc'];
663
664 } elseif (($l = fn_get_session_data('cart_localization')) && !empty($locs[$l])) {
665 $cart_localization = $l;
666
667 } else {
668 $_ip = fn_get_ip(true);
669 $_country = fn_get_country_by_ip($_ip['host']);
670 $_lngs = db_get_hash_single_array("SELECT lang_code, 1 as 'l' FROM ?:languages WHERE status = 'A'", array('lang_code', 'l'));
671 $_language = fn_get_browser_language($_lngs);
672
673 $cart_localization = db_get_field("SELECT localization_id, COUNT(localization_id) as c FROM ?:localization_elements WHERE (element = ?s AND element_type = 'C') OR (element = ?s AND element_type = 'L') GROUP BY localization_id ORDER BY c DESC LIMIT 1", $_country, $_language);
674
675 if (empty($cart_localization) || empty($locs[$cart_localization])) {
676 $cart_localization = db_get_field("SELECT localization_id FROM ?:localizations WHERE status = 'A' AND is_default = 'Y'");
677 }
678 }
679
680 if (empty($cart_localization)) {
681 reset($locs);
682 $cart_localization = key($locs);
683 }
684
685 if ($cart_localization != fn_get_session_data('cart_localization')) {
686 fn_set_session_data('cart_localization', $cart_localization, COOKIE_ALIVE_TIME);
687 }
688
689 if ($locs[$cart_localization]['custom_weight_settings'] == 'Y') {
690 Registry::set('config.localization.weight_symbol', $locs[$cart_localization]['weight_symbol']);
691 Registry::set('config.localization.weight_unit', $locs[$cart_localization]['weight_unit']);
692 }
693
694 fn_define('CART_LOCALIZATION', $cart_localization);
695 }
696
697 return array(INIT_STATUS_OK);
698}
699
700/**
701 * Detect user agent
702 *
703 * @return boolean true always
704 */
705function fn_init_ua()
706{
707 static $crawlers = array(
708 'google', 'bot', 'yahoo',
709 'spider', 'archiver', 'curl',
710 'python', 'nambu', 'Twitterbot',
711 'perl', 'sphere', 'PEAR',
712 'java', 'wordpress', 'radian',
713 'crawl', 'yandex', 'eventbox',
714 'monitor', 'mechanize', 'facebookexternal'
715 );
716
717 $http_ua = fn_strtolower($_SERVER['HTTP_USER_AGENT']);
718
719 if (strpos($http_ua, 'shiretoko') !== false || strpos($http_ua, 'firefox') !== false) {
720 $ua = 'firefox';
721 } elseif (strpos($http_ua, 'chrome') !== false) {
722 $ua = 'chrome';
723 } elseif (strpos($http_ua, 'safari') !== false) {
724 $ua = 'safari';
725 } elseif (strpos($http_ua, 'opera') !== false) {
726 $ua = 'opera';
727 } elseif (strpos($http_ua, 'msie') !== false || strpos($http_ua, 'trident/7.0; rv:11.0') !== false) {
728 // IE11 does not send normal headers and seems like Mozilla:
729 // Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
730 $ua = 'ie';
731 if (preg_match("/msie (6|7|8)/i", $http_ua)) {
732 Registry::set('runtime.unsupported_browser', true);
733 }
734 } elseif (preg_match('/(' . implode('|', $crawlers) . ')/', $http_ua, $m)) {
735 $ua = 'crawler';
736 fn_define('CRAWLER', $m[1]);
737 fn_define('NO_SESSION', true); // do not start session for crawler
738 } else {
739 $ua = 'unknown';
740 }
741
742 if (isset($_REQUEST['no_session']) && $_REQUEST['no_session'] === 'Y') {
743 fn_define('NO_SESSION', true);
744 }
745
746 fn_define('USER_AGENT', $ua);
747
748 return array(INIT_STATUS_OK);
749}
750
751function fn_check_cache($params)
752{
753 $regenerated = true;
754 $dir_root = Registry::get('config.dir.root') . '/';
755
756 if (isset($params['ct']) && ((AREA == 'A' && !(fn_allowed_for('MULTIVENDOR') && Registry::get('runtime.company_id'))) || Debugger::isActive() || fn_is_development())) {
757 Storage::instance('images')->deleteDir('thumbnails');
758 }
759
760 // Clean up cache
761 if (isset($params['cc']) && ((AREA == 'A' && !(fn_allowed_for('MULTIVENDOR') && Registry::get('runtime.company_id'))) || Debugger::isActive() || fn_is_development())) {
762 fn_clear_cache();
763 }
764
765 // Clean up templates cache
766 if (isset($params['ctpl']) && ((AREA == 'A' && !(fn_allowed_for('MULTIVENDOR') && Registry::get('runtime.company_id'))) || Debugger::isActive() || fn_is_development())) {
767 fn_clear_template_cache();
768 }
769
770 if (!in_array(AREA, array('A', 'V'))) {
771 return array(INIT_STATUS_OK);
772 }
773
774 return array(INIT_STATUS_OK);
775}
776
777function fn_init_settings()
778{
779 Registry::registerCache('settings', array('settings_objects', 'settings_vendor_values', 'settings_descriptions', 'settings_sections', 'settings_variants'), Registry::cacheLevel('static'));
780 if (Registry::isExist('settings') == false) {
781 $settings = Settings::instance()->getValues();
782
783 // Deprecated: workaround for old security settings
784 $settings['Security']['secure_auth'] = $settings['Security']['secure_storefront'] == 'partial' ? 'Y' : 'N';
785 $settings['Security']['secure_checkout'] = $settings['Security']['secure_storefront'] == 'partial' ? 'Y' : 'N';
786
787 Registry::set('settings', $settings);
788 }
789
790 //initialization remote settings for compatibility with third-party addons
791 //deprecated settings
792 $default_elements = Registry::get('settings.Appearance.admin_elements_per_page');
793 Registry::set('settings.Appearance.admin_products_per_page', $default_elements);
794 Registry::set('settings.Appearance.admin_orders_per_page', $default_elements);
795 Registry::set('settings.Appearance.admin_pages_per_page', $default_elements);
796
797 fn_init_time_zone(Registry::get('settings.Appearance.timezone'));
798
799 fn_define('DEFAULT_LANGUAGE', Registry::get('settings.Appearance.backend_default_language'));
800
801 return array(INIT_STATUS_OK);
802}
803
804/**
805 * Sets the given timezone as the PHP runtime timezone and as the current MySQL connection timezone.
806 *
807 * @param string $time_zone_name The name of a timezone like "Europe/London"
808 */
809function fn_init_time_zone($time_zone_name)
810{
811 $valid_timezone_identifiers = timezone_identifiers_list();
812
813 if (is_array($valid_timezone_identifiers) && in_array($time_zone_name, $valid_timezone_identifiers)) {
814 date_default_timezone_set($time_zone_name);
815 $offset_string = DateTimeHelper::getTimeZoneOffsetString($time_zone_name);
816
817 if ($offset_string) {
818 db_query('SET time_zone = ?s', $offset_string);
819 } else {
820 error_log("Unable to get timezone offset for {$time_zone_name}");
821 }
822 }
823}
824
825/**
826 * Initialize all enabled addons
827 *
828 * @return array INIT_STATUS_OK
829 */
830function fn_init_addons()
831{
832 Registry::registerCache(
833 'addons',
834 array(
835 'addons', 'settings_objects', 'settings_vendor_values',
836 'settings_descriptions', 'settings_sections', 'settings_variants'
837 ),
838 Registry::cacheLevel('static')
839 );
840
841 if (Registry::isExist('addons') == false) {
842 $init_addons = Registry::get('settings.init_addons');
843 $allowed_addons = null;
844
845 if ($init_addons == 'none') {
846 $allowed_addons = array();
847 } elseif ($init_addons == 'core') {
848 $allowed_addons = Snapshot::getCoreAddons();
849 }
850
851 $_addons = db_get_hash_array("SELECT addon, priority, status, unmanaged FROM ?:addons WHERE 1 ORDER BY priority", 'addon');
852
853 foreach ($_addons as $k => $v) {
854 $_addons[$k] = Settings::instance()->getValues($v['addon'], Settings::ADDON_SECTION, false);
855 if (fn_check_addon_snapshot($k)) {
856 $_addons[$k]['status'] = $v['status'];
857 } else {
858 $_addons[$k]['status'] = 'D';
859 }
860
861 if ($allowed_addons !== null && !in_array($v['addon'], $allowed_addons)) {
862 $_addons[$k]['status'] = 'D';
863 }
864
865 $_addons[$k]['priority'] = $v['priority'];
866 $_addons[$k]['unmanaged'] = $v['unmanaged'];
867 }
868
869 // Some addons could be disabled for vendors.
870 if (fn_allowed_for('MULTIVENDOR') && Registry::get('runtime.company_id')) {
871 Registry::set('addons', $_addons);
872
873 // So, we have to parse it one more time
874 foreach ($_addons as $k => $v) {
875 // and check permissions schema.
876 // We couldn't make it in the previous cycle because the fn_get_scheme func works only with full list of addons.
877 if (!fn_check_addon_permission($k)) {
878 unset($_addons[$k]);
879 }
880 }
881 }
882
883 Registry::set('addons', $_addons);
884 }
885
886 foreach ((array) Registry::get('addons') as $addon_name => $data) {
887 if (empty($data['status'])) {
888 // FIX ME: Remove me
889 error_log("ERROR: Addons initialization: Bad '$addon_name' addon data:" . serialize($data) . " Addons Registry:" . serialize(Registry::get('addons')));
890 }
891 if (!empty($data['status']) && $data['status'] == 'A') {
892 fn_load_addon($addon_name);
893 }
894 }
895
896 Registry::set('addons_initiated', true, true);
897
898 return array(INIT_STATUS_OK);
899}
900
901/**
902 * Initialize unmanaged addons
903 *
904 * @return array INIT_STATUS_OK
905 */
906function fn_init_unmanaged_addons()
907{
908 // Do not use cache here, because company ID is not initialized yet
909 $addons = db_get_fields("SELECT addon FROM ?:addons WHERE unmanaged = 1 AND status = 'A' ORDER BY priority");
910
911 foreach ($addons as $addon_name) {
912 fn_load_addon($addon_name);
913 }
914
915 return array(INIT_STATUS_OK);
916}
917
918function fn_init_full_path($request)
919{
920 // Display full paths cresecure payment processor
921 if (isset($request['display_full_path']) && ($request['display_full_path'] == 'Y')) {
922 define('DISPLAY_FULL_PATHS', true);
923 Registry::set('config.full_host_name', (defined('HTTPS') ? 'https://' . Registry::get('config.https_host') : 'http://' . Registry::get('config.http_host')));
924 } else {
925 Registry::set('config.full_host_name', '');
926 }
927
928 return array(INIT_STATUS_OK);
929}
930
931function fn_init_stack()
932{
933 $stack = Registry::get('init_stack');
934 if (empty($stack)) {
935 $stack = array();
936 }
937
938 $stack_data = func_get_args();
939
940 foreach ($stack_data as $data) {
941 $stack[] = $data;
942 }
943
944 Registry::set('init_stack', $stack);
945
946 return true;
947}
948
949/**
950 * Run init functions
951 *
952 * @param array $request $_REQUEST global variable
953 * @return bool always true
954 */
955function fn_init(&$request)
956{
957 // New init functions can be added to stack while init
958 while ($stack = Registry::get('init_stack')) {
959 $function_data = array_shift($stack);
960 $function = array_shift($function_data);
961
962 // Remove function from stack
963 Registry::set('init_stack', $stack);
964
965 if (!is_callable($function)) {
966 continue;
967 }
968
969 $result = call_user_func_array($function, $function_data);
970
971 $status = !empty($result[0]) ? $result[0] : INIT_STATUS_OK;
972 $url = !empty($result[1]) ? $result[1] : '';
973 $message = !empty($result[2]) ? $result[2] : '';
974 $permanent = !empty($result[3]) ? $result[3] : '';
975
976 if ($status == INIT_STATUS_OK && !empty($url)) {
977 $redirect_url = $url;
978
979 } elseif ($status == INIT_STATUS_REDIRECT && !empty($url)) {
980 $redirect_url = $url;
981 break;
982
983 } elseif ($status == INIT_STATUS_FAIL) {
984 if (empty($message)) {
985 $message = 'Initialization failed in <b>' . (is_array($function) ? implode('::', $function) : $function) . '</b> function';
986 }
987
988 throw new InitException($message);
989 }
990 }
991
992 if (!empty($redirect_url)) {
993 if (!defined('CART_LANGUAGE')) {
994 fn_init_language($request); // we need CART_LANGUAGE in fn_url function that called in fn_redirect
995 }
996 fn_redirect($redirect_url, true, !empty($permanent));
997 }
998
999 Debugger::init(true);
1000
1001 return true;
1002}
1003
1004/**
1005 * Init paths for storage store data (mse, saas)
1006 *
1007 * @return boolean true always
1008 */
1009function fn_init_storage()
1010{
1011 fn_set_hook('init_storage');
1012
1013 $storage = Settings::instance()->getValue('storage', '');
1014
1015 Registry::set('runtime.storage', unserialize($storage));
1016
1017 Registry::set('config.images_path', Storage::instance('images')->getUrl()); // FIXME this path should be removed
1018
1019 return array(INIT_STATUS_OK);
1020}
1021
1022/**
1023 * Init api object and put it to Application container.
1024 */
1025function fn_init_api()
1026{
1027 Tygh::$app['api'] = new Api();
1028
1029 return array(INIT_STATUS_OK);
1030}
1031
1032/**
1033 * Registers image manipulation library object at Application container.
1034 *
1035 * @return array
1036 */
1037function fn_init_imagine()
1038{
1039 Tygh::$app['image'] = function ($app) {
1040
1041 $driver = Registry::ifGet('config.tweaks.image_resize_lib', 'gd');
1042
1043 if ($driver == 'auto') {
1044 try {
1045 return new Imagine\Imagick\Imagine();
1046 } catch (\Exception $e) {
1047 try {
1048 return new Imagine\Gd\Imagine();
1049 } catch (\Exception $e) {
1050 return null;
1051 }
1052 }
1053 } else {
1054 switch ($driver) {
1055 case 'gd':
1056 return new Imagine\Gd\Imagine();
1057 break;
1058 case 'imagick':
1059 return new Imagine\Imagick\Imagine();
1060 break;
1061 }
1062 }
1063 };
1064
1065 return array(INIT_STATUS_OK);
1066}
1067
1068/**
1069 * Registers archiver object at Application container.
1070 *
1071 * @return array
1072 */
1073function fn_init_archiver()
1074{
1075 Tygh::$app['archiver'] = function ($app) {
1076 return new \Tygh\Tools\Archiver();
1077 };
1078
1079 return array(INIT_STATUS_OK);
1080}
1081
1082/**
1083 * Registers custom error handlers
1084 *
1085 * @return array
1086 */
1087function fn_init_error_handler()
1088{
1089 // Fatal error handler
1090 defined('AREA') && AREA == 'C' && register_shutdown_function(function () {
1091 $error = error_get_last();
1092
1093 // Check whether error is fatal (i.e. couldn't have been catched with trivial error handler)
1094 if (isset($error['type']) &&
1095 in_array($error['type'], array(
1096 E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
1097 ))
1098 ) {
1099 // Try to hide PHP's fatal error message
1100 fn_clear_ob();
1101
1102 $exception = new PHPErrorException($error['message'], $error['type'], $error['file'], $error['line']);
1103 $exception->output();
1104
1105 exit(1);
1106 }
1107 });
1108
1109 // Non-fatal errors, warnings and notices are caught and properly formatted
1110 defined('DEVELOPMENT')
1111 && DEVELOPMENT
1112 && !extension_loaded('xdebug')
1113 && set_error_handler(function($code, $message, $filename, $line) {
1114 if (error_reporting() & $code) {
1115 switch ($code) {
1116 // Non-fatal errors, code execution wouldn't be stopped
1117 case E_NOTICE:
1118 case E_USER_NOTICE:
1119 case E_WARNING:
1120 case E_USER_WARNING:
1121 case E_DEPRECATED:
1122 case E_USER_DEPRECATED:
1123 $exception = new PHPErrorException($message, $code, $filename, $line);
1124 $exception->output();
1125
1126 error_log(addslashes((string) $exception), 0);
1127
1128 return true;
1129 break;
1130 }
1131 }
1132
1133 // Let PHP's internal error handler handle other cases
1134 return false;
1135 });
1136
1137 return array(INIT_STATUS_OK);
1138}
1139