Пример #1
0
 public function init($category_id = null, $current_tuid = null)
 {
     parent::init();
     global $js_file;
     $js_file['tservices/tservices_catalog'] = 'tservices/tservices_catalog.js';
     if (isset($this->options['limit'])) {
         $this->limit = $this->options['limit'];
     }
     if (isset($this->options['prof_group_id'], $this->options['prof_id']) && !$category_id) {
         require_once ABS_PATH . '/classes/tservices/tservices_categories.php';
         $tservices_categories = new tservices_categories();
         $category_data = $tservices_categories->getCategoryByFreelancersCatalog($this->options['prof_group_id'], $this->options['prof_id']);
         if ($category_data) {
             $category_id = $category_data['id'];
             $this->options['category_title'] = $category_data['title'];
             $this->options['category_stitle'] = $category_data['link'];
         }
     }
     $tservicesCatalogModel = new tservices_catalog();
     $tservicesCatalogModel->setPage($this->limit, 1);
     if (isset($this->options['user_id']) && $this->options['user_id'] > 0) {
         $tservicesCatalogModel->user_id = $this->options['user_id'];
     } elseif ($category_id) {
         $tservicesCatalogModel->category_id = $category_id;
     }
     $exclude_ids = $current_tuid ? array($current_tuid) : array();
     $list = $tservicesCatalogModel->cache($this->ttl_cache)->getList($exclude_ids);
     $this->tservices = $list['list'];
     if ($this->tservices) {
         //расширение сведений о типовых услугах
         $tserviceModel = new TServiceModel();
         $tserviceModel->addOwnerInfo()->extend($this->tservices, 'id');
     }
 }
 /**
  * Отображение страницы /tu/.
  */
 public function actionIndex()
 {
     $uid = get_uid();
     $page = __paramInit('int', 'page', 'page', 1);
     $limit = 21;
     $empty_criteria = $this->filter_widget->filter->isEmpty();
     $prof_id = $this->filter_widget->filter->category ? $this->filter_widget->filter->category : $this->filter_widget->filter->category_group;
     $tserviceModel = TServiceModel::model();
     $freelancerModel = FreelancerModel::model();
     $tservicesCatalogModel = new tservices_catalog();
     $tservicesCatalogModel->category_id = $prof_id;
     $kind = tservices_binds::KIND_ROOT;
     if ($this->filter_widget->filter->category) {
         $kind = tservices_binds::KIND_SPEC;
     } elseif ($this->filter_widget->filter->category_group) {
         $kind = tservices_binds::KIND_GROUP;
     }
     if ($page == 1 && $uid && !is_emp()) {
         $this->getClips()->add('bind_teaser', $this->widget('TServiceBindTeaser', array('kind' => $kind, 'uid' => $uid, 'prof_id' => $prof_id, 'is_inner' => !$empty_criteria), true));
         $this->getClips()->add('bind_teaser_short', $this->widget('TServiceBindTeaserShort', array(), true));
     }
     $free_places = true;
     //Сначала берем закрепленные
     $tservicesCatalogModel->setPage($limit, $page);
     $tservices_binded = $tservicesCatalogModel->getBindedList($kind);
     //Тут только для текущей страницы
     $tservices_binded_ids = $tservicesCatalogModel->getBindedIds($kind);
     //Тут для всех страниц
     $count_binded = count($tservices_binded_ids);
     $count_binded_cur_page = count($tservices_binded);
     if ($count_binded_cur_page) {
         // расширение сведений о типовых услугах
         $tserviceModel->extend($tservices_binded, 'id')->readVideos($tservices_binded, 'videos', 'videos');
         // во всех строках "распаковать" массив видео-клипов
         // расширение сведений о пользователях
         $freelancerModel->extend($tservices_binded, 'user_id', 'user');
         //Добавляем попапы продления и поднятия к услугам текущего юзера
         foreach ($tservices_binded as $key => $tservice) {
             $is_owner = $tservice['user_id'] == $uid;
             if ($is_owner) {
                 $this->getClips()->add('bind_links_' . $tservice['id'], $this->widget('TServiceBindLinks', array('kind' => $kind, 'uid' => $uid, 'is_inner' => !$empty_criteria, 'date_stop' => $tservice['date_stop'], 'allow_up' => $page > 1 || $key > 0, 'tservice_id' => $tservice['id']), true));
                 if (quickPaymentPopupTservicebind::getInstance()->inited == false) {
                     quickPaymentPopupTservicebind::getInstance()->init(array('uid' => $uid, 'kind' => $kind, 'prof_id' => $prof_id));
                 }
                 $popup_id = quickPaymentPopupTservicebind::getInstance()->getPopupId($tservice['id']);
                 $popups[] = quickPaymentPopupTservicebind::getInstance()->render(array('is_prolong' => true, 'date_stop' => $tservice['date_stop'], 'popup_id' => $popup_id, 'tservices_cur' => $tservice['id'], 'tservices_cur_text' => $tservice['title']));
                 if ($key > 0) {
                     if (quickPaymentPopupTservicebindup::getInstance()->inited == false) {
                         quickPaymentPopupTservicebindup::getInstance()->init(array('uid' => $uid, 'tservices_id' => $tservice['id'], 'tservices_title' => $tservice['title'], 'kind' => $kind, 'prof_id' => $prof_id));
                     }
                     $popup_id = quickPaymentPopupTservicebindup::getInstance()->getPopupId($tservice['id']);
                     $popups[] = quickPaymentPopupTservicebindup::getInstance()->render(array('popup_id' => $popup_id, 'tservices_cur' => $tservice['id'], 'tservices_cur_text' => $tservice['title']));
                 }
             }
         }
         $free_places = $count_binded_cur_page < $limit;
     }
     if ($free_places) {
         //Есть места для отображения незакрепленных услуг
         $tservicesCatalogModel->keywords = $this->filter_widget->filter->keywords;
         $tservicesCatalogModel->price_ranges = $this->filter_widget->filter->prices;
         $tservicesCatalogModel->price_max = $this->filter_widget->filter->price_max;
         $tservicesCatalogModel->country_id = $this->filter_widget->filter->country;
         $tservicesCatalogModel->city_id = $this->filter_widget->filter->city;
         $tservicesCatalogModel->order = $this->filter_widget->filter->order;
         $tservicesCatalogModel->setPage($limit, $page, $count_binded, $count_binded_cur_page);
         // поиск записей
         $list = $tservicesCatalogModel->cache(300)->getList($tservices_binded_ids);
         $tservices_search = $list['list'];
         $total = $list['total'];
         // расширение сведений о типовых услугах
         $tserviceModel->extend($tservices_search, 'id')->readVideos($tservices_search, 'videos', 'videos');
         // во всех строках "распаковать" массив видео-клипов
         // расширение сведений о пользователях
         $freelancerModel->extend($tservices_search, 'user_id', 'user');
     }
     $tservices = $tservices_binded;
     foreach ($tservices_search as $tservice) {
         if (count($tservices) < $limit && !in_array($tservice['id'], $tservices_binded_ids)) {
             $tservices[] = $tservice;
         }
     }
     $tservicesCatalogModel2 = new tservices_catalog();
     $tservicesCatalogModel2->category_id = $prof_id;
     $tservicesCatalogModel2->order = TServiceFilter::ORDER_PRICE_ASC;
     $tservicesCatalogModel2->setPage(1, 1);
     $list2 = $tservicesCatalogModel2->cache(300)->getList();
     $min_price = $list2['list'][0]['price'];
     SeoTags::getInstance()->initTserviceList($prof_id, $this->filter_widget->filter->category > 0, $total, $min_price);
     $view_name = !$empty_criteria ? 'list' : 'tile';
     $this->is_main = $empty_criteria;
     /*
             if ($empty_criteria)
             {
                 // над списком типовых услуг вывести рекламный блок раздела
                 require_once($_SERVER['DOCUMENT_ROOT'] . '/tu/widgets/TServiceCatalogPromo.php');
                 $this->getClips()->add('content-promo', $this->widget('TServiceCatalogPromo', array(), true));
             }
     */
     $tservices_binds = new tservices_binds($kind);
     $this->render($view_name, array('category_title' => $this->filter_widget->getCategoryAngGroupTitle(' / '), 'total' => $total, 'nothing_found' => empty($tservices), 'tservices' => $tservices, 'page' => $tservicesCatalogModel->page, 'limit' => $limit, 'paging_base_url' => $this->filter_widget->getUserFriendlyUrl(), 'is_adm' => $this->is_adm, 'orders' => $this->filter_widget->getAllowedOrders(true), 'cur_order' => $this->filter_widget->filter->order, 'uid' => $uid, 'popups' => $popups, 'bind_up_price' => $tservices_binds->getPrice(true, $uid, $prof_id)));
 }
Пример #3
0
// Дополнительный стиль для отображения фона страницы
$body_additional_class = 'landing-fon';
// Прячем карусель вверху страницы
$hide_carouser = true;
// Прячем блок с сообщениями
$hide_notification_bar = true;
$header = "../header.php";
$footer = "../footer.html";
/**
* Типовые услуги
**/
require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/tservices/tservices_binds.php';
$page = 1;
// Количество типовых услуг на главной странице
$limit = 12;
$tserviceModel = TServiceModel::model();
$freelancerModel = FreelancerModel::model();
$tservicesCatalogModel = new tservices_catalog();
$tservicesCatalogModel->setPage($limit, $page);
//Сначала берем закрепленные
$tservices_binded = $tservicesCatalogModel->getBindedList(tservices_binds::KIND_LANDING);
$binded_ids = array();
if (count($tservices_binded)) {
    foreach ($tservices_binded as $tservice) {
        $binded_ids[] = $tservice['id'];
    }
    // расширение сведений о типовых услугах
    $tserviceModel->extend($tservices_binded, 'id')->readVideos($tservices_binded, 'videos', 'videos');
    // во всех строках "распаковать" массив видео-клипов
    // расширение сведений о пользователях
    $freelancerModel->extend($tservices_binded, 'user_id', 'user');
Пример #4
0
/**
 * Получение 3х смежных по категориям ТУ.
 * 
 * @param type $cat_group
 * @param type $cat
 *
 * @return \xajaxResponse
 */
function getRelativeTU($cat_group, $cat)
{
    $objResponse = new xajaxResponse();
    $cat_group = intval($cat_group);
    $cat = intval($cat);
    if (!$cat_group) {
        return $objResponse;
    }
    require_once $_SERVER['DOCUMENT_ROOT'] . '/tu/yii/tinyyii.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/tu/widgets/TServiceFilter.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/tservices/tservices_catalog.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/tservices/tservices_categories.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/tservices/tservices_helper.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/template.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/tu/models/TServiceModel.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/tu/models/FreelancerModel.php';
    $tservices_categories = new tservices_categories();
    $category_group = $tservices_categories->getIdByGid($cat_group);
    $category = $tservices_categories->getIdByPid($cat);
    $limit = 3;
    $tservicesCatalogModel = new tservices_catalog();
    $tservicesCatalogModel->category_id = $category ? (int) $category : (int) $category_group;
    $tservicesCatalogModel->setPage($limit);
    // поиск записей
    $list = $tservicesCatalogModel->cache(300)->getList();
    $tservices = $list['list'];
    // расширение сведений о типовых услугах
    $tserviceModel = TServiceModel::model();
    $tserviceModel->extend($tservices, 'id')->readVideos($tservices, 'videos', 'videos');
    // во всех строках "распаковать" массив видео-клипов
    // расширение сведений о пользователях
    $freelancerModel = FreelancerModel::model();
    $freelancerModel->extend($tservices, 'user_id', 'user');
    if (($cat_group || $cat) && count($tservices)) {
        $html = Template::render(ABS_PATH . '/templates/recomend_tu.php', array('tservices' => $tservices));
        $objResponse->script("\$('otherprojects').addClass('b-layout_hide');");
        $objResponse->assign('recomend_tu', 'innerHTML', $html);
    } else {
        $objResponse->script("\$('otherprojects').removeClass('b-layout_hide');");
        $objResponse->assign('recomend_tu', 'innerHTML', '');
    }
    return $objResponse;
}
Пример #5
0
 /**
  * Возвращает страницу каталога фрилансеров со всеми необходимыми причиндалами.
  * 
  * Немного оптимизированная замена old_getCatalog
  * - оптимизированы запросы, убран устаревший функционал
  * - отключен фильтр кроме категорий но поддерка остается (на поиск работает сфинкс)
  * - без фильтра полностью закешировал выдачу
  * 
  * 
  * @param integer prof_id     ид. профессии (раздела каталога). Если 0, то выводим фрилансеров из общего каталога.
  * @param integer uid         ид. юзера, просматривающего каталог.
  * @param integer count       количество всего фрилансеров в данном разделе каталога.
  * @param integer size        количество фрилансеров на данной странице каталога.
  * @param array   works       массив, индексированный ид. фрилансеров, содержащий массив из трех первых работ данного фрилансера в данном разделе.
  * @param integer limit       сколько фрилансеров на одной странице.
  * @param integer offset      OFFSET.
  * @param string  order       тип сортировки (см. использование).
  * @param int     direction   порядок сортировки. 0 -- по убывающей, не 0 -- по возрастающей.
  * @param int     favorite    флаг -- показывать ли только избранных.
  * @param array   filter      массив с параметрами фильтра или NULL -- фильтр не применен.
  *
  * @return array  массив с фрилансерами.
  */
 function new_getCatalog($prof_id, $uid, &$count, &$size, &$works, $limit, $offset, $order = "general", $direction = 0, $favorite = 0, $filter = NULL)
 {
     require_once $_SERVER['DOCUMENT_ROOT'] . "/classes/projects.php";
     global $DB;
     //текущая группа или специализация
     $current_categoty_id = 0;
     //группа или специализация
     $current_categoty_is_spec = $prof_id > 0;
     $project_exRates = project_exrates::GetAll();
     $fu_table = self::$fu_table;
     //Сбрасываем все параметры фильра кроме категории
     //так как эта выборка не поддерживает фильтр
     //фильтр осуществляется средствами поиска (сфинкс)!
     if (isset($filter['prof'])) {
         $tmp_filter = $filter;
         $filter = array();
         $filter['prof'] = $tmp_filter['prof'];
     }
     $fprms = self::createCatalogFilterSql($filter, $prof_id);
     if ($fprms == -1) {
         return null;
     }
     //@todo: фильтр каталога более не используем но поддержку оставляем
     //$filter_join не используется!
     //$filter_where только по разделам
     list($filter_where, $filter_join) = $fprms;
     $filter_join = '';
     if ($filter_where) {
         $filter_where = ' AND ' . $filter_where;
     }
     $size = 0;
     if ($prof_id) {
         $or_prof = professions::GetProfessionOrigin($prof_id);
         $ord_spec = ', s.its_his_main_spec DESC';
     }
     // Список специализаций для фильтрации в портфолио
     $specs_list = '';
     $dir_sql = !$direction ? 'DESC' : 'ASC';
     switch ($order) {
         case "opinions":
             $uc_side = 'INNER';
             $order = ", osum {$dir_sql}, s.rating {$dir_sql}";
             break;
         case "sbr":
             $uc_side = 'INNER';
             $order = ", ssum {$dir_sql}, s.rating {$dir_sql}";
             break;
         case "cost_hour":
             $order = "{$ord_spec}, cost_hour_is_0, cost_fm {$dir_sql}, s.rating {$dir_sql}";
             $orderCf = 'pc.cost_hour';
             $orderCt = 'pc.cost_type_hour';
             break;
         case "cost_month":
             $order = "{$ord_spec}, COALESCE(s.cost_month,0)=0, cost_fm {$dir_sql}, s.rating {$dir_sql}";
             $orderCf = 's.cost_month';
             $orderCt = 's.cost_type_month';
             break;
         case "cost_proj":
             $order = "{$ord_spec}, COALESCE(cost_from,0)=0, cost_fm {$dir_sql}, s.rating {$dir_sql}";
             $orderCf = 'pc.cost_from';
             $orderCt = 'pc.cost_type';
             break;
         case "cost_1000":
             $order = "{$ord_spec}, COALESCE(cost_1000,0)=0, cost_fm {$dir_sql}, s.rating {$dir_sql}";
             $orderCf = 'pc.cost_1000';
             $orderCt = 'pc.cost_type';
             break;
         case "general":
         default:
             $order = "{$ord_spec}, rating_get(s.rating, s.is_pro, s.is_verify, s.is_profi) {$dir_sql}";
             break;
     }
     $cost_fm = '';
     if (isset($orderCf, $orderCt)) {
         $cost_fm = ",\n            CASE WHEN COALESCE({$orderCt},0) = 0 THEN {$orderCf} * {$project_exRates[24]}\n                 WHEN {$orderCt} = 1 THEN {$orderCf} * {$project_exRates[34]}\n                 WHEN {$orderCt} = 2 THEN {$orderCf} * {$project_exRates[44]}\n                 WHEN {$orderCt} = 3 THEN {$orderCf} * {$project_exRates[14]}\n                 ELSE {$orderCf}\n             END as cost_fm ";
     }
     if (!isset($uc_side)) {
         //@todo: фильтр каталога более не используем но поддержку оставляем
         $uc_side = strpos($filter_where, 'uc.') !== false ? 'INNER' : 'OUTER';
     }
     $uc_cols = $uc_join = array('INNER' => '', 'OUTER' => '');
     //В зависимости наличия сортировки выборка и обьединение включается до лимита или после
     $uc_cols[$uc_side] = ", \n          uc.ops_emp_plus + uc.ops_frl_plus as sg, \n          uc.ops_emp_minus + uc.ops_frl_minus as sl, \n          uc.ops_emp_null + uc.ops_frl_null as se,\n          zin(uc.paid_advices_cnt + uc.sbr_opi_plus + uc.tu_orders_plus + uc.projects_fb_plus)-zin(uc.sbr_opi_minus + uc.tu_orders_minus + uc.projects_fb_minus) as ssum, \n          zin(uc.ops_emp_plus)-zin(uc.ops_emp_minus) as osum,\n          (uc.paid_advices_cnt + uc.sbr_opi_plus + uc.tu_orders_plus + uc.projects_fb_plus) AS total_opi_plus,\n          (uc.sbr_opi_null) AS total_opi_null,\n          (uc.sbr_opi_minus + uc.tu_orders_minus + uc.projects_fb_minus) AS total_opi_minus,\n          uc.*";
     $uc_join[$uc_side] = "LEFT JOIN users_counters uc ON uc.user_id = s.uid";
     //В наружнем запросе испозьзуются поля из user_counters, поэтому JOIN нужно делать всегда
     $uc_join['OUTER'] = "LEFT JOIN users_counters uc ON uc.user_id = s.uid";
     if ($prof_id) {
         // находимся в конкретном разделе (нижний уровень, подраздел).
         $current_categoty_id = $or_prof;
         //Если есть сортировки или фильтр то включаем внутрь выборки
         //@todo: фильтр в каталога не используется но поддержку оставляем
         $pc_side = strpos($filter_where, 'pc.') !== false || strpos($cost_fm, 'pc.') !== false ? 'INNER' : 'OUTER';
         $pc_cols = $pc_join = array('INNER' => '', 'OUTER' => '');
         //В зависимости наличия сортировки выборка и обьединение включается до лимита или после
         $pc_cols[$pc_side] = ", \n              (COALESCE(pc.cost_hour, 0) = 0) as cost_hour_is_0, \n              pc.cost_hour, \n              pc.cost_type_hour, \n              pc.cost_from, \n              pc.cost_type, \n              pc.cost_1000";
         $pc_join[$pc_side] = "LEFT JOIN portf_choise pc ON pc.prof_id = '{$or_prof}' AND pc.user_id = s.uid";
         //Основная выборка
         $fu = "(\n              SELECT \n                s.*, \n                true AS its_his_main_spec \n              FROM {$fu_table} AS s\n              WHERE spec_orig = '{$or_prof}'\n                  \n              UNION ALL\n              \n              SELECT \n                s.*, \n                false AS its_his_main_spec \n              FROM {$fu_table} AS s\n              INNER JOIN spec_add_choise sp ON sp.user_id = s.uid AND sp.prof_id = '{$or_prof}' \n              WHERE s.is_pro = true \n            )";
         //Собираем общий запрос
         //@todo: Рекомендуется вынести completed_cnt в users_counters таблицу и с ней соединяться
         //тем более, что в ней уже есть кол-во по новой БС reserves_completed_cnt
         //нужно добавить поле по старой БС и пересчитать туда
         $sql = "\n              SELECT s.*,\n                     city.city_name as str_city, \n                     country.country_name as str_country, \n                     COALESCE(smeta.completed_cnt, 0) + COALESCE(uc.reserves_completed_cnt, 0) AS completed_cnt, -- старые БС + новые БС\n                     rating_get(s.rating, s.is_pro, s.is_verify, s.is_profi) as t_rating\n                     {$uc_cols['OUTER']}\n                     {$pc_cols['OUTER']}\n                FROM (\n                  SELECT s.* \n                         {$cost_fm}, \n                         s.cost_hour as frl_cost_hour, \n                         s.cost_type_hour as frl_cost_type_hour,\n                         \n                         (fb.id > 0)::boolean AS is_binded,\n                         fb.id AS fb_id,\n                         fb.date_start AS fb_date_start \n                         \n                         {$uc_cols['INNER']}\n                         {$pc_cols['INNER']}\n                  FROM {$fu} AS s \n                  {$uc_join['INNER']}\n                  {$pc_join['INNER']}\n                  {$filter_join}\n                  LEFT JOIN freelancer_binds fb \n                    ON fb.user_id = s.uid \n                       AND fb.prof_id = '{$or_prof}' \n                       AND fb.status = true \n                       AND fb.date_stop > NOW() --желательно сделать индекс с условием\n                  WHERE \n                    s.is_banned = '0' \n                    AND s.last_time > now() - '6 months'::interval \n                    AND ( s.cat_show = 't' OR s.is_pro = 'f' ) --желательно исправить во вьюшке\n                    {$filter_where} \n                  ORDER BY (fb.id IS NULL)::boolean ASC, fb.date_start DESC, s.is_pro DESC {$order}, s.uid\n                  LIMIT {$limit} OFFSET {$offset}                 \n                ) as s \n              {$uc_join['OUTER']}\n              {$pc_join['OUTER']}\n              LEFT JOIN country  ON country.id = s.country\n              LEFT JOIN city ON city.id = s.city\n              LEFT JOIN sbr_meta AS smeta ON smeta.user_id = s.uid -- старые БС\n              ORDER BY (fb_id IS NULL)::boolean ASC, fb_date_start DESC, s.is_pro DESC {$order}, s.uid\n            ";
         //Счетчик количества
         $countSql = "\n                 SELECT \n                    COUNT(s.uid) AS count, \n                    SUM(s.is_pro::int) AS payed \n                 FROM {$fu} AS s {$filter_join} " . ($filter_where ? $uc_join['INNER'] . ' ' . $pc_join['INNER'] : '') . " WHERE \n                     s.is_banned = '0' \n                     AND ( s.cat_show = 't' OR s.is_pro = 'f' ) --желательно исправить во вьюшке\n                     AND s.last_time > now() - '6 months'::interval \n                     {$filter_where}";
     } else {
         $join_add_spec = '';
         $prof_choise_condition = "pc.prof_id = s.spec_orig";
         $pattern = "#(s.spec_orig\\s+(IN\\s+\\([\\d,]+\\)))#";
         $order_add_spec = "";
         $order_add_spec_field = "";
         if (preg_match($pattern, $filter_where, $m)) {
             $filter_where = preg_replace($pattern, "(\$1 OR (sa.prof_id \$2 AND s.is_pro = 't' ))", $filter_where);
             $join_add_spec = "LEFT JOIN \n                   spec_add_choise sa\n                     ON  sa.user_id = s.uid";
             $prof_choise_condition = "(\n                    pc.prof_id = s.spec_orig\n                      OR pc.prof_id = sa.prof_id\n                      )";
             //$order_add_spec = "aso DESC, ";
             $order_add_spec_field = "CAST(s.spec_orig {$m[2]} AS integer) AS aso, ";
         }
         // Сортировка фрилансеров внутри специализаии верхнего уровня по подуровням
         $spec_case_order = '';
         if (isset($m[2]) && $m[2]) {
             $spec_case_order = ", CASE WHEN s.spec_orig {$m[2]} THEN 1 ELSE 2 END";
             $specs_list = "p.prof_id {$m[2]}";
         }
         // Категория для закрепленной позиции
         $fb_on_prof = 0;
         if ($filter['prof']) {
             if (count($filter['prof'][0]) > 0) {
                 $group_ids = array_keys($filter['prof'][0]);
                 $fb_on_prof = $group_ids[0];
                 $current_categoty_id = $fb_on_prof;
             }
         }
         $sql = "\n                SELECT\n                    s.*,\n                    city.city_name as str_city, \n                    country.country_name as str_country, \n                    COALESCE(smeta.completed_cnt, 0) + COALESCE(uc.reserves_completed_cnt, 0) AS completed_cnt, -- старые БС + новые БС\n                    p.name as profname, \n                    p.is_text,\n                    rating_get(s.rating, s.is_pro, s.is_verify, s.is_profi) as t_rating\n                    \n                    {$uc_cols['OUTER']}\n               FROM (\n                    SELECT *\n                    FROM (\n                        SELECT \n                            DISTINCT ON (s.uid) \n                            s.*, \n                            s.cost_hour as frl_cost_hour, \n                            s.cost_type_hour as frl_cost_type_hour, \n                            {$order_add_spec_field} \n\n                            (COALESCE(pc.cost_hour, 0) = 0) as cost_hour_is_0, \n                            pc.cost_hour, \n                            pc.cost_from, \n                            pc.cost_type, \n                            pc.cost_1000, \n                            pc.cost_type_hour, \n                            \n                            (fb.id > 0)::boolean as is_binded, \n                            fb.id AS fb_id,\n                            fb.date_start AS fb_date_start\n                            \n                            {$cost_fm}\n                            {$uc_cols['INNER']}\n                        FROM {$fu_table} s \n                            {$join_add_spec} \n                            {$uc_join['INNER']}\n                            LEFT JOIN portf_choise pc \n                                ON {$prof_choise_condition} \n                                   AND pc.user_id = s.uid \n                            LEFT JOIN freelancer_binds fb \n                                ON fb.user_id = s.uid \n                                   AND fb.prof_id = {$fb_on_prof} \n                                   AND fb.is_spec = FALSE\n                                   AND fb.status = TRUE \n                                   AND fb.date_stop > NOW() --желательно сделать индекс с условием\n                            {$filter_join}\n                            WHERE s.is_banned = '0' {$filter_where}  \n                                  AND ( s.cat_show = 't' OR s.is_pro = 'f' ) --желательно исправить во вьюшке\n                                  AND s.last_time > now() - '6 months'::interval\n                    ) AS s    \n                    ORDER BY \n                        (fb_id IS NULL)::boolean ASC, fb_date_start DESC, \n                        s.is_pro DESC {$spec_case_order} {$order}, {$order_add_spec} s.uid\n                    LIMIT {$limit} OFFSET {$offset}\n               ) AS s\n                {$uc_join['OUTER']}\n                LEFT JOIN professions p ON p.id = s.spec \n                LEFT JOIN country ON country.id = s.country \n                LEFT JOIN sbr_meta AS smeta ON smeta.user_id = s.uid --старая БС\n                LEFT JOIN city ON city.id = s.city\n                ORDER BY\n                    (fb_id IS NULL)::boolean ASC, fb_date_start DESC, \n                    s.is_pro DESC {$spec_case_order} {$order}, {$order_add_spec} s.uid";
         $filter_where .= " AND s.last_time > now() - '6 months'::interval AND ( s.cat_show = 't' OR s.is_pro = 'f' )";
         $countSql = self::_createMainCountSql($filter_where, $filter_join, $join_add_spec);
     }
     $memBuff = new memBuff();
     //$DB->setTimeout(90);
     $frls = $memBuff->getSql($error, $sql, self::CATALOG_MEM_LIFE, true, static::getCatalogMemTags($current_categoty_id, $current_categoty_is_spec));
     //@todo: корректно сбрасывать установкой -1
     //$DB->setTimeout(-1);
     if ($error || !$frls) {
         return NULL;
     }
     if (!$prof_id && !$offset && !$memBuff->getBWasMqUsed()) {
         professions::RecalcCatalogPositions();
     }
     //$DB->setTimeout(90);
     $count_arr = $memBuff->getSql($error, $countSql, self::CATALOG_MEM_LIFE, true, static::getCatalogMemTags($current_categoty_id, $current_categoty_is_spec));
     //$DB->setTimeout();
     $count = $count_arr[0]['count'];
     $size = sizeof($frls);
     /*
      * @todo: судя по коду из оригинального getCatalog это не используется
     if ($prof_id && !$memBuff->getBWasMqUsed() && !$filter_where) {
         professions::UpdateProfessionCount($or_prof, $count, $count_arr[0]['payed']);
     }
     */
     $frl_ids = array();
     $frl_ids_map = array();
     $tu_frl_ids = array();
     foreach ($frls as $key => $row) {
         $frl_ids[$key] = $row['uid'];
         $frl_ids_map[$row['uid']] = $key;
         //Если вкладка ТУ выключена то сразу исключаем такие UID
         if (substr($row['tabs'], 7, 1) == 1) {
             $tu_frl_ids[$key] = $row['uid'];
         }
     }
     //Получение пользовательский превью работ/услуг
     require_once ABS_PATH . '/freelancers/widgets/FreelancersPreviewWidget.php';
     require_once ABS_PATH . '/freelancers/models/FreelancersPreviewModel.php';
     $freelancersPreviewModel = new FreelancersPreviewModel();
     $list = $freelancersPreviewModel->getListByUids($frl_ids, $current_categoty_is_spec ? 0 : $current_categoty_id, $prof_id);
     $tmp_tu_uids = $tu_frl_ids;
     foreach ($list as $item) {
         //Если отключена вкладка ТУ то их исключаем
         if (!$item || $item->type == FreelancersPreviewModel::TYPE_TU && !in_array($item->user_id, $tmp_tu_uids)) {
             continue;
         }
         //Инициализируем данные юзера в работе/услуге пока только логин нужен
         $key = $frl_ids_map[$item->user_id];
         $item->setUser(array('login' => $frls[$key]['login']));
         //Инитим виджет если его нет
         if (!isset($frls[$key]['preview'])) {
             $frls[$key]['preview'] = new FreelancersPreviewWidget(array('is_owner' => $frls[$key]['uid'] == $uid && $frls[$key]['is_pro'] == 't'));
         }
         //Добавляем работу в виджет
         $frls[$key]['preview']->addItem($item);
         //Исключаем из дальнейшей обработки
         unset($frl_ids[$key], $tu_frl_ids[$key]);
     }
     if ($frl_ids) {
         $join_blocked = ' LEFT JOIN portfolio_blocked pb ON p.id = pb.src_id ';
         $where_blocked = ' AND pb.src_id IS NULL ';
         $sql = "\n                SELECT \n                    p.id, \n                    p.user_id, \n                    p.name, \n                    p.descr, \n                    p.pict, \n                    p.prev_pict, \n                    p.show_preview, \n                    p.norder, \n                    p.prev_type, \n                    p.is_video\n                FROM portfolio p \n                INNER JOIN portf_choise pc ON pc.user_id = p.user_id AND pc.prof_id = p.prof_id \n                " . ($prof_id ? '' : 'INNER JOIN freelancer f ON f.uid = p.user_id') . "\n                {$join_blocked} \n                WHERE p.user_id IN (" . implode(',', $frl_ids) . ")";
         if ($specs_list) {
             $sql .= " AND {$specs_list}";
         } else {
             $sql .= " AND p.prof_id = " . ($prof_id ? "'{$or_prof}'" : 'f.spec_orig');
         }
         $sql .= " AND p.first3 = true  {$where_blocked} ORDER BY p.user_id, p.norder";
         if ($ret = $memBuff->getSql($error, $sql, self::CATALOG_PORTFOLIO_MEM_LIFE, true, static::getCatalogMemTags($current_categoty_id, $current_categoty_is_spec))) {
             $current_user_pf_ids = array();
             foreach ($ret as $row) {
                 $works[$row['user_id']][] = $row;
                 if ($row['user_id'] == $uid) {
                     $current_user_pf_ids[] = $row['id'];
                 }
             }
             if (!empty($current_user_pf_ids)) {
                 FreelancersPreviewModel::setExistPreviewData(FreelancersPreviewModel::TYPE_PF, $current_user_pf_ids);
             }
         }
     }
     //----------------------------------------------------------------------
     //Если у пользователя не отображатся портфолио
     //то можно показать 3 последнии ТУ
     $exist_uids = $works ? array_keys($works) : array();
     $tu_uids = array_diff($tu_frl_ids, $exist_uids);
     if ($tu_uids) {
         require_once ABS_PATH . '/tu/models/TServiceModel.php';
         $tserviceModel = new TServiceModel();
         if ($list = $tserviceModel->getListByUids($tu_uids, 3, self::CATALOG_PORTFOLIO_MEM_LIFE)) {
             $current_user_tu_ids = array();
             foreach ($list as $item) {
                 $key = $frl_ids_map[$item['user_id']];
                 $item['login'] = $frls[$key]['login'];
                 $frls[$key]['tservices'][] = $item;
                 if ($item['user_id'] == $uid) {
                     $current_user_tu_ids[] = $item['id'];
                 }
             }
             if (!empty($current_user_tu_ids)) {
                 FreelancersPreviewModel::setExistPreviewData(FreelancersPreviewModel::TYPE_TU, $current_user_tu_ids);
             }
         }
     }
     return $frls;
 }
 function setResults()
 {
     global $DB;
     require_once $_SERVER['DOCUMENT_ROOT'] . "/classes/freelancer.php";
     if ($filter = $this->isAdvanced()) {
         foreach ($this->matches as $val) {
             $frl_ids[] = $val;
         }
         $page = $this->_advanced_page;
         $limit = $this->_advanced_limit;
         $offset = 0;
         if ($page > 0) {
             $offset = ($page - 1) * $limit;
         }
         $this->_offset = $offset;
         //if(isset($filter['nt_negative'])) $filter['not_negative'] = $filter['nt_negative'];
         $prof_id = is_array($filter['prof'][1]) ? array_keys($filter['prof'][1]) : array();
         $order_by_spec_orign = "";
         if (count($prof_id)) {
             $order_by_spec_orign = "s.spec IN (" . join(", ", $prof_id) . ") DESC,";
         }
         $prof = $filter['prof'];
         unset($filter['prof']);
         $fprms = freelancer::createCatalogFilterSql($filter, 0);
         $filter_sql = $inner_sql = '';
         if ($fprms !== -1) {
             list($filter_sql, $inner_sql) = $fprms;
             if ($filter_sql) {
                 $filter_sql = ' AND ' . $filter_sql;
             }
         }
         $sql = "SELECT \n                      COUNT(u.uid) as cnt \n                    FROM users u\n                    LEFT JOIN \n                      freelancer s ON s.uid = u.uid\n                    LEFT JOIN\n                      portf_choise pc ON ( pc.prof_id = s.spec_orig AND pc.user_id = s.uid )\n                    LEFT JOIN\n                      users_counters uc ON ( uc.user_id = u.uid )\n                    {$inner_sql} \n                    WHERE \n                      u.uid IN (" . implode(", ", $frl_ids) . ") \n                        AND \n                      u.is_banned = '0'\n                      {$filter_sql} \n                    LIMIT 1;";
         $this->total = $DB->val($sql);
         $sql = "SELECT \n                      u.uid as uid, \n                      u.photo, \n                      u.role, \n                      u.is_pro, \n                      u.is_profi,\n                      u.is_team, \n                      u.is_pro_test, \n                      u.info_for_reg, \n                      p.name as name_prof, \n                      u.login, \n                      u.uname, \n                      u.usurname,\n                      u.email, \n                      u.skype, \n                      s.site, \n                      ctr.country_name, \n                      ct.city_name, \n                      s.spec_text, \n                      s.resume, \n                      s.konk, \n                      s.blocks, \n                      s.status_type,  \n                      s.cost_month, \n                      s.cost_hour AS frl_cost_hour, \n                      s.cost_type_hour as frl_cost_type_hour,\n                      s.in_office, \n                      s.exp, \n                      s.tabs,\n                      \n                      uc.sbr_opi_plus, \n                      uc.sbr_opi_minus, \n                      uc.sbr_opi_null,\n                      \n                      pc.cost_from, \n                      pc.cost_to, \n                      pc.cost_1000, \n                      pc.cost_type, \n                      uc.ops_emp_null + uc.ops_frl_null AS se, \n                      uc.ops_emp_plus + uc.ops_frl_plus AS sg, \n                      uc.ops_emp_minus + uc.ops_frl_minus AS sl, \n                      s.cost_type_hour, \n                      s.cost_type_month, \n                      rating_get(s.rating, s.is_pro, s.is_verify, s.is_profi) as t_rating,\n                      (add_spec.additional_specs || ', ' || COALESCE(p_spec.paid_specs, '')) AS additional_specs,\n                      -- get_additional_specs_as_string(u.uid) AS additional_spec,\n                      \n                      (uc.paid_advices_cnt + uc.sbr_opi_plus + uc.tu_orders_plus + uc.projects_fb_plus) AS total_opi_plus,\n                      (uc.sbr_opi_null) AS total_opi_null,\n                      (uc.sbr_opi_minus + uc.tu_orders_minus + uc.projects_fb_minus) AS total_opi_minus,\n                      \n                      COALESCE(smeta.completed_cnt, 0) + COALESCE(uc.reserves_completed_cnt, 0) AS completed_cnt -- старые БС + новые БС\n                      \n                    FROM users u\n                    LEFT JOIN freelancer s ON s.uid = u.uid\n                    LEFT JOIN portf_choise pc ON ( pc.prof_id = s.spec_orig AND pc.user_id = s.uid )\n                    LEFT JOIN professions p ON p.id = s.spec AND p.id > 0\n                    LEFT JOIN users_counters uc ON uc.user_id = u.uid\n                    LEFT JOIN country ctr ON ctr.id = s.country AND ctr.id > 0\n                    LEFT JOIN city ct ON ct.id = s.city AND ct.id > 0\n                    LEFT JOIN sbr_meta AS smeta ON smeta.user_id = u.uid -- старые БС\n                    LEFT JOIN \n                    ( \n                        SELECT \n                            array_to_string(array_agg(p.name), ', '::text) AS additional_specs, \n                            sa.user_id AS uid\n                        FROM spec_add_choise AS sa\n                        LEFT JOIN professions AS p ON p.id = prof_id\n\t                GROUP BY sa.user_id\n                    ) AS add_spec ON add_spec.uid = u.uid\n                    LEFT JOIN \n                    ( \n                        SELECT \n                            array_to_string(array_agg(p.name), ', '::text) AS paid_specs, \n                            sp.user_id AS uid\n                        FROM spec_paid_choise AS sp\n                        LEFT JOIN professions AS p ON p.id = prof_id\n\t                GROUP BY sp.user_id\n                    ) AS p_spec ON p_spec.uid = u.uid  \n                    \n                    {$inner_sql}\n                    WHERE\n                      u.uid IN (" . implode(", ", $frl_ids) . ") AND \n                      u.is_banned = '0' \n                      {$filter_sql}\n                    ORDER BY u.is_pro DESC, {$order_by_spec_orign} s.rating DESC, u.uid  \n                    LIMIT {$limit} OFFSET {$offset}";
         //echo "<pre>".$sql;
         $this->results = $DB->rows($sql);
     } else {
         $this->results = $this->getRecords('is_pro DESC, rating DESC, id');
     }
     if ($this->results) {
         $frl_ids_map = array();
         $tu_frl_ids = array();
         foreach ($this->results as $key => $row) {
             $frl_ids[] = $row['uid'];
             $frl_ids_map[$row['uid']] = $key;
             //Если вкладка ТУ выключена то сразу исключаем такие UID
             if (substr($row['tabs'], 7, 1) == 1) {
                 $tu_frl_ids[$key] = $row['uid'];
             }
         }
         $uid = isset($_SESSION["uid"]) ? $_SESSION["uid"] : 0;
         $is_spec = isset($prof[0]);
         $categoty_id = $is_spec ? key($prof[0]) : 0;
         $prof_id = !$is_spec && isset($prof[1]) ? key($prof[1]) : 0;
         //print_r($current_categoty_id);
         //exit;
         //Получение пользовательский превью работ/услуг
         require_once ABS_PATH . '/freelancers/widgets/FreelancersPreviewWidget.php';
         require_once ABS_PATH . '/freelancers/models/FreelancersPreviewModel.php';
         $freelancersPreviewModel = new FreelancersPreviewModel();
         $list = $freelancersPreviewModel->getListByUids($frl_ids, $categoty_id, $prof_id);
         $tmp_tu_uids = $tu_frl_ids;
         foreach ($list as $item) {
             //Если отключена вкладка ТУ то их исключаем
             if (!$item || $item->type == FreelancersPreviewModel::TYPE_TU && !in_array($item->user_id, $tmp_tu_uids)) {
                 continue;
             }
             //Инициализируем данные юзера в работе/услуге пока только логин нужен
             $key = $frl_ids_map[$item->user_id];
             $item->setUser(array('login' => $this->results[$key]['login']));
             //Инитим виджет если его нет
             if (!isset($this->results[$key]['preview'])) {
                 $this->results[$key]['preview'] = new FreelancersPreviewWidget();
             }
             //Добавляем работу в виджет
             $this->results[$key]['preview']->addItem($item);
             //Исключаем из дальнейшей обработки
             unset($frl_ids[$key], $tu_frl_ids[$key]);
         }
         //------------------------------------------------------------------
         $this->works = null;
         if ($frl_ids) {
             $this->works = $this->getUsersWorks($frl_ids, $uid);
         }
         //------------------------------------------------------------------
         //Если у пользователя не отображатся портфолио
         //то можно показать 3 последнии ТУ
         $exist_uids = $this->works ? array_keys($this->works) : array();
         $tu_uids = array_diff($frl_ids, $exist_uids);
         if ($tu_uids) {
             require_once ABS_PATH . '/tu/models/TServiceModel.php';
             $tserviceModel = new TServiceModel();
             if ($list = $tserviceModel->getListByUids($tu_uids, 3, freelancer::CATALOG_PORTFOLIO_MEM_LIFE)) {
                 $current_user_tu_ids = array();
                 foreach ($list as $item) {
                     $key = $frl_ids_map[$item['user_id']];
                     $item['login'] = $this->results[$key]['login'];
                     $this->results[$key]['tservices'][] = $item;
                     if ($item['user_id'] == $uid) {
                         $current_user_tu_ids[] = $item['id'];
                     }
                 }
                 if (!empty($current_user_tu_ids)) {
                     FreelancersPreviewModel::setExistPreviewData(FreelancersPreviewModel::TYPE_TU, $current_user_tu_ids);
                 }
             }
         }
     }
 }