Перейти к контенту

Полезные примочки от Song'а


Рекомендуемые сообщения

Внимание! Все add-on'ы приводимые в этом топике преднозначены для форумов версий 1.2, 1.3

 

Примочка №1

 

Если на форум стоит премодерация новых топиков, то эту премодерацию можно легко обойти, переместив топик из другого форума.

Некоторые могут сказать, что дескать это ж модератор, ему можно.

Но вот вам пример. В один форум идёт вечный спам. Модератору этого форума надоедает чистить, и он просит ставить премодерацию.

Какой-нибудь нахальный гость плодит эту тему, пока до его одноизвилинного мозга наконец не доходит, что безрезультатно, тема не появится.

Тогда он идёт в раздел по похожей тематике и оставляет тему там. Радивый модератор того раздела славно и совершенно правильно делает свою работу: он переместит эту тему по назначению..

 

Итак как пофиксить.

Файл sources/lib/modfunctions.php

 

Находим кусок кода:

  //---------------------------------- 
 // Update the topic 
 //---------------------------------- 

 $DB->query("UPDATE ibf_topics SET forum_id=$moveto WHERE forum_id=$source AND tid".$tid);

 

и заменяем на

// Song * permit activation topic if the destination forum is moderated within topics, 06.04.2005

 $preview = "";

 $DB->query("SELECT preview_posts FROM ibf_forums WHERE id='".$moveto."'");

 $moderate = $DB->fetch_row();

 if ( $moderate['preview_posts'] and ( $moderate['preview_posts'] == 1 or $moderate['preview_posts'] == 2 ) )
 {
	 $preview = ", approved=0";
 }

// Song * permit activation topic if the destination forum is moderated within topics, 06.04.2005
 
 //---------------------------------- 
 // Update the topic 
 //---------------------------------- 

 $DB->query("UPDATE ibf_topics SET forum_id=".$moveto.$preview." WHERE forum_id=$source AND tid".$tid);

Ссылка на комментарий
Поделиться на других сайтах

Примочка №2

 

Функция слежения за PM письмами, доступная в профиле выполняется очень долго, потому как написана очень нерационально и без нужных индексов.

Лично у меня вызов этой функции делается около 7-10 секунд. Это конечно же не дело.

Давайте убыстрим? :D

 

Первое нам нужно добавить индекс:

ALTER TABLE ibf_messages ADD INDEX (from_id)

 

Это сократит выполнение функции вдвое.

Давайте сократим ещё вдвое ;)

Дело в том, что функция, написанная создателями форума очень нерациональна.

 

Схематично она выглядит так:

Запрос 1

Обработка результатов запроса 1

 

Запрос 2

Обработка результатов запроса 2

 

Это было бы допустимо, если бы запросы были разные. Но на самом деле (вы не поверите :) ) они разделяются всего лишь на одну цифру.

Выход так и напрашивается - объединить оба запроса в 1 и написать вывод в один цикл.

 

Файл Messenger.php

Находим и вырезаем полностью функцию

function show_tracking()

 

Вместо неё пишем мою: :)

// Song * new tracking function
 function show_tracking() {
	 global $ibforums, $DB, $std, $print;
	 
	 //---------------------------------------------
	 // Get all tracked and read messages
	 //---------------------------------------------
	 
	 $this->output .= $this->html->trackread_table_header();
	 
	 $DB->query("SELECT m.*, mp.name as to_name, mp.id as memid 
       FROM ibf_messages m, ibf_members mp
     WHERE m.tracking=1 
        AND m.from_id='".$this->member['id']."'
        AND m.member_id=mp.id 
     ORDER BY m.read_state DESC, msg_date DESC");

	 if ( $DB->get_num_rows() )
	 {
	 $current = "";

	 $change = FALSE;

   while( $row = $DB->fetch_row() )
   {
   if ( $row['read_state'] != $current and !$row['read_state'] )
   {
  	 if ( $current == "" ) $this->output .= $this->html->No_msg_inbox();

  	 $this->output .= $this->html->trackread_end();
     $this->output .= $this->html->trackUNread_table_header();
  	 $change = TRUE;
   }

   if ( $row['read_state'] )
   {
     $row['icon']     = "<{M_READ}>";
     $row['date']     = $std->get_date( $row['read_date'] , 'LONG' );
     $this->output .= $this->html->trackread_row( $row );
   } else
   {
     $row['icon']     = "<{M_UNREAD}>";
     $row['date']     = $std->get_date( $row['msg_date'] , 'LONG' );
     $this->output .= $this->html->trackUNread_row( $row );
   }

   $current = $row['read_state'];
   }

	 if ( !$change )
	 {
   $this->output .= $this->html->trackread_end();
  	 $this->output .= $this->html->trackUNread_table_header();
  	 $this->output .= $this->html->No_msg_inbox();
	 }

   $this->output .= $this->html->trackUNread_end();

	 } else
	 {
   $this->output .= $this->html->No_msg_inbox();
	 $this->output .= $this->html->trackread_end();

   $this->output .= $this->html->trackUNread_table_header();
   $this->output .= $this->html->No_msg_inbox();
   $this->output .= $this->html->trackUNread_end();
	 }
	 
	 $this->page_title = $ibforums->lang['t_welcome'];

	 $this->nav        = array( "<a href='".$this->base_url."act=UserCP&CODE=00'>".$ibforums->lang['t_title']."</a>" );
	 
	 
 }
// Song * new tracking function

Ссылка на комментарий
Поделиться на других сайтах

Примочка №3

Мы знаем, что в настройках групп можно включить право ответа в закрытые темы.

Как правило, такое право дают для группы модераторов.

При этом любой модератор может отвечать в закрытую тему любого раздела, хотя сам не модерирует там.

Предлагаю пофиксить.

Файлы post_reply_post.php, post_q_reply_post.php, post_edit_post.php

 

Находим:

  // Is the topic locked?
 
 if ($this->topic['state'] != 'open')
 {
	 if ($ibforums->member['g_post_closed'] != 1)
	 {
   $std->Error( array( LEVEL => 1, MSG => 'locked_topic') );
	 }
 }

 

меняем на:

  // Is the topic locked?

 if ( $this->topic['state'] != 'open' )
 {
         if ( !$ibforums->member['id'] or !( $ibforums->member['g_post_closed'] and ( $ibforums->member['g_is_supmod'] or $class->moderator['mid'] ) ) )
	 {
   $std->Error( array( LEVEL => 1, MSG => 'locked_topic') );
	 }
 }

Ссылка на комментарий
Поделиться на других сайтах

  • 1 месяц спустя...

Примочка №4

Добавляем автоинкремент пользователей.

 

Как ни странно, авторы IPB не включали автоинкремент в таблицу пользователей. Тем не менее зря.

Это досадное упущение вызывает ошибки при активной регистрации пользователей.

 

Если коротко, то регистрация выполняется так:

1) Получаем максимальный id пользователя

2) Прибавляем единицу

3) Добавляем нового мебера

4) Добавляем дополнительные поля мембера

 

Всё бы хорошо, если между п. 1 и п.2 не вклинивалась регистрация 2-го мембера, который тоже захотел зарегистрироваться в данный момент. В этом случае система даёт сбой, id "сдваивается", а т.к. на это поле назначен PRIMARY ключ, то выдаётся MySQL ошибка.

 

Как от этого избавиться.

Прежде всего, почему разработчики не сделали автоинкремента? Не не знали же они про него :D

Отчасти есть тому объяснение.

В таблице мемберов есть участник с именем Guest. И id унего 0.

Если бы был автоинкремент, тогда бы id 0-го быть не могло.

 

Врочем, для меня всегда оставалось загадкой для чего нужен юзер Guest с id=0.

При авторизации он участия не принимает. При удалении этого пользователя ничего не меняется.

 

Итак,

 

Шаг 1. AdminCP -> SQL Managment -> MySQL ToolBox -> область "Manual Query".

Введите и исполните запрос

DELETE FROM ibf_members WHERE id=0

 

Ша 2. Файл Register.php

Найдите

  //+--------------------------------------------
 //| Find the highest member id, and increment it
 //| auto_increment not used for guest id 0 val.
 //+--------------------------------------------
 
 $DB->query("SELECT MAX(id) as new_id FROM ibf_members");
 $r = $DB->fetch_row();
 
 $member_id = $r['new_id'] + 1;

Удалите этот кусок.

 

Найдите на 2 строчки ниже

       'id'              => $member_id,

 

Удалите этот кусок.

 

Найдите

  $DB->query("INSERT INTO ibf_members (" .$db_string['FIELD_NAMES']. ") VALUES (". $db_string['FIELD_VALUES'] .")");

 

Добавьте ниже:

	// id of new user
$member_id = $DB->get_insert_id();

$member['id'] = $member_id;

 

Шаг 3. Файд ad_members.php

 

Найдите

  //+--------------------------------------------
 //| Find the highest member id, and increment it
 //| auto_increment not used for guest id 0 val.
 //+--------------------------------------------
 
 $DB->query("SELECT MAX(id) as new_id FROM ibf_members");
 $r = $DB->fetch_row();
 
 $member_id = $r['new_id'] + 1;

Удалите этот кусок.

 

Чуть ниже найдите

                'id'          => $member_id,

Удалите этот кусок.

 

Найдите

  $DB->query("INSERT INTO ibf_members (" .$db_string['FIELD_NAMES']. ") VALUES (". $db_string['FIELD_VALUES'] .")");
 
 //$member_id = $DB->get_insert_id();

 

Расскоментируйте вторую строчку (уберите две косые черты).

Если у вас нет такой строчки то добавьте (без косых черт само собой).

 

Шаг 4. AdminCP -> SQL Managment -> MySQL ToolBox -> область "Manual Query".

 

Введите и исполните запрос

ALTER TABLE ibf_members MODIFY id mediumint(8) UNSIGNED NOT NULL default 0 auto_increment

Ссылка на комментарий
Поделиться на других сайтах

Примочка №5.

 

Часто бывает ситуация, когда юзер, зарегистрировавшись на форуме, задаёт ответ, подписывается на тему и, получив ответ, уходит с форума. Со временем его электронный адрес пропадает, а темы или форумы, подписанные на него продолжают пытаться отправляться.

 

Файл /sources/Admin/ad_member.php

 

1. Найти

  if ($custom_out != "")
 {
 
	 $ADMIN->html .= $SKIN->end_table();
	 
	 
	 $SKIN->td_header[] = array( " "  , "40%" );
	 $SKIN->td_header[] = array( " "  , "60%" );
	 
	 //+-------------------------------+
	 
	 $ADMIN->html .= $SKIN->start_table( "Custom Profile Fields" );
	 
	 
	 $ADMIN->html .= $custom_out;
           
 }

 

Вставить перед этим:

  $SKIN->td_header[] = array( " "  , "40%" );
 $SKIN->td_header[] = array( " "  , "60%" );
 $ADMIN->html .= $SKIN->start_table( "Контроль подписок" );
 $ADMIN->html .= $SKIN->add_td_row( array( "Удалить все подписки пользователя на темы и форумы?" ,
             $SKIN->form_checkbox("subscribe_delete", 0)
             )      );

 

2. Найти:

 

  //----------------------------------
 // Custom profile field stuff
 //----------------------------------

 

Вставить перед этим:

 

  if ( $IN['subscribe_delete'] )
 {

	 $DB->query("DELETE FROM ibf_tracker WHERE member_id={$IN['mid']}");

	 $DB->query("DELETE FROM ibf_forum_tracker WHERE member_id={$IN['mid']}");

 }

Ссылка на комментарий
Поделиться на других сайтах

  • 3 месяца спустя...

Примочка №6

 

Указываем в title'е юзера о том, что он забанен.

 

Файл Topics.php:

 

$query = "SELECT p.*, m.id, m.name, m.mgroup, m.email, m.joined, m.avatar, m.avatar_size, m.posts, m.aim_name, m.icq_number,

    m.signature,  m.website, m.yahoo, m.integ_msg, m.title, m.hide_email, m.msnname,  m.warn_level, ....

Заменить выделенный кусочек на

 

IF(m.temp_ban=1,'".$ibforums->lang['banned_title']."',m.title) as title

 

А в файлы lang_topic.php всех языков внести нужную надпись

 

Файл Profile.php

 

Ищем

 

SELECT m.*, g.g_title as group_title FROM ibf_members m, ibf_groups g...

 

После выделенного куска дописываем:

 

IF(m.temp_ban=1,'".$ibforums->lang['banned_title']."',m.title) as title,

 

В файлы lang_profile.php всех языков добавляем желаемую надпись.

Ссылка на комментарий
Поделиться на других сайтах

  • 2 месяца спустя...

Примочка №7. Помощь в отладке ошибок

 

Идея: GIV

Внимание! Версия PHP от 4.3.0 !

 

Очень часто когда мы разрабатываем модификации, у нас вылезают ошибки форума. Поясню: не ошибки интерпретатора php, а именно ошибки форума, который он выдаёт в функции func:: Error.

 

Следующая модификация очень поможет вам с отладкой своих модификаций.

Суть её заключается в том, что под стандартной ошибкой показывается "история" наследования классов форума с указанием номеров строк (!) и названием функций и классов.

С такой информацией вы сможете быстро отладить свой код, понять где как и почему код у вас не работает так как надо.

К примеру, такой мод понадобился мне при разработке мода мультиаттача

 

1. В функцию класса func:: $std->Error(), файл functions.php

перед

		$print = new display();

добавляем:

// Song * admin debug info

if ( $ibforums->member['g_access_cp'] )
{
	$html = str_replace("<!--IBF.ADMIN_ERROR_CODES-->", $this->admin_debug_info(debug_backtrace()), $html);
}

// Song * admin debug info

 

2. В этот же класс функцией ниже добавляем новую функцию:

// Song * admin debug info

function admin_debug_info($debug_trace = array()) {
global $skin_universal;

$class						= " class='row%d'";

foreach($debug_trace as $error)
{
	$debug_array[]				= "<tr>";

	$idx					= 1;

	foreach($error as $line)
	{
		if ( !is_array($line) )
		{
			$curr			= "<td";

			if ( $idx - 1 )
			{
				$curr		.= " align='center'";
			}

			$curr			.= sprintf($class,( $idx % 2 ) ? 1 : 2).">".$line."</td>";

			$debug_array[]		= $curr;

				$idx++;
		}
	}

	$debug_array[count($debug_array) - 1]	= "</tr>";
}

$debug_txt					= implode("", $debug_array);

$debug_txt					= $skin_universal->describe_error($debug_txt);

return $debug_txt;

}

 

3. В файле skin_global.php находим скиновую функцию

function Error($message,....

и в нужном месте включаем наш трейс, например перед окончанием таблицы: перед

<div class='tableborder'>
<div class='pformstrip' align="center">< 
 <a href='javascript:history.go(-1)'>{$ibforums->lang['error_back']}</a>   
</div>
</div>

добавим

<!--IBF.ADMIN_ERROR_CODES-->

 

4. В скин функцией ниже добавляем ещё одну функцию:

function describe_error($data) {
global $ibforums;
return <<<EOF

<br><b>{$ibforums->lang['desc_error_header']}</b>
<div class='tableborder'>
<div class='maintitle'>{$ibforums->lang['debug_caption']}</div>
 <table width='100%' border='0'>
  <tr>
<th class='pformstrip'>{$ibforums->lang['debug_php_file']}</th>
<th class='pformstrip'>{$ibforums->lang['debug_line_number']}</th>
<th class='pformstrip'>{$ibforums->lang['debug_func_name']}</th>
<th class='pformstrip'>{$ibforums->lang['debug_class_name']}</th>
  </tr>
  {$data}
 </table>
</div>
<br>

EOF;
}

 

5. В языковых файлах вам нужно описать используемые язоковые макросы на свой вкус.

 

6. That is all!

Изменено пользователем Song
Ссылка на комментарий
Поделиться на других сайтах

  • 1 год спустя...

Несколько замечаний по примочкам

Примочка №4

Последний mysql запрос

ALTER TABLE ibf_members MODIFY id mediumint(8) UNSIGNED NOT NULL default 0 auto_increment

в таком виде не выполнится. Выдаст ошибку о неверном дефолтном значении для поля id

Правильно будет так:

ALTER TABLE ibf_members MODIFY id mediumint(8) UNSIGNED NOT NULL auto_increment

 

Примочка №5

Здесь небольшая ошибка

Вставить перед этим:
$SKIN->td_header[] = array( " "  , "40%" );
$SKIN->td_header[] = array( " "  , "60%" );
$ADMIN->html .= $SKIN->start_table( "Контроль подписок" );
$ADMIN->html .= $SKIN->add_td_row( array( "Удалить все подписки пользователя на темы и форумы?" ,
		 $SKIN->form_checkbox("subscribe_delete", 0)
		 )	  );

Нужно так:

$ADMIN->html .= $SKIN->end_table();

$SKIN->td_header[] = array( " "  , "40%" );
$SKIN->td_header[] = array( " "  , "60%" );
$ADMIN->html .= $SKIN->start_table( "Контроль подписок" );
$ADMIN->html .= $SKIN->add_td_row( array( "Удалить все подписки пользователя на темы и форумы?" ,
		 $SKIN->form_checkbox("subscribe_delete", 0)
		 )	  );

Т.е. прежде чем открыть новую таблицу, нужно закрыть предыдущую.

Ссылка на комментарий
Поделиться на других сайтах

в таком виде не выполнится. Выдаст ошибку о неверном дефолтном значении для поля id

Правильно будет так:

В то время когда я писал эту примочку, стабильной была MySQL 3-я версия. В ней выполнится.

Соответственно и пробовал всё на ней.

Ссылка на комментарий
Поделиться на других сайтах

Присоединиться к обсуждению

Вы можете ответить сейчас, а зарегистрироваться позже. Если у вас уже есть аккаунт, войдите, чтобы ответить от своего имени.

Гость
Ответить в этой теме...

×   Вы вставили отформатированный текст.   Удалить форматирование

  Допустимо не более 75 смайлов.

×   Ваша ссылка была автоматически заменена на медиа-контент.   Отображать как ссылку

×   Ваши публикации восстановлены.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Зарузка...
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, вы соглашаетесь на использование файлов cookie, а также с нашим положением о конфиденциальности Политика конфиденциальности и пользовательским соглашением Условия использования.