Второе пожалание это мультикатегории. У меня на форуме длится вечная борьба модераторов: какой релиз правильнее где разместить. Иногда он переносится несколько раз туда обратно.

Решил добавить в `bb_topics` 3 дополнительных поля forum_id_ext1,forum_id_ext2,forum_id_ext3 и дополнительный select в форму добавления/редактирования релиза.
posting.tpl
<!-- IF CATS -->
<tr>
<td colspan="2">{CATS}</td>
</tr>
<!-- ENDIF -->
posting.php
if (!$forums_ext = $datastore->get('cat_forums')){
$datastore->update('cat_forums');
$forums_ext = $datastore->get('cat_forums');
}
$selected = [];
if(!empty($post_info['forum_id_ext1'])){
$selected[$post_info['forum_id_ext1']]=$post_info['forum_id_ext1'];
}
if(!empty($post_info['forum_id_ext2'])){
$selected[$post_info['forum_id_ext2']]=$post_info['forum_id_ext2'];
}
if(!empty($post_info['forum_id_ext3'])){
$selected[$post_info['forum_id_ext3']]=$post_info['forum_id_ext3'];
}
//var_dump($selected_);
$params = [];
foreach($forums_ext['c'] as $c){
if($c["cat_id"]!=$post_info['cat_id'])continue;
$fparams = [];
foreach($forums_ext['f'] as $f){
if($f["forum_id"]==$forum_id) continue;
if(in_array($f["forum_id"], $bb_cfg['multicategories_not_allow_arr'])) continue;
if($f["cat_id"]==$c["cat_id"]) {
//$key = $f["forum_name"].'<|||>'.strip_tags(bbcode2html($f['text']));
$fparams[(($f["forum_parent"]!=0)?" ":'').fc_name_lang($f["forum_name"],$userdata["user_lang"])] = $f["forum_id"];
}
}
$params[$c["cat_title"]] = $fparams;
}
//var_dump($params);
$extra_forums = build_bootstrap_select ('extra_forums[]', $params, $selected, HTML_SELECT_MAX_LENGTH, 10, '',false,true, $lang['EXTRA_CATEGORIES'],3);
//vdn($post_info);
$template->assign_vars(array(
'FORUM_NAME' => htmlCHR($forum_name),
//'FORUM_ID' => $forum_id,
'PAGE_TITLE' => $page_title,
'CATS' => (!in_array($forum_id, $bb_cfg['multicategories_not_allow_arr']))? $extra_forums : false,
......
functions.php
function build_bootstrap_select ($name, $params, $selected = null, $max_length = HTML_SELECT_MAX_LENGTH, $multiple_size = false, $js = '',$data_images = false,$search=false,$label_text=false,$max_options=false)
{
global $lang;
if (empty($params)) return '';
//vdn($data_images);
$this->options = '';
$this->selected = array_flip((array) $selected);
$this->max_length = $max_length;
$this->attr = array();
$this->cur_attr =& $this->attr;
if (isset($params['__attributes']))
{
$this->attr = $params['__attributes'];
unset($params['__attributes']);
}
$this->_build_bootstrap_select_rec($params,$data_images);
$select_params = ($js) ? " $js" : '';
$select_params .= ($multiple_size) ? ' multiple="multiple" data-size="'. $multiple_size .'" size="'. $multiple_size .'"' : '';
$select_params .= ($search) ? ' data-live-search="true"' : '';
$select_params .= ($max_options) ? ' data-max-options="'. (int)$max_options .'"' : '';
$select_params .= ($max_options) ? ' data-max-options-text="'. sprintf($lang['SLECTPICKER_MULTIPLE_MAX'], $max_options) .'"' : '';
//
$select_params .= ' name="'. htmlCHR($name) .'"';
$select_params .= ' id="'. htmlCHR($name) .'"';
$select_params .= ' class="form-control selectpicker"';
$label_text = ($label_text) ? '<label for="'. htmlCHR($name) .'">'.$label_text.'</label>' : '';
return "\n{$label_text}\n<select {$select_params}>\n". $this->options ."</select>\n";
}
function _build_bootstrap_select_rec ($params,$data_images=false)
{
//var_dump($params);
foreach ($params as $opt_name => $opt_val)
{
$opt_name = rtrim($opt_name);
//vdn($data_images);
if (is_array($opt_val))
{
$this->cur_attr =& $this->cur_attr[$opt_name];
$label = htmlCHR(str_short($opt_name, $this->max_length));
$this->options .= "\t<optgroup label=\"". $label ."\">\n";
$this->_build_bootstrap_select_rec($opt_val);
$this->options .= "\t</optgroup>\n";
$this->cur_attr =& $this->attr;
}
else
{
$text = htmlCHR(str_short($opt_name, $this->max_length));
if(stristr($opt_name,'<|||>')){
$tmp_arr = explode('<|||>',$opt_name);
$text = (!empty($tmp_arr[0])) ? htmlCHR(str_short($tmp_arr[0], $this->max_length)) : $text;
$data_subtext = (!empty($tmp_arr[1])) ? ' data-subtext="'. htmlCHR($tmp_arr[1]) .'"' : $text;
}
else{
$data_subtext = '';
}
$value = ' value="'. htmlCHR($opt_val) .'"';
$class = isset($this->cur_attr[$opt_name]['class']) ? ' class="'. $this->cur_attr[$opt_name]['class'] .'"' : '';
$style = isset($this->cur_attr[$opt_name]['style']) ? ' style="'. $this->cur_attr[$opt_name]['style'] .'"' : '';
$selected = isset($this->selected[$opt_val]) ? HTML_SELECTED : '';
$disabled = isset($this->cur_attr[$opt_name]['disabled']) ? HTML_DISABLED : '';
$images = ($data_images AND @getimagesize("images/position/".$opt_val.".png")) ? ' data-image="images/position/'.$opt_val.'.png?2"':"";
$this->options .= "\t\t<option".$class . $style . $selected . $disabled . $data_subtext . $value. $images. '>'. $text ."</option>\n";
}
}
}
Это позволят пользователю выбрать 3 дополнительных категории для релиза. Если он отметит доп категории, то во vieforum.php выборка будет проходить по условию
SELECT t.topic_id
FROM ". BB_TOPICS ." t
WHERE t.forum_id = $forum_id OR ((t.forum_id_ext1 = $forum_id OR t.forum_id_ext2 = $forum_id OR t.forum_id_ext3 = $forum_id) AND t.forum_id NOT IN(".$bb_cfg['multicategories_not_allow']."))
$only_new_sql
$title_match_sql
$limit_topics_time_sql
$order_sql
LIMIT $start, $topics_per_pageГде
$bb_cfg['multicategories_not_allow'] это список категорий в которых запрещены мультикатегории (архив, приватное итд)
Сделано довольно костыльно, изначально вообще думал создать одно поле с указанием форумов зерез запятую наплевав на всякие "нормальные формы"
Раздачи в других форумах буду помечаться другим цветом с указанием главной категории под ними
Учите php друзья и мои правки покажутся вам полезными и легкими 😉