Forums / National / Russian / Модули и плагины / Дополнительные настройки в админке. Как это делать?

<<<1234>>>

Sergeich
#31 2010-01-29 18:28
Форум - это модуль. В будущих версиях планируется модульность довести до ума, поэтому сейчас нет смысла делать такие глубокие изменения.
Gunslinger
#32 2010-01-29 21:05
Кстати в чем принципиальная разница между плагином и модулем?
Sergeich
#33 2010-01-29 21:19
если грубо, то модуль - большой плагин.
Gunslinger
#34 2010-01-29 22:38
ГХм...
Народ, не обижайтесь, но ваши ответы иногда просто убивают :)


Еще раз: в чем разница между плагинами и модулями? Всего лиш в объеме кода???

А если разницы нет, то на кой икс здались модули? Или плагины...
Sergey
#35 2010-01-29 23:29
# Gunslinger : ГХм...
Народ, не обижайтесь, но ваши ответы иногда просто убивают :)
Ваш вопрос меня поверг своей наивностью и вот почему: в вашем вопросе содержится ответ на то, что вам еще пока не "по зубам" работать с PHP. Вообще-то модуль, это (в общем случае) самостоятельная, заранее определенная часть, которая загружается по правилам обращений с ссылками в интернет. Если взять форум, то вот это обращение http_://www.cotonti.com/forums.php т.е. вызывается модуль forums.php из корневой части сайта www.cotonti.com. После знака ? идут ключи, по которым модуль определяет что делать дальше.
Плагин, это пользовательская заплатка, которая подключается в модуле соответствующим образом, в соответствующим порядком и подключается к тому юзеру, которому предоставлено разрешение на то, чтобы воспользоваться этой заплаткой. Весь эффект основан на этой стандартной части модуля по подключению плагина:
/* === Hook === */
$extp = sed_getextplugins('page.download.first');
if (is_array($extp))
{ foreach($extp as $k => $pl) { include_once($cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php'); } }

В массиве $extp содержатся указания на плагины, перебирая эти указания подключаются соответствующие плагины. Каждый модуль, условно, разбит на законченные логические части - это скелет.
У такой части имеется наименование Hook (для примера это page.download.first - загрузи в странице первым) следовательно будут загружаться плагины помеченные как page.download.first . Однако, плагинов к одной части может быть подключено много, для этого массив $extp, предварительно, сортируется по порядку Order и имени для одинаковых порядков. Исполняются вначале самые меньшие значения. Далее, ответ на мое утверждение "вам еще пока не "по зубам" работать с PHP" следует вызов этого плагина. Фактически оператор include_once (единожды) загружает файл с кодом PHP. Имя и где его искать берутся как раз берутся из условий в массиве $extp и установок всего ресурса в целом ($cfg['plugins_dir']). Условия загрузки формируются при установке плагина, обработкой специальной части плагина Setup.
Надо знать, что PHP это интерпретатор, который наперед не знает, что будет дальше. PHP просто берет это файл плагина включает в текст модуля и интерпретирует. Если, в плагине будет свой механизм Hook, то это будет продолжено дальше, пока не будут исчерпаны все подключаемые плагины для данной части.
Пройдя последний оператор плагина, интерпретатор возвратиться к исходному модулю и продолжит обработку его операторов, до следующего Hook
www.cotonti.mobi
Sergeich
#36 2010-01-30 00:26
Вот чёрт, спасибо за ликбез. Теперь и я стал понимать чем модуль от плагина отличается :).
Gunslinger
#37 2010-01-30 00:30
Sergey
Ваш вопрос меня поверг своей наивностью и вот почему: в вашем вопросе содержится ответ на то, что вам еще пока не "по зубам" работать с PHP.

Пока работабю и мир от этого не рухнул. И что общего имеет концепция построения движка по которой вообще и в принципе нет человеческой документации (в следствие чего и возникают подобные вопросы) с языком программирования я не совсем понимаю. И еще одно. С точки зрения програмного кода плагин по вашему не является тем же подключаемым модулем?

Сударь, я конечно польщен тем, что вы снизошли до пояснений полному профану. Премного благодарен. Я так понимаю вы совершенно не в курсе, что люди задают вопросы для того чтобы чему-то научиться?

В краткой форме: по нормальному без демонстративного выпендрежа ответить можно?

П.С.

Sergey, Вот видите? У нас даже старожилы не понимают разници а вы в мой адрес приговоры выдаете.
Trustmaster
#38 2010-01-30 00:46
Ликбез по хукам получился весьма неплохой, хоть и несколько сложноват.

Модули и плагины рождают много путаницы, потому как в общем случае слова очень близкие по значению. Так что скорее всего модули придётся именовать как-то по-другому, например зонами (zones) или областями (areas). Но пока по привычке - модули - в Seditio/Cotonti это скрипты верхнего (корневого) уровня, реализующий некий фундаментальный функционал. Примеры: форумы, страницы, личные сообщения. Как правило, один модуль содержит несколько включаемых файлов (includes). Однако ни один модуль не может заведомо реализовать все возможные пожелания тех или иных пользователей, хотя бы потому, что все сайты разные и требуют разный функционал. Поэтому для каждой логически целостной части модуля имеются точки расширения - хуки. Вот к ним-то и подключаются плагины.

Есть ещё один момент: standalone части плагинов, которые отличаются от модулей только тем, что на корневом уровне используют модуль plug.php и отличаются от модулей меньшим объёмом кода (хотя бывают и плагины с исходниками по 300kB текста), а также тем, что кроме standalone в них всё-таки есть и части, использующие хуки других модулей. Модули же не зависят друг от друга.

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

С документацией беда, да. Стараемся хотя бы на англ. документировать основные моменты. Но возможности ограничены.
May the Source be with you!
Sergey
#39 2010-01-30 01:09
# Gunslinger : Sergey
С точки зрения програмного кода плагин по вашему не является тем же подключаемым модулем?
Вы не поняли, модуль подключается, точнее включается средствами браузера, а плагин средствами PHP.
Однако, PHP имеет внутренний механизм организации нового потока, подменяющего ответ от браузера. Как бы вписывает строку урла в браузере и тут же сам ее принимает. Вот рассмотрим этот необычно-стандартный участок, не только обработки ошибок.
if ($pag['page_state'] == 1 && !$usr['isadmin'] && $usr['id'] != $pag['page_ownerid'])
{
	sed_log("Attempt to directly access an un-validated page", 'sec');
	header("Location: " . SED_ABSOLUTE_URL . sed_url('message', "msg=930", '', true));
	exit;
}

if (mb_substr($pag['page_text'], 0, 6)=='redir:')
	{
	$redir = str_replace('redir:', '', trim($pag['page_text']));
	$sql = sed_sql_query("UPDATE $db_pages SET page_filecount=page_filecount+1 WHERE page_id='".$pag['page_id']."'");
	header("Location: " . SED_ABSOLUTE_URL . $redir);
	exit;
	}

elseif (mb_substr($pag['page_text'], 0, 8)=='include:')
	{
	$pag['page_text'] = sed_readraw('datas/html/'.trim(mb_substr($pag['page_text'], 8, 255)));
	}
В группе операторов
if ($pag['page_state'] == 1 && !$usr['isadmin'] && $usr['id'] != $pag['page_ownerid'])
{
	sed_log("Attempt to directly access an un-validated page", 'sec');
	header("Location: " . SED_ABSOLUTE_URL . sed_url('message', "msg=930", '', true));
	exit;
}
модуль определяет, что если входная страница имеет статус не утвержденной страницы, и что эта страница не юзера и что зашел не админ (модератор), то такую страницу читать нельзя (не положено).
Выводится сообщение Attempt to directly access an un-validated page
и производится перенаправление к загрузке модуля в SED_ABSOLUTE_URL для этого сайта это http_://www.cotonti.com т.е. в самое начало. НО, текущий процесс работы модуля идет! Оператор exit; прекращает его жизнь.
Теперь посмотрим на другой участок
if (mb_substr($pag['page_text'], 0, 6)=='redir:')
	{
	$redir = str_replace('redir:', '', trim($pag['page_text']));
	$sql = sed_sql_query("UPDATE $db_pages SET page_filecount=page_filecount+1 WHERE page_id='".$pag['page_id']."'");
	header("Location: " . SED_ABSOLUTE_URL . $redir);
	exit;
	}
Он похож, но не совсем. Смотрим первых 6 знаков в тексте. Если эти знаки команды (наше правило движка) равны слову redir: то мы отсекаем из текста эти знаки а получившуюся часть складываем с SED_ABSOLUTE_URL что мы имеем, мы имеем переход на тот модуль в движке который нам нужен. Браузер через PHP выполняет команду-оператор header. Текущий процесс обработки мы опять прекращаем exit; Этот метод имеет существенный недостаток - происходит перезагрузка всей системы движка, а не подгрузка части программного кода, например из другого модуля (т.е. не как плагина к готовому целому). Происходит замена всего модуля на другой.
Не надо обижаться - это обычный, не быстрый этап освоения профессии программиста. Инструкции по программированию готовят для тех, кто прежде всего, уже это делал не раз. И, следовательно, пережевка, мешает заострить внимание.

Gunslinger! Тут, в моем примере, есть и третий участок. (модуль page.inc.php) попробуйте разобраться, для начала, и вы откроете совсем необычную возможность движка это ...
www.cotonti.mobi
This post was edited by Sergey (2010-01-30 01:24, 14 years ago)
SunChase
#40 2010-01-30 02:52
может слегка не в тему,но может ктото ткнуть на инфу по условиям типа PHP.tab и всё такое?
[url=http://ka13.orgfree.com]KA13[/url] - The essence of creativity
Trustmaster
#41 2010-01-30 03:05
# SunChase : может слегка не в тему,но может ктото ткнуть на инфу по условиям типа PHP.tab и всё такое?
http://www.cotonti.com/docs/en/skins/xtemplate_introduction
May the Source be with you!
Gunslinger
#42 2010-01-30 03:15
Sergey, Trustmaster, большое спасибо за потраченное вами на ликбез время. Sergey, вам отдельная благодарность за детали. Вот теперь картина с плагинами и модулями обрела ясность.

Полагаю, будет не лишним предложить вынести содержимое ваших постов в виде отдельной статьи в раздел русскоязычной документации. На мой взгляд изложенная вами информация будет многим полезна. Ведь согласитесь, что если бороться за грамотное написание плагинов к движку то начинать стоит с четкого понимания основополагающих моментов структуры самого движка Котонти.

И еще одно. Если вам не сложно, то обратите внимание еще на эту тему : Система Hooks. Принцип работы.. Как мне кажется она так же недостаточно прозрачна в плане понимания обычным пользователям. Буду категорически признателен за ваши комментарии и пояснения.
Sergey
#43 2010-01-30 03:54
Так уж принято кем-то и везде, что выражение в шаблоне (template) стоящие в фигурных скобках это тег. Тег (Tag), это то, что должен заменить парсер (часть шаблонизатора). Такое разделение шаблона и программных модулей сделано специально, чтобы программист выполнял свою часть, а скинмейкер свою: творил скины ( кожу - skin). Тег имеет имя, вместо которого парсер подставляет значение. В cotonti принято, что, что-то написанное большими буквами стоящим в фигурных скобках, а затем в шаблоне, то это тег, который формируется парсером, например, так:

$t->parse("MAIN.LIST_ROW");

где MAIN это префикс всех тегов в главной части шаблона, отвечающие выражению LIST_ROW и дальше, т.е
	"LIST_ROW_URL" => $pag['page_pageurl'],
	"LIST_ROW_ID" => $pag['page_id'],
	"LIST_ROW_CAT" => $pag['page_cat'],
	"LIST_ROW_KEY" => htmlspecialchars($pag['page_key']),
	"LIST_ROW_TITLE" => htmlspecialchars($pag['page_title']),
	"LIST_ROW_DESC" => $pag['page_desc'],
	"LIST_ROW_DESC_OR_TEXT" => sed_cutpost($pag['page_text'], 200, false),
	"LIST_ROW_AUTHOR" => htmlspecialchars($pag['page_author']),
	"LIST_ROW_OWNER" => sed_build_user($pag['page_ownerid'], htmlspecialchars($pag['user_name'])),
	"LIST_ROW_DATE" => @date($cfg['formatyearmonthday'], $pag['page_date'] + $usr['timezone'] * 3600),
	"LIST_ROW_FILEURL" => empty($pag['page_url']) ? '' : sed_url('page', 'id='.$pag['page_id'].'&a=dl'),
	"LIST_ROW_SIZE" => $pag['page_size'],
	"LIST_ROW_COUNT" => $pag['page_count'],
	"LIST_ROW_FILEICON" => $pag['page_fileicon'],
	"LIST_ROW_FILECOUNT" => $pag['page_filecount'],
	"LIST_ROW_JUMP" => sed_url('page', $page_urlp.'&a=dl'),
	"LIST_ROW_COMMENTS" => $pag['page_comments'],
	"LIST_ROW_RATINGS" => $list_ratings,
	"LIST_ROW_ADMIN" => $pag['admin'],
	"LIST_ROW_ODDEVEN" => sed_build_oddeven($jj),
    "LIST_ROW_NUM" => $jj
Однако, имеются переменные, которые вставляются как теги. Для этих тегов имеется правило:
PHP.имя_переменной.ассоциативный_код
вот пример из шаблона list.tpl
<tr>
	<td class="coltop">{LIST_TOP_TITLE} {LIST_TOP_COUNT}</td>
	<td class="coltop" style="width:96px;">{PHP.L.Comments}</td>
	<td class="coltop" style="width:96px;">{PHP.L.Ratings}</td>
	<td class="coltop" style="width:96px;">{LIST_TOP_DATE}</td>
	<td class="coltop" style="width:128px;">{LIST_TOP_AUTHOR}</td>
</tr>
теги LIST_TOP_DATE и LIST_TOP_AUTHOR, а PHP.L.Comments и PHP.L.Ratings это переменные PHP: $L['Comments'] и $L['Ratings'].
Все теги которые не были "запарсены" префиксно, парсятся в конце модуля оператором

$t->parse("MAIN");

а выводится во внешний поток (на экран юзера) оператором

$t->out("MAIN");

Надо помнить, что сколько раз вы включили $t->parse() столько раз, эта часть шаблона парсится. Так получаются таблицы. Вот этот участок в list.inc.php
	$t-> assign(array(
		"LIST_ROWCAT_URL" => sed_url('list', 'c='.$i),
		"LIST_ROWCAT_TITLE" => $x['title'],
		"LIST_ROWCAT_DESC" => $x['desc'],
		"LIST_ROWCAT_ICON" => $x['icon'],
		"LIST_ROWCAT_COUNT" => $sub_count,
		"LIST_ROWCAT_ODDEVEN" => sed_build_oddeven($kk),
        "LIST_ROWCAT_NUM" => $kk,
		));

		/* === Hook - Part2 : Include === */
		if (is_array($extp))
		{ foreach($extp as $k => $pl) { include($cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php'); } }
		/* ===== */


		$t->parse("MAIN.LIST_ROWCAT");
Имеется еще одно замечательное определение, точнее переопределение. До парсинга, у тега можно изменить значение двумя способами, вот пример, обращение как элементу класса через функцию $t-> assign() и как к элементу массива через имя тега:

$t->vars["ИМЯ_ТЕГА"]
if	(isset($mesg_elink) and !empty ($mesg_elink))   // сообщение на странице отображения элемента
	{
	if	(isset($t->vars["PAGE_MSG"]))
		{
		$t->vars["PAGE_MSG"] .= "<br />".$mesg_elink;
		}
		else
			{
			$t->assign(array("PAGE_MSG" => $mesg_elink));
			}
	}
В этот примере определяется, был ли каким-то плагином, сформирован тег PAGE_MSG Если он не сформирован, то тег генерируется, а если тег есть, то он дополняется новым сообщением. Не заменяется, как в первом случае, а дополняется или модифицируется.
Впрочем ссылка на шаблонизатор уже приведена.
www.cotonti.mobi
Dayver
#44 2010-01-30 04:03
# Gunslinger : И еще одно. Если вам не сложно, то обратите внимание еще на эту тему : Система Hooks. Принцип работы..Как мне кажется она так же недостаточно прозрачна в плане понимания обычным пользователям.
Не внимательность - зло. Отсюда и непрозрачность. Чесн слово прозрачнее некуда. Я бы понял вашу позицию если бы вы впервые увидели движок но судя по форуму neocrome.ru в это поверить не реально. Вот все ругают котонти за отсутствие документации .... и ругают многие которые перешли с седа .. возникает вопрос как же все жилы раньше при седе? Ох почему то я не видел такого недовольства на неокроме. Многие новшества внедренные в котонти мало мальски документированы ... мало документации по тому функционалу который не изменился со времен седитио (Радует что в версиях 0.7.0 и 1.0.0 такого останется крайне мало).
Pavlo Tkachenko aka Dayver
Sergey
#45 2010-01-30 04:39
# Gunslinger :
И еще одно. Если вам не сложно, то обратите внимание еще на эту тему Система Hooks.
Начнем издалека. Вот текст этой функции, которая загружает плагин
function sed_getextplugins($hook, $cond='R')
{
	global $sed_plugins, $usr;

	if (is_array($sed_plugins))
	{
		foreach($sed_plugins as $i => $k)
		{
			if($k['pl_hook']==$hook && sed_auth('plug', $k['pl_code'], $cond))
			{
				$extplugins[$i] = $k;
			}
		}
	}
	return $extplugins;
}

а теперь посмотрим типичный пример описания установки плагина

Auth_guests=R
Lock_guests=W12345A
Auth_members=R
Lock_members=W12345A

типичный вызов:

/* === Hook === */
$extp = sed_getextplugins('list.main');

Ведите, в вызове функции sed_getextplugins один параметр, а в описании их два. Что обозначает это вызов? Этот, типовой вызов обозначает,
что это

Auth_guests=R
Lock_guests=W12345A
Auth_members=R
Lock_members=W12345A

системе пофиг, это выполняется одним образом $cond='R' т.е. всегда, если вы установили Auth в R .
Имеется еще один момент. У функции sed_getextplugins($hook, $cond='R') проводится выборка по имени хука $hook всех активных (не отключенных) одноименных с хуком элементов плагинов. Выборка производится из массива $sed_plugins Выборка производится один раз по ключу $cond. Следовательно, если у вас появилась мысль использовать плагин для группы "доверенных товарищей" вам придется позаботится об этом самим, т.е. написать особый плагин загрузки ваших плагинов для "доверенных товарищей".

вот вызов для получения правильного доступа по правам из page.inc.php к категории (списку)

list($usr['auth_read'], $usr['auth_write'], $usr['isadmin'], $usr['auth_download']) = sed_auth('page', $pag['page_cat'], 'RWA1');

аналогично, должно быть и к плагину для группы товарищей.

Следующий момент, это не понимание работы оператора (тут отвлеченный пример):

if (is_array($extp))
{ foreach($extp as $k => $pl) { include_once($cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php'); } }

Оператор foreach коварен. Он вначале у себя внутри выбирает все элементы из $extp а потом их перебирает, поэтому !! вы не сможете уже переопределить массив $extp дальше. Конечно, надо несколько другой механизм применять, но необходимость этого встречается только в отдельных случаях, когда вы решили динамически подвинуть или исключить плагин. Не выйдет.

Другое коварство заключается в именах переменных. Такие простенькие имена типа $i или $k могут использоваться и другими разработчиками других плагинов, особенно, состоящих из нескольких частей. Можно ненароком потереть или переопределить чужую переменную. В этом случае лучше перейти к своему классу или на худой конец оформить свой плагин функцией.
www.cotonti.mobi
This post was edited by Sergey (2010-01-30 05:09, 14 years ago)

<<<1234>>>