/** * @param int $sectionId * @param bool $forPublic * @return static[] */ public static function findAllBySection($sectionId, $forPublic = false) { if (!$forPublic) { return self::findAllByAttributes(['section_id' => $sectionId], ['order' => '`order` ASC']); } if (!UserAccess::get()->canRead($sectionId)) { return []; } $condition = new ModelCondition(['model' => __CLASS__]); $condition->join = "LEFT JOIN forum_groups2categories ON (category_id = id AND group_id = :group)"; $condition->addCondition("canread IS NULL OR canread = 1"); $condition->setParam(":group", UserAccess::get()->getUserGroup($sectionId, true)); $condition->order = "`order` ASC"; $condition->with = ['subcategories', 'subcategories.lastActiveThread', 'subcategories.lastActiveUser']; $condition->compareColumn("section_id", $sectionId); $categories = self::findAll($condition); if (WebApp::get()->user()->isConnected()) { $subcategories = self::getDb()->table('forum_userhiddensubcategories')->where("user_id = :user")->setParam(":user", WebApp::get()->user()->id)->get(); $subcategories = ArrayHelper::get()->transform($subcategories, "subcategory_id"); foreach ($categories as $category) { if ($category->subcategories) { foreach ($category->subcategories as $subcategory) { if (in_array($subcategory->id, $subcategories)) { $subcategory->hidden = true; } } } } } return $categories; }
/** * @param DbModel[] $models * @param string|array $fields * @return ModelCondition */ public function getConditionForModels($models, $fields) { $key = '__parentRelationKey'; $column = "(CASE "; $mCondition = new ModelCondition(['model' => $this->model]); if ($this->joins) { foreach ($this->joins as $join) { if (is_array($join[0])) { $t = '`' . key($join[0]) . '` as `' . current($join[0]) . '`'; } else { $t = '`' . $join[0] . '`'; } $c = []; // columns; foreach ($join[1] as $col1 => $col2) { if (is_array($col2)) { } else { if ('!=' == substr($col2, 0, 2)) { } elseif ('>=' == substr($col2, 0, 2)) { } elseif ('<=' == substr($col2, 0, 2)) { } elseif ('>' == $col2[0]) { } elseif ('<' == $col2[0]) { } else { } } } // values; foreach ($join[2] as $col => $value) { if (is_array($value)) { } else { if ('!=' == substr($value, 0, 2)) { } elseif ('>=' == substr($value, 0, 2)) { } elseif ('<=' == substr($value, 0, 2)) { } elseif ('>' == $value[0]) { } elseif ('<' == $value[0]) { } else { } } } // type; $mCondition->join .= $join[3] . $t . " ON (" . implode(') AND (', $c) . ")"; } } foreach ($this->conditions as $ck => $condition) { switch ($condition[0]) { case "=": case "!=": $parentColumn = $condition[1]; // for now it only supports single column for this type of relations; $relationColumn = $condition[2]; // same for relation column if (is_string($parentColumn) && (false !== strpos($parentColumn, '.') && false !== strpos($parentColumn, '_'))) { $r = $relationColumn; $relationColumn = $parentColumn; $parentColumn = $r; } if (is_array($relationColumn)) { $relationColumnListForIn = []; foreach ($relationColumn as $c) { $relationColumnListForIn[] = $this->_column($c, true); } $relationColumnListForIn = implode(', ', $relationColumnListForIn); } else { $relationColumnListForIn = $relationColumn; } $conditionParts = []; foreach ($models as $mk => $model) { // generates CASE column WHEN parentv1 THEN parentk1 WHEN parentv2 THEN parentk2 ELSE -1 AS __parentRelationKey + the condition itself $paramKey = ':' . $ck . '_' . $mk . '_'; if (is_array($parentColumn) && is_array($relationColumn)) { $column .= "WHEN ("; $columnList = []; foreach ($parentColumn as $col) { $mCondition->setParam($paramKey . $col, $model->{$col}); $conditionParts[] = $paramKey . $col . ('!=' == $condition[0] ? 'NOT' : '') . ' IN ( ' . $relationColumnListForIn . ' )'; $columnList[] = $paramKey . $col . ('!=' == $condition[0] ? 'NOT' : '') . ' IN ( ' . $relationColumnListForIn . ' )'; } $column .= implode(' OR ', $columnList); $column .= ") THEN {$mk} "; } elseif (is_array($parentColumn)) { $column .= "WHEN (" . $this->_column($relationColumn, true) . ('!=' == $condition[0] ? 'NOT' : '') . ' IN '; $paramList = []; foreach ($parentColumn as $col) { $mCondition->setParam($paramKey . $col, $model->{$col}); $paramList[] = $paramKey . $col; } $conditionParts[] = $this->_column($relationColumn, true) . ('!=' == $condition[0] ? 'NOT' : '') . ' IN (' . implode(', ', $paramList) . ')'; $column .= "(" . implode(", ", $paramList) . ")"; $column .= ") THEN {$mk} "; } elseif (is_array($relationColumn)) { $mCondition->setParam($paramKey . $parentColumn, $model->{$parentColumn}); $conditionParts[] = $paramKey . $parentColumn . ('!=' == $condition[0] ? 'NOT' : '') . " IN ({$relationColumnListForIn})"; $column .= "WHEN {$paramKey} . {$parentColumn} " . ('!=' == $condition[0] ? 'NOT' : '') . " IN ({$relationColumnListForIn}) THEN {$mk} "; } else { if ("(CASE " == $column) { $column .= $this->_column($relationColumn, true); } $p = str_replace('.', '__', $paramKey . $relationColumn); $mCondition->setParam($p, $model->{$parentColumn}); $conditionParts[] = $p; $column .= " WHEN " . $p . " THEN {$mk} "; } } if (is_string($parentColumn) && is_string($relationColumn)) { $mCondition->addCondition($this->_column($relationColumn, true) . ('!=' == $condition[0] ? 'NOT' : '') . " IN (" . implode(', ', $conditionParts) . ")"); } else { $mCondition->addCondition('(' . implode(") OR (", $conditionParts) . ')'); } break; case "==": case "=attribute": if ($condition[0] == '=attribute') { // for attribute read the value $parentModel = get_class(current($models)); $c = $condition[2]; if (false === strpos($c, '(')) { $condition[2] = $parentModel::$c; } else { // for method call it and get the value; $c = substr($c, 0, strlen($c) - 2); $condition[2] = call_user_func("{$parentModel}::{$c}"); } } $mCondition->compareColumn($condition[1], $condition[2]); break; } } $column .= "ELSE -1 END) AS `{$key}`"; //die($column); if (is_array($fields)) { $fields[] = $column; } else { $fields .= ', ' . $column; } $mCondition->fields = $fields; return $mCondition; }
/** * @param ForumUser2Section[] $sections * @param $limit * @param $offset * @param null $sectionId * @return array|static[] */ protected static function _findRecent($sections, $limit, $offset, $sectionId = null) { $guest = false; $sectionsIds = []; if (1 === count($sections) && is_null($sections[0])) { if (is_null($sectionId)) { return []; } $sectionsIds = [$sectionId]; $guest = true; } elseif (count($sections)) { $sectionsIds = ArrayHelper::get()->transform($sections, 'section_id'); } $userId = WebApp::get()->user()->isConnected() ? WebApp::get()->user()->id : 0; $reload = !WebApp::get()->cache()->exists('User:'******':visibleSubcategories'); $ids = []; if (!$reload) { $info = WebApp::get()->cache()->value('User:'******':visibleSubcategories'); if ($info['time'] < time() - 720) { //force refresh once every 30m $reload = true; } else { $ids = $info['categories']; } } if ($reload) { $condition = new ModelCondition(['model' => ForumSubcategory::className()]); $condition->with = ['category']; if ($guest) { $groups = [ForumSection::findByPk($sectionId)->default_visitors_group_id]; } else { $groups = ArrayHelper::get()->transform($sections, 'group_id'); } if ($groups) { $groups = implode(', ', $groups); $condition->join = "LEFT JOIN forum_groups2categories ON (forum_groups2categories.category_id = category.id AND forum_groups2categories.group_id IN ({$groups}))"; $condition->addCondition("forum_groups2categories.canread IS NULL OR forum_groups2categories.canread = 1"); $condition->addInCondition('category.section_id', $sectionsIds); $categories = ForumSubcategory::findAll($condition); } else { $categories = []; } $ids = []; foreach ($categories as $cat) { if (!isset($ids[$cat->category->section_id])) { $ids[$cat->category->section_id] = []; } $ids[$cat->category->section_id][] = $cat->id; } WebApp::get()->cache()->set('User:'******':visibleSubcategories', ['time' => time(), 'categories' => $ids]); } $finalIDs = []; if ($guest) { $finalIDs = $ids[$sectionId]; } else { foreach ($sections as $s) { if (isset($ids[$s->section_id])) { foreach ($ids[$s->section_id] as $id) { $finalIDs[] = $id; } } } } if (!$finalIDs) { return []; } $condition = new ModelCondition(['model' => __CLASS__]); $condition->with = ['category', 'subcategory', 'lastActiveUser', 'owner']; $condition->addInCondition('subcategory_id', $finalIDs); $condition->compareColumn('deleted', 0); $condition->order = "GREATEST(IFNULL(t.edit_time, t.create_time), IFNULL(t.last_reply_date, t.create_time)) DESC"; $condition->limit = $limit; $condition->offset = $offset; return self::findAll($condition); }