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

Полезные примочки от 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-я версия. В ней выполнится.

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

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

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

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

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

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

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

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

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

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

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