Exemplo n.º 1
0
function fn_print_shipment_packing_slips($shipment_ids, $pdf = false, $lang_code = CART_LANGUAGE)
{
    $view = Tygh::$app['view'];
    $month = array(1 => 'Января', 2 => 'Февраля', 3 => 'Марта', 4 => 'Апреля', 5 => 'Мая', 6 => 'Июня', 7 => 'Июля', 8 => 'Августа', 9 => 'Сентября', 10 => 'Октября', 11 => 'Ноября', 12 => 'Декабря');
    foreach ($shipment_ids as $shipment_id) {
        list($shipment, $order_info) = fn_get_packing_info($shipment_id);
        $order_info_ = fn_get_order_info($order_info['order_id']);
        if (empty($shipment)) {
            continue;
        }
        $total_weight = 0;
        // foreach($order_info['products'] as $pi=>$pv)
        // {
        //     $total_weight+=$pv['weight'];
        // }
        $order_info['payment_info'] = $order_info_['payment_info'];
        $order_info['payment_method'] = $order_info_['payment_method'];
        $order_info['timestamp'] = $order_info_['timestamp'];
        $order_info['info_customer'] = "";
        $n_month = (int) date("m", $order_info['timestamp']);
        $invoice_date = date("d", $order_info['timestamp']) . ' ' . $month[$n_month] . ' ' . date("Y", $order_info['timestamp']);
        $order_info['text_invoice_payment'] = __("addons.rus_payments.text_invoice_payment", array('[number_account]' => $order_info['order_id'], '[invoice_data]' => $invoice_date));
        $order_info['invoice_date'] = $invoice_date;
        $products = fn_load_products_extra_data($order_info['products'], array('only_short_fields' => true), 'ru');
        $total_amount = 0;
        //var_dump($products); die();
        foreach ($products as $pi => $pv) {
            $weights[$pi] = $pv['weight'];
            $total_weight += $pv['weight'] * $pv['shipped_amount'];
            $total_amount += $pv['shipped_amount'];
            //var_dump($pv['amount'],'<br/>');
        }
        $order_info['weights'] = $weights;
        $order_info['total_cnt'] = $total_amount;
        $order_info['str_count'] = RusInvoicePayment::clearDoit($total_amount);
        $order_info['str_count'] = str_replace('Один', 'Одно', $order_info['str_count']);
        $order_info['str_count'] = str_replace(array(' 00 копеек', 'рублей', 'рубль', 'рубля'), '', $order_info['str_count']);
        $order_info['total_weight'] = RusInvoicePayment::clearDoit($total_weight);
        $order_info['total_weight'] = str_replace(array('рублей', 'рубль'), 'килограмм', $order_info['total_weight']);
        $order_info['total_weight'] = str_replace('рубля', 'килограмма', $order_info['total_weight']);
        $order_info['total_weight'] = str_replace('копеек', 'грамм', $order_info['total_weight']);
        $order_info['str_total'] = RusInvoicePayment::clearDoit($order_info['display_subtotal']);
        if (!empty($order_info['payment_info'])) {
            if (!empty($order_info['payment_info']['organization_customer'])) {
                $order_info['info_customer'] .= $order_info['payment_info']['organization_customer'] . ' ';
            }
            if (!empty($order_info['payment_info']['inn_customer'])) {
                $order_info['info_customer'] .= __("inn_customer") . ': ' . $order_info['payment_info']['inn_customer'] . ' ';
            }
            if (!empty($order_info['payment_info']['kpp_customer'])) {
                $order_info['info_customer'] .= __("kpp_customer") . ': ' . $order_info['payment_info']['kpp_customer'] . ' ';
            }
            if (!empty($order_info['payment_info']['ogrn_customer'])) {
                $order_info['info_customer'] .= __("ogrn_customer") . ': ' . $order_info['payment_info']['ogrn_customer'] . ' ';
            }
            if (!empty($order_info['payment_info']['phone'])) {
                $order_info['info_customer'] .= __("phone") . ': ' . $order_info['payment_info']['phone'] . ' ';
            }
            if (!empty($order_info['payment_info']['zip_postal_code'])) {
                $order_info['info_customer'] .= __("zip_postal_code") . ': ' . $order_info['payment_info']['zip_postal_code'] . ' ';
            }
            if (!empty($order_info['payment_info']['address'])) {
                $order_info['info_customer'] .= __("address") . ': ' . $order_info['payment_info']['address'] . ' ';
            }
            if (!empty($order_info['payment_info']['bank_details'])) {
                $order_info['info_customer'] .= __("addons.rus_payments.bank_details") . ': ' . $order_info['payment_info']['bank_details'];
            }
        }
        $order_info['info_supplier'] = "";
        $data_payment = $order_info['payment_method']['processor_params'];
        if (!empty($data_payment)) {
            if (!empty($data_payment['account_recepient_name'])) {
                $order_info['info_supplier'] .= $data_payment['account_recepient_name'] . '; ';
            }
            if (!empty($data_payment['account_address'])) {
                $order_info['info_supplier'] .= __("address") . ': ' . $data_payment['account_address'] . '; ';
            }
            if (!empty($data_payment['account_inn'])) {
                $order_info['info_supplier'] .= __("inn_customer") . ': ' . $data_payment['account_inn'] . ' / ';
            }
            if (!empty($data_payment['account_kpp'])) {
                $order_info['info_supplier'] .= __("addons.rus_payments.account_kpp") . ': ' . $data_payment['account_kpp'] . '; ';
            }
            if (!empty($data_payment['account_ogrn'])) {
                $order_info['info_supplier'] .= __("ogrn_customer") . ': ' . $data_payment['account_ogrn'] . '; ';
            }
            if (!empty($data_payment['account_bank'])) {
                $order_info['info_supplier'] .= "Банк" . ': ' . $data_payment['account_bank'] . ' ';
            }
            if (!empty($data_payment['account_current'])) {
                $order_info['info_supplier'] .= "р/с" . ': ' . $data_payment['account_current'] . '; ';
            }
            if (!empty($data_payment['account_cor'])) {
                $order_info['info_supplier'] .= "к/с" . ': ' . $data_payment['account_cor'] . '; ';
            }
            if (!empty($data_payment['account_bik'])) {
                $order_info['info_supplier'] .= "БИК" . ': ' . $data_payment['account_bik'] . '; ';
            }
            // if (!empty($data_payment['account_phone'])) {
            //     $order_info['info_supplier'] .= __("phone") . ': ' . $data_payment['account_phone'] . ' ';
            // }
        }
        $view->assign('order_info', $order_info);
        $view->assign('shipment', $shipment);
        if ($pdf == true) {
            fn_disable_live_editor_mode();
            $html[] = $view->displayMail('orders/print_packing_slip.tpl', false, 'A', $order_info['company_id'], $lang_code);
        } else {
            $view->displayMail('orders/print_packing_slip.tpl', true, 'A', $order_info['company_id'], $lang_code);
            if ($shipment_id != end($shipment_ids)) {
                echo "<div style='page-break-before: always;'>&nbsp;</div>";
            }
        }
    }
    if ($pdf == true) {
        Pdf::render($html, __('shipments') . '-' . implode('-', $shipment_ids));
    }
    return true;
}
Exemplo n.º 2
0
/**
 * Gets products list by search params
 *
 * @param array  $params         Product search params
 * @param int    $items_per_page Items per page
 * @param string $lang_code      Two-letter language code (e.g. 'en', 'ru', etc.)
 * @return array Products list and Search params
 */
function fn_get_products($params, $items_per_page = 0, $lang_code = CART_LANGUAGE)
{
    /**
     * Changes params for selecting products
     *
     * @param array  $params         Product search params
     * @param int    $items_per_page Items per page
     * @param string $lang_code      Two-letter language code (e.g. 'en', 'ru', etc.)
     */
    fn_set_hook('get_products_pre', $params, $items_per_page, $lang_code);
    // Init filter
    $params = LastView::instance()->update('products', $params);
    // Set default values to input params
    $default_params = array('area' => AREA, 'use_caching' => true, 'extend' => array('product_name', 'prices', 'categories'), 'custom_extend' => array(), 'pname' => '', 'pshort' => '', 'pfull' => '', 'pkeywords' => '', 'feature' => array(), 'type' => 'simple', 'page' => 1, 'action' => '', 'filter_variants' => array(), 'features_hash' => '', 'limit' => 0, 'bid' => 0, 'match' => '', 'tracking' => array(), 'get_frontend_urls' => false, 'items_per_page' => $items_per_page);
    if (empty($params['custom_extend'])) {
        $params['extend'] = !empty($params['extend']) ? array_merge($default_params['extend'], $params['extend']) : $default_params['extend'];
    } else {
        $params['extend'] = $params['custom_extend'];
    }
    $params = array_merge($default_params, $params);
    if ((empty($params['pname']) || $params['pname'] != 'Y') && (empty($params['pshort']) || $params['pshort'] != 'Y') && (empty($params['pfull']) || $params['pfull'] != 'Y') && (empty($params['pkeywords']) || $params['pkeywords'] != 'Y') && !empty($params['q'])) {
        $params['pname'] = 'Y';
    }
    $total = !empty($params['total']) ? intval($params['total']) : 0;
    $auth =& $_SESSION['auth'];
    $fields = array('product_id' => 'products.product_id');
    // Define sort fields
    $sortings = array('code' => 'products.product_code', 'status' => 'products.status', 'product' => 'product', 'position' => 'products_categories.position', 'price' => 'price', 'list_price' => 'products.list_price', 'weight' => 'products.weight', 'amount' => 'products.amount', 'timestamp' => 'products.timestamp', 'updated_timestamp' => 'products.updated_timestamp', 'popularity' => 'popularity.total', 'company' => 'company_name', 'null' => 'NULL');
    if (!empty($params['get_subscribers'])) {
        $sortings['num_subscr'] = 'num_subscr';
        $fields['num_subscr'] = 'COUNT(DISTINCT product_subscriptions.subscription_id) as num_subscr';
    }
    if (!empty($params['order_ids'])) {
        $sortings['p_qty'] = 'purchased_qty';
        $sortings['p_subtotal'] = 'purchased_subtotal';
        $fields['purchased_qty'] = "SUM(?:order_details.amount) as purchased_qty";
        $fields['purchased_subtotal'] = "SUM(?:order_details.price * ?:order_details.amount) as purchased_subtotal";
    }
    if (isset($params['compact']) && $params['compact'] == 'Y') {
        $union_condition = ' OR ';
    } else {
        $union_condition = ' AND ';
    }
    $join = $condition = $u_condition = $inventory_condition = '';
    $having = array();
    // Search string condition for SQL query
    if (isset($params['q']) && fn_string_not_empty($params['q'])) {
        $params['q'] = trim($params['q']);
        if ($params['match'] == 'any') {
            $pieces = fn_explode(' ', $params['q']);
            $search_type = ' OR ';
        } elseif ($params['match'] == 'all') {
            $pieces = fn_explode(' ', $params['q']);
            $search_type = ' AND ';
        } else {
            $pieces = array($params['q']);
            $search_type = '';
        }
        if (!empty($params['pcode_from_q'])) {
            $params['pcode'] = $params['q'];
        }
        $_condition = array();
        foreach ($pieces as $piece) {
            if (strlen($piece) == 0) {
                continue;
            }
            $tmp = db_quote("(descr1.search_words LIKE ?l)", '%' . $piece . '%');
            // check search words
            if ($params['pname'] == 'Y') {
                $tmp .= db_quote(" OR descr1.product LIKE ?l", '%' . $piece . '%');
            }
            if ($params['pshort'] == 'Y') {
                $tmp .= db_quote(" OR descr1.short_description LIKE ?l", '%' . $piece . '%');
                $tmp .= db_quote(" OR descr1.short_description LIKE ?l", '%' . htmlentities($piece, ENT_QUOTES, 'UTF-8') . '%');
            }
            if ($params['pfull'] == 'Y') {
                $tmp .= db_quote(" OR descr1.full_description LIKE ?l", '%' . $piece . '%');
                $tmp .= db_quote(" OR descr1.full_description LIKE ?l", '%' . htmlentities($piece, ENT_QUOTES, 'UTF-8') . '%');
            }
            if ($params['pkeywords'] == 'Y') {
                $tmp .= db_quote(" OR (descr1.meta_keywords LIKE ?l OR descr1.meta_description LIKE ?l)", '%' . $piece . '%', '%' . $piece . '%');
            }
            if (!empty($params['feature_variants'])) {
                $tmp .= db_quote(" OR ?:product_features_values.value LIKE ?l", '%' . $piece . '%');
                $params['extend'][] = 'feature_values';
            }
            if (isset($params['pcode']) && fn_string_not_empty($params['pcode'])) {
                $pcode = trim($params['pcode']);
                $fields['combination'] = 'inventory.combination';
                $tmp .= db_quote(" OR inventory.product_code LIKE ?l OR products.product_code LIKE ?l", "%{$pcode}%", "%{$pcode}%");
            }
            fn_set_hook('additional_fields_in_search', $params, $fields, $sortings, $condition, $join, $sorting, $group_by, $tmp, $piece, $having);
            $_condition[] = '(' . $tmp . ')';
        }
        if (isset($params['pcode']) && fn_string_not_empty($params['pcode'])) {
            $pcode = trim($params['pcode']);
            $inventory_condition .= db_quote(" AND inventory.product_code LIKE ?l", "%{$pcode}%");
        }
        $_cond = implode($search_type, $_condition);
        if (!empty($_condition)) {
            $condition .= ' AND (' . $_cond . ') ';
        }
        //if perform search we also get additional fields
        if ($params['pname'] == 'Y') {
            $params['extend'][] = 'product_name';
        }
        if ($params['pshort'] == 'Y' || $params['pfull'] == 'Y' || $params['pkeywords'] == 'Y') {
            $params['extend'][] = 'description';
        }
        unset($_condition);
    }
    //
    // [Advanced and feature filters]
    //
    if (!empty($params['apply_limit']) && $params['apply_limit'] && !empty($params['pid'])) {
        $pids = array();
        foreach ($params['pid'] as $pid) {
            if ($pid != $params['exclude_pid']) {
                if (count($pids) == $params['limit']) {
                    break;
                } else {
                    $pids[] = $pid;
                }
            }
        }
        $params['pid'] = $pids;
    }
    // Feature code
    if (!empty($params['feature_code'])) {
        $condition .= db_quote(" AND ?:product_features.feature_code = ?s", $params['feature_code']);
        $params['extend'][] = 'features';
        $params['extend'][] = 'feature_values';
    }
    // find with certain variant
    if (!empty($params['variant_id'])) {
        $join .= db_quote(" INNER JOIN ?:product_features_values as c_var ON c_var.product_id = products.product_id AND c_var.lang_code = ?s AND c_var.variant_id = ?i", $lang_code, $params['variant_id']);
    }
    if (!empty($params['features_hash']) || !empty($params['filter_variants'])) {
        $selected_filters = !empty($params['filter_variants']) ? $params['filter_variants'] : fn_parse_filters_hash($params['features_hash']);
        $filters = db_get_hash_array("SELECT ?:product_filters.*, ?:product_features.feature_type FROM ?:product_filters LEFT JOIN ?:product_features ON ?:product_features.feature_id = ?:product_filters.feature_id WHERE ?:product_filters.filter_id IN (?n) AND ?:product_filters.status = 'A'", 'filter_id', array_keys($selected_filters));
        list($join, $condition) = fn_generate_feature_conditions($filters, $selected_filters, $join, $condition, $lang_code);
        $params = fn_generate_filter_field_params($params, $filters, $selected_filters);
    }
    fn_set_hook('get_products_before_select', $params, $join, $condition, $u_condition, $inventory_condition, $sortings, $total, $items_per_page, $lang_code, $having);
    //
    // [/Advanced filters]
    //
    $feature_search_condition = '';
    if (!empty($params['feature_variants'])) {
        $feature_params = array('plain' => true, 'variants' => false, 'exclude_group' => true, 'feature_id' => array_keys($params['feature_variants']));
        list($features, ) = fn_get_product_features($feature_params, PRODUCT_FEATURES_THRESHOLD);
        list($join, $condition) = fn_generate_feature_conditions($features, $params['feature_variants'], $join, $condition, $lang_code);
    }
    // Filter by category ID
    if (!empty($params['cid'])) {
        $cids = is_array($params['cid']) ? $params['cid'] : explode(',', $params['cid']);
        if (isset($params['subcats']) && $params['subcats'] == 'Y') {
            $_ids = db_get_fields("SELECT a.category_id" . "\n                 FROM ?:categories as a" . "\n                 LEFT JOIN ?:categories as b" . "\n                 ON b.category_id IN (?n)" . "\n                 WHERE a.id_path LIKE CONCAT(b.id_path, '/%')", $cids);
            $cids = fn_array_merge($cids, $_ids, false);
        }
        $condition .= db_quote(" AND ?:categories.category_id IN (?n)", $cids);
    }
    // If we need to get the products by IDs and no IDs passed, don't search anything
    if (!empty($params['force_get_by_ids']) && empty($params['pid']) && empty($params['product_id'])) {
        return array(array(), $params, 0);
    }
    // Product ID search condition for SQL query
    if (!empty($params['pid'])) {
        $u_condition .= db_quote($union_condition . ' products.product_id IN (?n)', $params['pid']);
    }
    // Exclude products from search results
    if (!empty($params['exclude_pid'])) {
        $condition .= db_quote(' AND products.product_id NOT IN (?n)', $params['exclude_pid']);
    }
    // Search by feature comparison flag
    if (!empty($params['feature_comparison'])) {
        $condition .= db_quote(' AND products.feature_comparison = ?s', $params['feature_comparison']);
    }
    // Search products by localization
    $condition .= fn_get_localizations_condition('products.localization', true);
    $company_condition = '';
    if (fn_allowed_for('MULTIVENDOR')) {
        if ($params['area'] == 'C') {
            $company_condition .= " AND companies.status = 'A' ";
            $params['extend'][] = 'companies';
        } else {
            $company_condition .= fn_get_company_condition('products.company_id');
        }
    } else {
        $cat_company_condition = '';
        if (Registry::get('runtime.company_id')) {
            $params['extend'][] = 'categories';
            $cat_company_condition .= fn_get_company_condition('?:categories.company_id');
        } elseif (!empty($params['company_ids'])) {
            $params['extend'][] = 'categories';
            $cat_company_condition .= db_quote(' AND ?:categories.company_id IN (?a)', explode(',', $params['company_ids']));
        }
        $company_condition .= $cat_company_condition;
    }
    $condition .= $company_condition;
    if (!fn_allowed_for('ULTIMATE') && Registry::get('runtime.company_id') && isset($params['company_id'])) {
        $params['company_id'] = Registry::get('runtime.company_id');
    }
    if (isset($params['company_id']) && $params['company_id'] != '') {
        $condition .= db_quote(' AND products.company_id = ?i ', $params['company_id']);
    }
    if (!empty($params['filter_params'])) {
        foreach ($params['filter_params'] as $field => $f_vals) {
            $condition .= db_quote(' AND products.' . $field . ' IN (?a) ', $f_vals);
        }
    }
    if (isset($params['price_from']) && fn_is_numeric($params['price_from'])) {
        $condition .= db_quote(' AND prices.price >= ?d', fn_convert_price(trim($params['price_from'])));
        $params['extend'][] = 'prices2';
        $params['extend'][] = 'prices';
    }
    if (isset($params['price_to']) && fn_is_numeric($params['price_to'])) {
        $condition .= db_quote(' AND prices.price <= ?d', fn_convert_price(trim($params['price_to'])));
        $params['extend'][] = 'prices2';
        $params['extend'][] = 'prices';
    }
    if (isset($params['weight_from']) && fn_is_numeric($params['weight_from'])) {
        $condition .= db_quote(' AND products.weight >= ?d', fn_convert_weight(trim($params['weight_from'])));
    }
    if (isset($params['weight_to']) && fn_is_numeric($params['weight_to'])) {
        $condition .= db_quote(' AND products.weight <= ?d', fn_convert_weight(trim($params['weight_to'])));
    }
    // search specific inventory status
    if (!empty($params['tracking'])) {
        $condition .= db_quote(' AND products.tracking IN(?a)', $params['tracking']);
    }
    if (isset($params['amount_from']) && fn_is_numeric($params['amount_from'])) {
        $condition .= db_quote(" AND IF(products.tracking = ?s, inventory.amount >= ?i, products.amount >= ?i)", ProductTracking::TRACK_WITH_OPTIONS, $params['amount_from'], $params['amount_from']);
        $inventory_condition .= db_quote(' AND inventory.amount >= ?i', $params['amount_from']);
    }
    if (isset($params['amount_to']) && fn_is_numeric($params['amount_to'])) {
        $condition .= db_quote(" AND IF(products.tracking = ?s, inventory.amount <= ?i, products.amount <= ?i)", ProductTracking::TRACK_WITH_OPTIONS, $params['amount_to'], $params['amount_to']);
        $inventory_condition .= db_quote(' AND inventory.amount <= ?i', $params['amount_to']);
    }
    // Cut off out of stock products
    if (Registry::get('settings.General.inventory_tracking') == 'Y' && Registry::get('settings.General.show_out_of_stock_products') == 'N' && $params['area'] == 'C') {
        $condition .= db_quote(' AND (CASE products.tracking' . '   WHEN ?s THEN inventory.amount > 0' . '   WHEN ?s THEN products.amount > 0' . '   ELSE 1' . ' END)', ProductTracking::TRACK_WITH_OPTIONS, ProductTracking::TRACK_WITHOUT_OPTIONS);
    }
    if (!empty($params['status'])) {
        $condition .= db_quote(' AND products.status IN (?a)', $params['status']);
    }
    if (!empty($params['shipping_freight_from'])) {
        $condition .= db_quote(' AND products.shipping_freight >= ?d', $params['shipping_freight_from']);
    }
    if (!empty($params['shipping_freight_to'])) {
        $condition .= db_quote(' AND products.shipping_freight <= ?d', $params['shipping_freight_to']);
    }
    if (!empty($params['free_shipping'])) {
        $condition .= db_quote(' AND products.free_shipping = ?s', $params['free_shipping']);
    }
    if (!empty($params['downloadable'])) {
        $condition .= db_quote(' AND products.is_edp = ?s', $params['downloadable']);
    }
    if (isset($params['amount_to']) && fn_is_numeric($params['amount_to']) || isset($params['amount_from']) && fn_is_numeric($params['amount_from']) || !empty($params['pcode']) || Registry::get('settings.General.inventory_tracking') == 'Y' && Registry::get('settings.General.show_out_of_stock_products') == 'N' && $params['area'] == 'C') {
        $join .= " LEFT JOIN ?:product_options_inventory as inventory ON inventory.product_id = products.product_id {$inventory_condition}";
    }
    if (!empty($params['period']) && $params['period'] != 'A') {
        list($params['time_from'], $params['time_to']) = fn_create_periods($params);
        $condition .= db_quote(" AND (products.timestamp >= ?i AND products.timestamp <= ?i)", $params['time_from'], $params['time_to']);
    }
    if (!empty($params['item_ids'])) {
        $condition .= db_quote(" AND products.product_id IN (?n)", explode(',', $params['item_ids']));
    }
    if (isset($params['popularity_from']) && fn_is_numeric($params['popularity_from'])) {
        $params['extend'][] = 'popularity';
        $condition .= db_quote(' AND popularity.total >= ?i', $params['popularity_from']);
    }
    if (isset($params['popularity_to']) && fn_is_numeric($params['popularity_to'])) {
        $params['extend'][] = 'popularity';
        $condition .= db_quote(' AND popularity.total <= ?i', $params['popularity_to']);
    }
    if (!empty($params['order_ids'])) {
        $arr = strpos($params['order_ids'], ',') !== false || !is_array($params['order_ids']) ? explode(',', $params['order_ids']) : $params['order_ids'];
        $condition .= db_quote(" AND ?:order_details.order_id IN (?n)", $arr);
        $join .= " LEFT JOIN ?:order_details ON ?:order_details.product_id = products.product_id";
    }
    $limit = '';
    $group_by = 'products.product_id';
    // Show enabled products
    $_p_statuses = array('A');
    $condition .= $params['area'] == 'C' ? ' AND (' . fn_find_array_in_set($auth['usergroup_ids'], 'products.usergroup_ids', true) . ')' . db_quote(' AND products.status IN (?a)', $_p_statuses) : '';
    // -- JOINS --
    // Feature values and features
    if (in_array('feature_values', $params['extend'])) {
        $join .= db_quote(" LEFT JOIN ?:product_features_values ON ?:product_features_values.product_id = products.product_id AND ?:product_features_values.lang_code = ?s", $lang_code);
        if (in_array('features', $params['extend'])) {
            $join .= db_quote(" LEFT JOIN ?:product_features ON ?:product_features_values.feature_id = ?:product_features.feature_id");
        }
    }
    if (in_array('product_name', $params['extend'])) {
        $fields['product'] = 'descr1.product as product';
        $join .= db_quote(" LEFT JOIN ?:product_descriptions as descr1 ON descr1.product_id = products.product_id AND descr1.lang_code = ?s ", $lang_code);
    }
    // get prices
    $price_condition = '';
    if (in_array('prices', $params['extend'])) {
        $join .= " LEFT JOIN ?:product_prices as prices ON prices.product_id = products.product_id AND prices.lower_limit = 1";
        $price_condition = db_quote(' AND prices.usergroup_id IN (?n)', $params['area'] == 'A' ? USERGROUP_ALL : array_merge(array(USERGROUP_ALL), $auth['usergroup_ids']));
        $condition .= $price_condition;
    }
    // get prices for search by price
    if (in_array('prices2', $params['extend'])) {
        $price_usergroup_cond_2 = db_quote(' AND prices_2.usergroup_id IN (?n)', $params['area'] == 'A' ? USERGROUP_ALL : array_merge(array(USERGROUP_ALL), $auth['usergroup_ids']));
        $join .= " LEFT JOIN ?:product_prices as prices_2 ON prices.product_id = prices_2.product_id AND prices_2.lower_limit = 1 AND prices_2.price < prices.price " . $price_usergroup_cond_2;
        $condition .= ' AND prices_2.price IS NULL';
        $price_condition .= ' AND prices_2.price IS NULL';
    }
    // get companies
    $companies_join = db_quote(" LEFT JOIN ?:companies AS companies ON companies.company_id = products.company_id ");
    if (in_array('companies', $params['extend'])) {
        $fields['company_name'] = 'companies.company as company_name';
        $join .= $companies_join;
    }
    // for compatibility
    if (in_array('category_ids', $params['extend'])) {
        $params['extend'][] = 'categories';
    }
    // get categories
    $_c_statuses = array('A', 'H');
    // Show enabled categories
    $skip_checking_usergroup_permissions = fn_is_preview_action($auth, $params);
    if ($skip_checking_usergroup_permissions) {
        $category_avail_cond = '';
    } else {
        $category_avail_cond = $params['area'] == 'C' ? ' AND (' . fn_find_array_in_set($auth['usergroup_ids'], '?:categories.usergroup_ids', true) . ')' : '';
    }
    $category_avail_cond .= $params['area'] == 'C' ? db_quote(" AND ?:categories.status IN (?a) ", $_c_statuses) : '';
    $categories_join = " INNER JOIN ?:products_categories as products_categories ON products_categories.product_id = products.product_id INNER JOIN ?:categories ON ?:categories.category_id = products_categories.category_id {$category_avail_cond} {$feature_search_condition}";
    if (!empty($params['order_ids'])) {
        // Avoid duplicating by sub-categories
        $condition .= db_quote(' AND products_categories.link_type = ?s', 'M');
    }
    if (in_array('categories', $params['extend'])) {
        $join .= $categories_join;
        $condition .= fn_get_localizations_condition('?:categories.localization', true);
    }
    // get popularity
    $popularity_join = db_quote(" LEFT JOIN ?:product_popularity as popularity ON popularity.product_id = products.product_id");
    if (in_array('popularity', $params['extend'])) {
        $fields['popularity'] = 'popularity.total as popularity';
        $join .= $popularity_join;
    }
    if (!empty($params['get_subscribers'])) {
        $join .= " LEFT JOIN ?:product_subscriptions as product_subscriptions ON product_subscriptions.product_id = products.product_id";
    }
    //  -- \JOINs --
    if (!empty($u_condition)) {
        $condition .= " {$union_condition} ((" . ($union_condition == ' OR ' ? '0 ' : '1 ') . $u_condition . ')' . $company_condition . $price_condition . ')';
    }
    // -- SORTINGS --
    if (empty($params['sort_by']) || empty($sortings[$params['sort_by']])) {
        $params = array_merge($params, fn_get_default_products_sorting());
        if (empty($sortings[$params['sort_by']])) {
            $_products_sortings = fn_get_products_sorting();
            $params['sort_by'] = key($_products_sortings);
        }
    }
    $default_sorting = fn_get_products_sorting();
    if ($params['sort_by'] == 'popularity' && !in_array('popularity', $params['extend'])) {
        $join .= $popularity_join;
    }
    if ($params['sort_by'] == 'company' && !in_array('companies', $params['extend'])) {
        $join .= $companies_join;
    }
    if (empty($params['sort_order'])) {
        if (!empty($default_sorting[$params['sort_by']]['default_order'])) {
            $params['sort_order'] = $default_sorting[$params['sort_by']]['default_order'];
        } else {
            $params['sort_order'] = 'asc';
        }
    }
    $sorting = db_sort($params, $sortings);
    if (fn_allowed_for('ULTIMATE')) {
        if (in_array('sharing', $params['extend'])) {
            $fields['is_shared_product'] = "IF(COUNT(IF(?:categories.company_id = products.company_id, NULL, ?:categories.company_id)), 'Y', 'N') as is_shared_product";
            if (strpos($join, $categories_join) === false) {
                $join .= $categories_join;
            }
        }
    }
    // -- \SORTINGS --
    // Load prices in main SQL-query when they are needed and sorting or filtering by price is applied
    if (in_array('prices', $params['extend']) && (isset($params['sort_by']) && $params['sort_by'] == 'price' || in_array('prices2', $params['extend']))) {
        $fields['price'] = 'MIN(IF(prices.percentage_discount = 0, prices.price, prices.price - (prices.price * prices.percentage_discount)/100)) as price';
    }
    /**
     * Changes additional params for selecting products
     *
     * @param array  $params    Product search params
     * @param array  $fields    List of fields for retrieving
     * @param array  $sortings  Sorting fields
     * @param string $condition String containing SQL-query condition possibly prepended with a logical operator (AND or OR)
     * @param string $join      String with the complete JOIN information (JOIN type, tables and fields) for an SQL-query
     * @param string $sorting   String containing the SQL-query ORDER BY clause
     * @param string $group_by  String containing the SQL-query GROUP BY field
     * @param string $lang_code Two-letter language code (e.g. 'en', 'ru', etc.)
     * @param array  $having    HAVING condition
     */
    fn_set_hook('get_products', $params, $fields, $sortings, $condition, $join, $sorting, $group_by, $lang_code, $having);
    // Used for View cascading
    if (!empty($params['get_query'])) {
        return "SELECT products.product_id FROM ?:products as products {$join} WHERE 1 {$condition} GROUP BY products.product_id";
    }
    // Used for Extended search
    if (!empty($params['get_conditions'])) {
        return array($fields, $join, $condition);
    }
    if (!empty($params['limit'])) {
        $limit = db_quote(" LIMIT 0, ?i", $params['limit']);
    } elseif (!empty($params['items_per_page'])) {
        $limit = db_paginate($params['page'], $params['items_per_page']);
    }
    $calc_found_rows = '';
    if (empty($total)) {
        $calc_found_rows = 'SQL_CALC_FOUND_ROWS';
    }
    if (!empty($having)) {
        $having = ' HAVING ' . implode(' AND ', $having);
    } else {
        $having = '';
    }
    $sql_query_body = "SELECT {$calc_found_rows} " . implode(', ', $fields) . " FROM ?:products as products {$join} WHERE 1 {$condition} GROUP BY {$group_by} {$having} {$sorting} {$limit}";
    $fn_load_products = function ($query, $params) use($total) {
        $products = db_get_array($query);
        $total_found_rows = empty($params['items_per_page']) ? count($products) : (empty($total) ? db_get_found_rows() : $total);
        return array($products, $total_found_rows);
    };
    // Caching conditions
    if ($params['use_caching'] && isset($params['dispatch']) && $params['dispatch'] == 'categories.view' && $params['area'] == 'C' && $auth['usergroup_ids'] == array(0, 1) && !empty($params['cid']) && empty($params['q']) && empty($params['pid']) && empty($params['exclude_pid']) && empty($params['feature_comparison']) && empty($params['features_hash']) && empty($params['feature_code']) && empty($params['multiple_variants']) && empty($params['custom_range']) && empty($params['field_range']) && empty($params['fields_ids']) && empty($params['slider_vals']) && empty($params['ch_filters']) && empty($params['tx_features']) && empty($params['feature_variants']) && empty($params['filter_params']) && !isset($params['price_from']) && !isset($params['price_to']) && !isset($params['weight_from']) && !isset($params['weight_to']) && empty($params['tracking']) && !isset($params['amount_from']) && !isset($params['amount_to']) && empty($params['status']) && empty($params['shipping_freight_from']) && empty($params['shipping_freight_to']) && empty($params['free_shipping']) && empty($params['downloadable']) && !isset($params['pcode']) && empty($params['period']) && empty($params['item_ids']) && !isset($params['popularity_from']) && !isset($params['popularity_to']) && empty($params['order_ids'])) {
        $cache_prefix = __FUNCTION__;
        $cache_key = md5($sql_query_body);
        Registry::registerCache($cache_prefix . '_' . $cache_key, array('products', 'categories', 'products_categories'), Registry::cacheLevel('static'), true);
        if ($cache = Registry::get($cache_prefix . '_' . $cache_key)) {
            list($products, $params['total_items']) = $cache;
        } else {
            list($products, $params['total_items']) = $fn_load_products($sql_query_body, $params);
            if ($params['total_items'] > Registry::get('config.tweaks.products_found_rows_no_cache_limit')) {
                Registry::set($cache_prefix . '_' . $cache_key, array($products, $params['total_items']));
            }
        }
    } else {
        list($products, $params['total_items']) = $fn_load_products($sql_query_body, $params);
    }
    if (!empty($params['get_frontend_urls'])) {
        foreach ($products as &$product) {
            $product['url'] = fn_url('products.view?product_id=' . $product['product_id'], 'C');
        }
    }
    if (!empty($params['item_ids'])) {
        $products = fn_sort_by_ids($products, explode(',', $params['item_ids']));
    }
    if (!empty($params['pid']) && !empty($params['apply_limit']) && $params['apply_limit']) {
        $products = fn_sort_by_ids($products, $params['pid']);
    }
    $products = fn_load_products_extra_data($products, $params, $lang_code);
    /**
     * Changes selected products
     *
     * @param array  $products  Array of products
     * @param array  $params    Product search params
     * @param string $lang_code Language code
     */
    fn_set_hook('get_products_post', $products, $params, $lang_code);
    LastView::instance()->processResults('products', $products, $params);
    return array($products, $params);
}