Сегодня я вам расскажу, как можно оптимизировать PHP-Nuke с помощью переписания кода ядра и удаления или замены модулей.

Итак, начнем! Для начала мы разберемся с модулями. Нам нужно убрать все ненужные и тяжелые модули. Ниже таблица, которой вы можете руководствоваться при удалении модулей.

Название модуля Файлы Таблицы
Журнал 
(Journal)
modules/Journal/ nuke_journal 
nuke_journal_comments 
nuke_journal_stats 
Энциклопедия 
(Encyclopedia)

modules/Encyclopedia/

admin/case/case.encyclopedia.php
admin/links/links.encyclopedia.php
admin/modules/encyclopedia.php

nuke_encyclopedia 
nuke_encyclopedia_text
Рецензии 
(Reviews)

modules/Reviews/

admin/case/case.reviews.php
admin/links/links.reviews.php
admin/modules/reviews.php

nuke_reviews
nuke_reviews_add
nuke_reviews_comments
nuke_reviews_main
Специальный раздел 
(Sections)

modules/Sections/

admin/case/case.sections.php
admin/links/links.sections.php
admin/modules/sections.php

nuke_sections
Заголовки статей 
(AvantGo)
modules/AvantGo/ отсутствует
Группы пользователей 
(Groups)
admin/case/case.groups.php
admin/links/links.groups.php
admin/modules/groups.php
nuke_groups
nuke_groups_points
Наши пользователи
(Members_List)
modules/Members_List/ отсутствует
Лучшее 
(Top)
modules/Top/ nuke_seccont
Статистика сайта 
(Statistics)
modules/Statistics/ nuke_stats_date
nuke_stats_hour 
nuke_stats_month 
nuke_stats_year
nuke_counter

Рефералы
(Referers)

admin/case/case.referers.php
admin/links/links.httpreferers.php
admin/modules/referers.php
nuke_referer
Наши опросы 
(Surveys)

modules/Surveys/

admin/links/links.surveys.php

nuke_poll_check
nuke_poll_data 
nuke_poll_desc 
nuke_pollcomments
Каталог файлов 
(Downloads)

modules/Downloads/

admin/case/case.download.php
admin/links/links.download.php
admin/modules/download.php

nuke_downloads_categories
nuke_downloads_downloads 
nuke_downloads_editorials 
nuke_downloads_modrequest 
nuke_downloads_newdownload 
nuke_downloads_votedata
Контент сайта 
(Content)

modules/Content/

admin/case/case.content.php
admin/links/links.content.php
admin/modules/content.php

nuke_pages 
nuke_pages_categories

Баннеры
(Banners)

www/banners.php

admin/case/case.banners.php
admin/links/links.banners.php
admin/modules/banners.php

nuke_banner
nuke_bannerclient 
Рассылка 
(Newsletter)
admin/case/case.newsletter.php
admin/links/links.newsletter.php
admin/modules/newsletter.php
отсутствет
Вопросы и ответы 
(Faq)

modules/Faq/

admin/links/links.faq.php

nuke_faqanswer
nuke_faqcategories
Форум 
(Forums)

modules/Forums/

admin/case/case.forums.php
admin/links/links.forums.php
admin/modules/forums.php

nuke_bbaut_access
nuke_bbbanlist 
nuke_bbcategories
nuke_bbconfig 
nuke_bbdisallow 
nuke_bbforum_prune 
nuke_bbforums 
nuke_bbgroups 
nuke_bbposts 
nuke_bbposts_text 
nuke_bbprivmsgs 
nuke_bbprivmsgs_text 
nuke_bbranks 
nuke_bbsearch_results
nuke_bbsearch_wordlist 
nuke_bbsearch_wordmatch 
nuke_bbsessions 
nuke_bbsmilies 
nuke_bbthemes 
nuke_bbthemes_name 
nuke_bbtopics 
nuke_bbtopics_watch 
nuke_bbuser_group 
nuke_bbvote_desc 
nuke_bbvote_results 
nuke_bbvote_voters
nuke_bbwords 
nuke_confirm 

Личные сообщения
(Private Messages)
modules/Private_Messages/ В таблицах форума
Каталог ссылок
(Web_Links)

modules/Web_Links/

admin/case/case.links.php
admin/links/links.weblinks.php
admin/modules/links.php

nuke_links_categories 
nuke_links_editorials 
nuke_links_links 
nuke_links_modrequest 
nuke_links_newlink 
nuke_links_votedata

Ниже вы найдете список таблиц и их функции:

nuke_authors – Содержит информацию об администраторах сайта

nuke_banned_ip - Содержит информацию о забаненных IP-адресах

nuke_blocks - Содержит информацию о блоках (Название, расположение, статус и т.д.)

nuke_config - Содержит основную информацию о сайте

nuke_headlines - Содержит информацию о RSS/RDF файлах. Она используется в блоках.

nuke_modules - Содержит информацию о модулях (Название, статус и т.д.)

nuke_optimize_gain – Содержит информацию о запусках модуля Optimize DB

nuke_pages – Здесь хранятся страницы модуля Content

nuke_pages_categories - Содержит информацию о категориях модуля Content

nuke_autonews – Содержит информацию о функции автоновости модуля News (Функция позволяет выводить новости в заданное время)

nuke_comments – В этой таблице содержатся все комментарии к новостям (Модуль News)

nuke_main - Содержит информацию о модуле на главной странице

nuke_queue – Содержит непроверенные новости, добавленные пользователями (Submit_News)

nuke_related - Используется в новостях для связанных статей

nuke_session - Сессии посетителей

nuke_subions – Содержит информацию о подписчиках на рассылку

nuke_stories – Содержит новости (модуль News)

nuke_stories_cat – Содержит информацию о разделах модуля News

nuke_message – Содержит сообщения, выводимые на главной странице

nuke_public_messages – Содержит личные сообщения

nuke_quotes – Миха написал, что это - Форум ссылки, но я хотел бы узнать поточнее…

Скажу вам сразу, что если вы хотите оптимизировать ньюку, то вам придется распрощаться с модулями рефералов и статистики сайта. Модуль опросов прийдется заменить на более легкий, т.к. стандартный модуль выдает примерно на 20 запросов больше, а у нас в конечно результате должно получиться всего 20 запросов к БД. Поняли суть? Приступим от теории к делу... Первым делом мы удаляем эти два модуля: Рефералы и Статистику. Модуль опросов заменяем на модуль Voting, который вы всегда найдете в нашем каталоге файлов. Когда все сделали, выбираем из таблицы (та что выше) ненужные нам модули и удаляем их. Здесь у вас может появиться проблема - В новых версиях PHP-Nuke многих файлов в папках admin/case/, admin/links/ и admin/modules/ может не оказаться. Ну, нет так нет. Удаляем просто все что есть. Также в новых версия и не нашел несколько модулей. Этого тоже можете не бояться. После всех этих манипуляций необходимо почистить ядро. Для начала мы удалим строчку include("includes/counter.php"); из файла header.php, который находится в корне сайта. Теперь открываем файл index.php, который также находится в корне сайта и удаляем следующий код:

if ($httpref==1) {
$referer = $_SERVER["HTTP_REFERER"];
$referer = check_html($referer, nohtml);
if ($referer=="" OR eregi("^unknown", $referer) OR substr("$referer",0,strlen($nukeurl))==$nukeurl OR eregi("^bookmark",$referer)) {
} else {
$sql = "INSERT INTO ".$prefix."_referer VALUES (NULL, '$referer')";
$result = $db->sql_query($sql);
}
$sql = "SELECT * FROM ".$prefix."_referer";
$result = $db->sql_query($sql);
$numrows = $db->sql_numrows($result);
if($numrows>=$httprefmax) {
$sql = "DELETE FROM ".$prefix."_referer";
$result = $db->sql_query($sql);
}
}

Если вы используете одну тему оформления, то неплохо было бы из файла maifile.php, который также находится в корне сайта, заменить код:

function get_theme() {
global $user, $cookie, $Default_Theme;
if(is_user($user)) {
$user2 = base64_decode($user);
$t_cookie = explode(":", $user2);
if($t_cookie[9]=="") $t_cookie[9]=$Default_Theme;
if(isset($theme)) $t_cookie[9]=$theme;
if(!$tfile=@opendir("themes/$t_cookie[9]")) {
$ThemeSel = $Default_Theme;
} else {
$ThemeSel = $t_cookie[9];
}
} else {
$ThemeSel = $Default_Theme;
}
return($ThemeSel);

на следующий код:

function get_theme() {
global $Default_Theme;
$ThemeSel = $Default_Theme;
return($ThemeSel);
}

Теперь приступим к оптимизации ядра. Предупреждаю, что теперь мы будем работать только с файлом mainfile.php, который еще раз повторяю находится в корне сайта, дабы не возникало таких вопросов, как "А какой файл то открывать?". Приступим...

Находим строчку $start_time = $mtime; и после нее добавляем следующий код:

unset($edogs_isadmin);
unset($edogs_isuser);
unset($edogs_usrinfo);
unset($edogs_get_author);
unset($edogs_gettopics);
unset($edogs_blocks);
unset($edogs_is_insidemod);
unset($edogs_admins);
global $edogs_admins;
global $edogs_is_insidemod;
global $edogs_blocks;
global $edogs_gettopics;
global $edogs_get_author;
global $edogs_isadmin;
global $edogs_isuser;
global $edogs_usrinfo;

Находим function is_user($user). Удаляем полностью эту функцию (удалить полность - значит удалить все до следующего слова function). На это место вставляем следующий код:

function is_user($user) {
if(!isset($user)) return 0;
global $edogs_isuser;
global $edogs_usrinfo;
$t=$user;
if(!is_array($user)) $user=explode(":",base64_decode($user));
if(isset($edogs_isuser[$user[0]])) return $edogs_isuser[$user[0]];
global $db, $user_prefix;
$sql="select * from ".$user_prefix."_users where user_id='$user[0]' and user_password='$user[2]'";
$res=$db->sql_query($sql);
if($db->sql_numrows($res)==1) {
$edogs_usrinfo[$user[0]]=$db->sql_fetchrow($res);
$edogs_isuser[$user[0]]=1;
} else {
$edogs_isuser[$user[0]]=0;
}
$db->sql_freeresult($res);
return $edogs_isuser[$user[0]];
}

Находим функцию function is_admin($admin) { и заменяем (ВСЮ функцию!) на следующий код:

function is_admin($admin) {
if(!isset($admin)) return 0;
global $db, $prefix;
global $edogs_isadmin;
if(!is_array($admin)) $admin=explode(":",base64_decode($admin));

if(isset($edogs_isadmin[$admin[0]]))
{
$returnv=$edogs_isadmin[$admin[0]];
} else {
$sql="select count(*) from ".$prefix."_authors where aid='$admin[0]' and pwd='$admin[1]'";
$res=$db->sql_query($sql);
list($edogs_isadmin[$admin[0]])=$db->sql_fetchrow($res);
$db->sql_freeresult($res);
$returnv=$edogs_isadmin[$admin[0]];
}

global $edogs_is_insidemod, $edogs_admins;
if($edogs_is_insidemod=='') return $returnv;
if(!isset($edogs_admins[$admin[0]])) {
$sql="select crights from ".$prefix."_edogsadmins where aid='$admin[0]'";
$res0=$db->sql_query($sql);
list($temp0)=$db->sql_fetchrow($res0);
if(isset($temp0))
$edogs_admins[$admin[0]]=unserialize(base64_decode($temp0));
$sql="select radminsuper from ".$prefix."_authors where aid='$admin[0]'";
list($edogs_admins[$admin[0]]['supermegaadmin'])=$db->sql_fetchrow($db->sql_query($sql));
}
if($edogs_admins[$admin[0]]['supermegaadmin']==1) return 1;
return intval($edogs_admins[$admin[0]][$edogs_is_insidemod]);
}

Находим function cookiedecode($user). Также заменяем на следующий код:

function cookiedecode($user) {
global $edogs_isuser;
global $edogs_usrinfo;
global $cookie;
if(is_user($user)) {
$cookie=explode(":",base64_decode($user));
return $cookie;
} else {
$cookie=array();
unset($cookie);
}
}

Находим function getusrinfo($user). Заменяем на следующий код:

function getusrinfo($user) {
global $edogs_usrinfo;
global $userinfo;
$user=explode(":",base64_decode($user));
if(!is_user($user)) { unset($userinfo); return; };
$userinfo=$edogs_usrinfo[$user[0]];
return $userinfo;
}

Находим function formatAidHeader($aid). Заменяем на следующий код:

function formatAidHeader($aid) {
echo get_author($aid);
return;
}

Находим function getTopics($s_sid). Заменяем на следующий код:

function getTopics($s_sid) {
$s_sid=intval($s_sid);
global $edogs_gettopics;
global $topicname, $topicimage, $topictext, $topicid, $prefix, $db;
if(!isset($edogs_gettopics[$s_sid])) {
$sql="select topicid, topicname, topicimage, topictext from ".$prefix."_topics as a ";
$sql.=" left join ".$prefix."_stories as b ";
$sql.=" on (topicid=topic) ";
$sql.=" where b.sid='$s_sid'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);

$edogs_gettopics[$s_sid]['topicid'] = $row[topicid];
$edogs_gettopics[$s_sid]['topicname'] = $row[topicname];
$edogs_gettopics[$s_sid]['topicimage']= $row[topicimage];
$edogs_gettopics[$s_sid]['topictext']= $row[topictext];
}
$topicid=    $edogs_gettopics[$s_sid]['topicid'];
$topicname=  $edogs_gettopics[$s_sid]['topicname'];
$topicimage= $edogs_gettopics[$s_sid]['topicimage'];
$topictext=  $edogs_gettopics[$s_sid]['topictext'];
$topictext=stripslashes(check_html($topictext, "nohtml"));
}

Находим function blocks($side). Заменяем на следующий код:

function blocks($side) {
global $storynum, $prefix, $multilingual, $currentlang, $db, $admin, $user;
if ($multilingual == 1) {
$querylang = "AND (blanguage='$currentlang' OR blanguage='')";
} else {
$querylang = "";
}
if (strtolower($side[0]) == "l") {
$pos = "l";
} elseif (strtolower($side[0]) == "r") {
$pos = "r";
}  elseif (strtolower($side[0]) == "c") {
$pos = "c";
} elseif  (strtolower($side[0]) == "d") {
$pos = "d";
}
$side = $pos;
global $edogs_blocks;
if(empty($edogs_blocks)) {
$sql = "SELECT bid, bkey, title, content, url, blockfile, view, expire, action, subion, bposition FROM ".$prefix."_blocks WHERE active='1' $querylang ORDER BY weight ASC";
$result = $db->sql_query($sql);
while($row_z = $db->sql_fetchrow($result)) {
$edogs_blocks[]=$row_z;
}
}
foreach($edogs_blocks as $k=>$row) {
if($row['bposition']!=$pos) continue;
$bid = intval($row['bid']);
$title = stripslashes(check_html($row['title'], "nohtml"));
$content = stripslashes($row['content']);
$url = stripslashes($row['url']);
$blockfile = $row['blockfile'];
$view = intval($row['view']);
$expire = intval($row['expire']);
$action = $row['action'];
$action = substr("$action", 0,1);
$now = time();
$sub = intval($row['subion']);
if ($sub == 0 OR ($sub == 1 AND !paid())) {
if ($expire != 0 AND $expire <= $now) {
if ($action == "d") {
$db->sql_query("UPDATE ".$prefix."_blocks SET active='0', expire='0' WHERE bid='$bid'");
return;
} elseif ($action == "r") {
$db->sql_query("DELETE FROM ".$prefix."_blocks WHERE bid='$bid'");
return;
}
}
if ($row[bkey] == admin) {
adminblock();
} elseif ($row[bkey] == userbox) {
userblock();
} elseif ($row[bkey] == "") {
if ($view == 0) {
render_blocks($side, $blockfile, $title, $content, $bid, $url);
} elseif ($view == 1 AND is_user($user) || is_admin($admin)) {
render_blocks($side, $blockfile, $title, $content, $bid, $url);
} elseif ($view == 2 AND is_admin($admin)) {
render_blocks($side, $blockfile, $title, $content, $bid, $url);
} elseif ($view == 3 AND !is_user($user) || is_admin($admin)) {
render_blocks($side, $blockfile, $title, $content, $bid, $url);
}
}
}
}
}

Теперь лучше сделать копию нашего уже измененного файла, т.к. данный прием у меня не работает. Сделали? Идем дальше...

Находим function get_author($aid). Заменяем на следующий код:

function get_author($aid) {
global $edogs_get_author;
if(isset($edogs_get_author[$aid])) return $edogs_get_author[$aid];
$t=$aid;
global $prefix, $db;
$sql = "SELECT url, email FROM ".$prefix."_authors WHERE aid='$aid'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$aid=($row['url']!='' ? '
'.$aid.'' : ($row['email']!='' ? ''.$aid.''">mailto:'.$row['email'].'">'.$aid.'' : $aid) );
$db->sql_freeresult($res);
$edogs_get_author[$t]=$aid;
return $aid;
}

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

Если вам интересно, сколько у вас запросов к БД, читайте статью "Ставим счетчик запросов на PHP-Nuke".

Ну, вот мы и оптимизировали нашу любимую ньюку. Я думаю, что теперь переходить на xNuke вообще нет ни какого смысла. Для тех, кто не знает, xNuke - это очень шустрая система с переписанной логикой ядра. Она делает 20 запросов к БД в то время, как неоптимизированная PHP-Nuke с точно таким же содержимым делает от 80 до 200 запросов. Теперь у нас на главной странице будет около 20 запросов с двумя-тремя новостями и парой блоков. Не забывайте, что каждый блок - нагрузка на БД. Каждая новость также добавляет 2 запроса в БД. Поэтому не захламляйте свой сайт, да будет грузится ваш сайт за 0.0000000001 секунду!

При написании статьи использовались многие источники информации.