예제 #1
0
 /**
  * Возвращает список проектов.
  * 
  * @param integer $num_prjs		возвращает кол-во проектов
  * @param integer|array $kind   тип проектов (-1=5=Все проекты; 2=Конкурсы; 4=В офис; 6=Только для про)
  *                              если массив, то: array(тип, tops_only), где
  *                              tops_only: true, если нужно получить только закрепленные проекты.
  * @param integer $page			страница проектов (кол-во проектов на странице PAGE_SIZE)
  * @param boolean $comments		возвращать ли комментарии к проектам (проекты без Кандидат-Исполнитель)				
  * @param array   $filter		массив с фильтром проектов				
  * @param integer $prj_id       ID проекта, если не NULL то берется тинформация только об одном проекте
  * @param integer $is_closed    Конкурс или проект закрыт или нет
  * @param integer $to_date      Брать проекты только до этой даты.
  * @param boolean $withouttop   возвращать ли проекты не учитывая их закрепление
  * @return array				массив с информацией о проектах
  */
 function getProjects(&$num_prjs, $kind = -1, $page = 1, $comments = false, $filter = NULL, $is_blocked = true, $is_ajax = false, $prj_id = NULL, $is_closed = false, $to_date = NULL, $withouttop = false)
 {
     global $DB;
     list($kind, $tops_only) = (array) $kind;
     $is_emp = is_emp();
     $is_moder = hasPermissions('projects');
     $uid = $_SESSION['uid'];
     if ($uid && !$_SESSION['ph'] && !$is_ajax) {
         projects_filters::initClosedProjects();
     }
     $phidd = $_SESSION['ph'];
     $filterSql = new_projects::createFilterSql($filter, $kind);
     $ret = NULL;
     $limit = $this->page_size;
     if ((int) $page < 1) {
         $page = 1;
     }
     $offset = $to_date ? 0 : ($page - 1) * $limit;
     $slimit = $limit + (int) (!!$filterSql);
     // для проверки, есть ли след. страница.
     $addit = '';
     if ($filterSql) {
         if ($tops_only) {
             $addit = "(p.edit_date IS NOT NULL AND p.edit_date > NOW() - interval '2 month') AND ";
         } else {
             $addit = "(p.post_date > NOW() - interval '2 month') AND ";
         }
     }
     $addit .= (get_uid(false) ? '' : 'COALESCE(p.hide, false) = false AND ') . 'p.closed = false AND p.user_id <> 0 AND p.kind <> 9';
     if ($is_closed) {
         $addit .= ' AND ( p.end_date > NOW() OR p.end_date IS NULL )';
     }
     if ($kind == 6) {
         $addit .= ' AND p.pro_only = true';
     } else {
         if ($kind == 2) {
             $addit .= " AND (p.kind = 2 OR p.kind = 7)";
         } else {
             if ($kind != -1 && $kind != 5) {
                 $addit .= " AND p.kind = '{$kind}'";
             }
         }
     }
     if ($phidd && is_array($phidd)) {
         $hidden_projects = array();
         foreach ($phidd as $pkey => $pvalue) {
             $hidden_projects[] = $pkey;
         }
         $addit .= ' AND p.id NOT IN (' . implode(',', $hidden_projects) . ')';
     }
     if ($comments) {
         $comm = ' LEFT JOIN blogs_themes_old bt ON bt.id_gr = p.id AND bt.base = ' . ($kind == 2 ? 5 : 3);
         $sel = ', bt.thread_id, bt.messages_cnt - 1 as comm_count';
         if ($uid) {
             $comm .= " LEFT JOIN projects_watch pw ON pw.user_id = {$uid} AND pw.prj_id = p.id ";
             $sel .= ', pw.status AS prj_status';
         }
     }
     //выборка предложения по проекту пользователя
     if ($uid && !$is_emp) {
         $sel_offer = ", po.id as offer_id, po.refused, po.selected";
         $join_offer = " LEFT JOIN projects_offers po ON po.project_id = p.id AND po.user_id = '{$uid}' ";
     }
     // исключаем заблокированные проекты
     $sel_blocked = ", pb.reason as blocked_reason, pb.blocked_time, pb.project_id::boolean as is_blocked";
     $join_blocked = "LEFT JOIN projects_blocked pb ON p.id = pb.project_id ";
     if ($is_moder) {
         $sel_blocked .= ", admins.login as admin_login, admins.uname as admin_uname, admins.usurname as admin_usurname";
         $join_blocked .= "LEFT JOIN users as admins ON pb.admin = admins.uid ";
     } else {
         $join_c_blocked = $join_blocked;
         $wb = "(" . ($is_emp ? "p.user_id = {$uid} OR " : "") . " pb.project_id IS NULL) ";
         $where_blocked = "WHERE {$wb}";
         if ($filterSql) {
             $where_blocked = "";
         }
         $where_c_blocked = "AND {$wb}";
         if (!$is_blocked) {
             $join_is_blocked = $join_blocked;
             $where_is_blocked = "WHERE {$wb}";
             $where_is_c_blocked = "AND {$wb}";
         }
     }
     $offset = intvalPgSql((string) $offset);
     // условие, при котором проект в данный момент закреплен наверху ленты.
     $top_cond = ' ( (top_from IS NOT NULL AND now() BETWEEN top_from AND top_to) OR strong_top = 1 ) ';
     $top_payed_col = 'top_from';
     if (!$tops_only) {
         // Закрепленные получаем отдельным запросом.
         if ($withouttop) {
             $top_cond = "NOT(1=0)";
             $top_payed_col = "'epoch'";
             $order = 'p.post_date DESC';
             $tops = array();
             $tops_cnt = 0;
         } else {
             $top_cond = "NOT({$top_cond})";
             $top_payed_col = "'epoch'";
             $order = 'p.strong_top DESC, p.post_date DESC';
             $tops = $to_date ? array() : $this->getProjects($x, array($kind, true), 1, $comments, $filter, $is_blocked, $is_ajax, $prj_id);
             $tops_cnt = count($tops);
         }
         if ($offset >= $tops_cnt) {
             // Случай, когда топы не попадают на заданную страницу, но надо сдвинуть оффсет для
             // получения обычных проектов.
             $x_offset = $offset - ($tops_cnt > $slimit ? $slimit : $tops_cnt);
             $x_limit = $slimit;
             $tops = array();
         } else {
             // когда топ-проектов больше чем помещается на одну страницу
             // по-любому все топы должны быть на первой странице, обычных проектов уже не будет
             if ($page === 1) {
                 if ($tops_cnt > $limit) {
                     $limit = $tops_cnt;
                     $x_limit = 0;
                     // обычных проектов уже не надо
                 } else {
                     $x_limit = $slimit - $tops_cnt;
                 }
             } else {
                 $x_limit = $slimit - (($tops_cnt > $offset ? $offset : $tops_cnt) - $offset);
             }
             $x_offset = 0;
             //$tops = array_splice($tops, $offset, $slimit); // не зыбываем оставлять один проверочный в конце.
             if ($x_limit < 0) {
                 // Т.е. на странице вместились только топы.
                 $x_limit = 0;
             }
             if ($page !== 1) {
                 $tops = array();
             }
         }
         $limit_str = "LIMIT {$x_limit} OFFSET {$x_offset}";
         if ($to_date) {
             $where_date = $DB->parse(' AND p.post_date < ? ', $to_date);
         }
     } else {
         $order = 'p.strong_top DESC, sort_date ASC, p.post_date ASC';
         //$order = 'p.strong_top DESC, p.top_from DESC, p.post_date ASC';
         //$order = 'p.post_date DESC';
     }
     if ($prj_id) {
         $prjid_sql = " AND p.id = " . intval($prj_id);
         $limit_str = '';
     }
     // Показываем для всех, кроме модераторов и владельцев, только проект со статусом "Опубликован" (projects.state = 0)
     /*
     if (!$is_moder) {
         //$addit .= ' AND (p.state = 0 OR p.user_id = '.intval($uid).')';
         $addit .= " AND NOT(p.payed = 0 AND p.kind = ".self::KIND_VACANCY." AND p.state = ".self::STATE_MOVED_TO_VACANCY.")";
     }
     */
     $sql = "\n         SELECT p.*, {$top_payed_col} as top_payed, f.fname as logo_name, f.path as logo_path, NULL as category_name, city.city_name, country.country_name, e.login,\n                e.uid, e.uname, e.usurname, e.warn, e.role, e.is_pro, e.is_team, e.email, e.is_banned, e.self_deleted, e.is_verify, e.photo, e.reg_date, e.modified_time, e.photo_modified_time, fl.is_banned  as exec_is_banned \n                {$sel_offer} {$sel} {$sel_blocked}\n           FROM (\n             -- этот запрос оптимизирован под индекс 'ix projects/main'.\n             SELECT p.*,\n                -- особая сортировка: железные проекты по возрастанию даты публикации, остальные закрепленные по убыванию даты закрепления\n                CASE WHEN p.strong_top = 1 THEN (p.post_date - NOW()) ELSE (NOW() - p.top_from) END as sort_date\n             FROM projects p {$join_is_blocked}\n              WHERE {$addit} {$where_is_c_blocked} {$where_date} {$filterSql} AND {$top_cond} {$prjid_sql}\n              ORDER BY {$order} {$limit_str}\n           ) as p\n         INNER JOIN\n           employer e\n             ON e.uid = p.user_id\n         LEFT JOIN\n           freelancer fl\n             ON fl.uid = p.exec_id\n         LEFT JOIN\n           file_projects f\n             ON f.id = p.logo_id\n         LEFT JOIN \n           city \n             ON city.id = p.city\n         LEFT JOIN \n           country\n             ON country.id = p.country\n         {$join_blocked}\n         {$join_offer}\n         {$comm}\n         {$where_blocked}\n         ORDER BY {$order}";
     $ret = $DB->rows($sql);
     if (($ret || $tops) && !$tops_only) {
         if ($tops) {
             $ret = array_merge($tops, $ret ? $ret : array());
         }
         $blocked_cnt = 0;
         $scnt = count($ret);
         if ($scnt > $limit) {
             array_pop($ret);
             // убиваем проверочный проект (см. $slimit).
         }
         if (!$is_moder) {
             foreach ($ret as $k => $v) {
                 if ($v['is_blocked'] && !($is_emp && $v['user_id'] == $uid) || $v['is_banned'] == 1) {
                     unset($ret[$k]);
                     $blocked_cnt++;
                 }
             }
         }
         if ($num_prjs != 'nenado') {
             if (!$filterSql) {
                 $num_prjs = (int) new_projects::getProjectsCount($kind, $page, $is_emp ? $uid : null, $is_moder);
             } else {
                 $cnt = $scnt;
                 //+ $blocked_cnt;
                 $num_prjs = $offset + $cnt;
                 // + (int)($cnt > $limit) * $limit; // 0012679
             }
         }
     }
     setlocale(LC_ALL, 'en_US.UTF-8');
     return $ret;
 }