/** * Возвращает список проектов. * * @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; }