/**
 * Сохранить выбор пользователя.
 * 
 * @param type $data
 *
 * @return \xajaxResponse
 */
function FPEP_saveProcess($data)
{
    $objResponse = new xajaxResponse();
    $uid = get_uid(false);
    if ($uid > 0 && !is_emp() && is_pro()) {
        require_once ABS_PATH . '/freelancers/models/FreelancersPreviewModel.php';
        $model = new FreelancersPreviewModel();
        $data['uid'] = $uid;
        if ($model->isValid($data)) {
            if ($model->save()) {
                require_once ABS_PATH . '/freelancers/widgets/FreelancersPreviewWidget.php';
                $data = $model->getLastItem();
                if (count($data)) {
                    $item = $data->current();
                    $item->setUser(array('login' => $_SESSION['login']));
                    $widget = new FreelancersPreviewWidget(array('is_ajax' => true));
                    $widget->addItem($item);
                    $html = $widget->render();
                    $objResponse->assign("preview_pos_{$model->getPos()}", 'innerHTML', $html);
                }
            }
        }
        $objResponse->call("window.popups_factory.getPopup('freelancersPreviewEditorPopup').close_popup");
    }
    return $objResponse;
}
 public function current()
 {
     $value = parent::current();
     $class_name = FreelancersPreviewModel::getTypeClass($value['type']);
     if ($class_name) {
         return new $class_name($value);
     }
     return;
 }
Exemple #3
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;
 }
 public function getUsersWorks($users, $uid)
 {
     global $DB;
     require_once ABS_PATH . '/freelancers/models/FreelancersPreviewModel.php';
     $sql = "SELECT p.id, p.user_id, p.name, p.descr, p.pict, p.prev_pict, p.show_preview, p.norder, p.prev_type, p.is_video\n               FROM portfolio p\n             INNER JOIN\n               portf_choise pc\n                 ON pc.user_id = p.user_id\n                AND pc.prof_id = p.prof_id \n             INNER JOIN freelancer f ON f.uid = p.user_id AND substring(f.tabs::text from 1 for 1)::integer = 1\n              WHERE p.user_id IN (" . implode(',', $users) . ")\n                AND p.prof_id = f.spec_orig\n                AND p.first3 = true\n              ORDER BY p.norder";
     $ret = $DB->rows($sql);
     $works = null;
     if ($ret) {
         $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);
         }
     }
     return $works;
 }