Блок пользователя
Регистрация на нашем сайте позволит вам общаться на форумах и получить доступ к другому полезному функционалу
Вы вошли как Гость

С чего начать создание темы Cotonti

  • 340 просмотров
  • 20 января, 2023
  • Обновлено: 16 октября, 2023
  • admin
  • Время чтения: 11 минут

После того, как вы развернули на удаленном или локальном сервере дистрибутив Cotonti, необходимо создать новую тему оформления. В эпоху Seditio ее называли скин (skin).

Как правило, тема для Котонти создается "с нуля". Для этого необходимо использовать коробочную тему Nemesis и произвести над ней некоторые действия, чтобы уникализировать ее и добавить немного необходимого функционала. Если в дальнейшем планируется разработка новых тем, рекомендую сохранить созданный каркас, например, на Github для того, чтобы дальнейшие процедуры клонирования занимали меньше времени и усилий.

Копирование и переименование

Откроем папку /themes. Здесь находятся две темы: Nemesis и Sumisun. Последнюю сразу удаляем -- это модельная тема давно не обновлялась и уже потеряла свою актуальность. Работать мы будем с темой Nemesis.

Прежде всего, придумаем название новой темы и соответствующим образом переименуем папку. Например, nemesis -> kudos. Аналогичным образом поступим с четырьмя "именными" файлами в папке:

  • nemesis.php -> kudos.php
  • nemesis.en.lang.php -> kudos.en.lang.php
  • nemesis.rc.php -> kudos.rc.php
  • nemesis.ru.lang.php -> kudos.ru.lang.php

Откроем файл kudos.php и отредактируем "шапку":

/* ====================
[BEGIN_COT_THEME]
Name=Kudos
Version=1.00b
Schemes=default:Default
[END_COT_THEME]
==================== */

Аналогичным образом поступим с файлами локализаций:

/**
 * User English Language File for Kudos theme
 *
 * @package Cotonti
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

и

/**
 * User Russian Language File for Kudos theme
 *
 * @package Cotonti
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

Также исправим header файла-загрузчика:

/**
 * JavaScript and CSS loader for Kudos theme
 *
 * @package Cotonti
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

Редактирование основных файлов

Очистим основные файлы для дальнейшей работы с ними. В первую очередь нас интересуют файлы TPL-шаблонов.

Правка файлов-шаблонов

Откроем header.tpl и удалим верстку ниже открывающего тега body. Тег HEADER_META_KEYWORDS нам тоже уже не понадобится. В итоге получим:

<!-- BEGIN: HEADER -->
<!DOCTYPE html>
<html lang="{PHP.cfg.defaultlang}">
<head>
<title>{HEADER_TITLE}</title>
<!-- IF {HEADER_META_DESCRIPTION} -->
<meta name="description" content="{HEADER_META_DESCRIPTION}" />
<!-- ENDIF -->
<!-- IF {HEADER_META_KEYWORDS} -->
<meta name="keywords" content="{HEADER_META_KEYWORDS}" />
<!-- ENDIF -->
<meta http-equiv="content-type" content="{HEADER_META_CONTENTTYPE}; charset=UTF-8" />
<meta name="generator" content="Cotonti https://www.cotonti.com" />
<link rel="canonical" href="{HEADER_CANONICAL_URL}" />
{HEADER_BASEHREF}
{HEADER_HEAD}
<link rel="shortcut icon" href="favicon.ico" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
</head>

<body>

  <header class="py-3 bg-secondary-subtle">
    <div class="container">
      <div class="row">
        <div class="col">
          <p class="text-center mb-0">
            This is header <a href="{PHP.cfg.mainurl}">Back Home</a>
          </p>
        </div>
      </div>
    </div>
  </header>

<!-- END: HEADER -->

Так же поступим с шаблоном footer.tpl:

<!-- BEGIN: FOOTER -->

  <footer class="py-3 bg-secondary-subtle">
    <div class="container">
      <div class="row">
        <div class="col">
          <p class="text-center mb-0">
            This is footer
          </p>
        </div>
      </div>
    </div>
  </footer>

{FOOTER_RC}
</body>
</html>
<!-- END: FOOTER -->

Шаблон index.tpl очищаем полностью:

<!-- BEGIN: MAIN -->
  <main id="home" class="my-4">
    <div class="container">
    <div class="row">
      <div class="col">
        <p class="text-center mb-0">
          This is index
        </p>
      </div>
    </div>
    </div>
  </main>
<!-- END: MAIN -->

Пройдемся по остальным шаблонам. Самым трудоемким будет login.tpl. Будем считать, что в качестве CSS-фреймворка используется Bootstrap:

<!-- BEGIN: MAIN -->
<main id="login" class="my-4">
	<div class="container">
		<div class="row">
			<div class="mx-auto col col-lg-7 col-xl-6 col-xxl-5">
{FILE "{PHP.cfg.themes_dir}/{PHP.theme}/warnings.tpl"}
				<div class="title mb-3">
					<ul class="breadcrumb">
						<li class="breadcrumb-item">
							<a href="{PHP.cfg.mainurl}" title="{PHP.L.Home}">{PHP.L.Home}</a>
						</li>
						<li class="breadcrumb-item">{PHP.L.Login}</li>
					</ul>
					<h1 class="display-6 lh-1">{USERS_AUTH_TITLE}</h1>
				</div>
<!-- IF {PHP.usr.id} -->
				<div class="alert alert-info">
					<p class="mb-0">
						{PHP.L.users_loggedinas} <strong>{PHP.usr.name}</strong>. {PHP.L.users_logoutfirst}
					</p>
				</div>
				<div class="btn-group w-100">
<!-- IF {PHP.usr.maingrp} == 5 OR {PHP.usr.maingrp} == 6 -->
					<a class="btn btn-danger btn flex-fill" href="{PHP|cot_url('admin')}">{PHP.L.Adminpanel}</a>
<!-- ENDIF -->
					<a class="btn btn-success btn flex-fill" href="{PHP|cot_url('users', 'm=profile')}">{PHP.L.Profile}</a>
					<a class="btn btn-success btn flex-fill" href="{PHP.sys.xk|cot_url('login','out=1&x=$this', '', 0, 1)}">{PHP.L.Logout}</a>
				</div>
<!-- ELSE -->
				<form name="login" action="{USERS_AUTH_SEND}" method="post">
					<div class="input-group mb-3">
						<span class="input-group-text small w-25">{PHP.L.Name}:</span>
						{USERS_AUTH_USER}
					</div>
					<div class="input-group mb-3">
						<span class="input-group-text small w-25">{PHP.L.Password}:</span>
						{USERS_AUTH_PASSWORD}
						<div class="input-group-text">
							{USERS_AUTH_REMEMBER}
						</div>
					</div>
					<div class="btn-group w-100">
						<button type="submit" name="rlogin" value="0" class="btn btn-success btn flex-fill">{PHP.L.Login}</button>
<!-- IF !{PHP.cfg.users.disablereg} -->
						<a href="{PHP|cot_url('users','m=register')}" class="btn btn-primary btn flex-fill">{PHP.L.Registration}</a>
<!-- ENDIF -->
						<a href="{PHP|cot_url('users','m=passrecover')}" class="btn btn-primary btn flex-fill">{PHP.L.users_lostpass}</a>
					</div>
				</form>
<!-- ENDIF -->

<!-- BEGIN: USERS_AUTH_MAINTENANCE -->
				<div class="alert alert-warning mb-0" role="alert">
					<h4>
						{PHP.L.users_maintenance1}
<!-- IF {PHP.cfg.maintenancereason} -->
						({PHP.cfg.maintenancereason})
<!-- ENDIF -->
					</h4>
					<p class="mb-0">
						{PHP.L.users_maintenance2}
					</p>
				</div>
<!-- END: USERS_AUTH_MAINTENANCE -->

			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

Следующий в очереди error.tpl:

<!-- BEGIN: MAIN -->
<!DOCTYPE html>
<html lang="{PHP.cfg.defaultlang}">
	<head>
		<title>{MESSAGE_TITLE}</title>
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<meta name="generator" content="Cotonti http://www.cotonti.com" />
		{MESSAGE_BASEHREF}
		{MESSAGE_STYLESHEET}
		{MESSAGE_REDIRECT}
	</head>
	<body>
		<main id="error">
			<div class="container">
				<div class="row">
					<div class="col">
						<h1>{MESSAGE_TITLE}</h1>
						<div>
							{MESSAGE_BODY}
						</div>
					</div>
				</div>
			</div>
		</main>
	</body>
</html>
<!-- END: MAIN -->

За ним message.tpl:

<!-- BEGIN: MAIN -->
<!-- IF !{AJAX_MODE} -->
<main id="message" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
				<div class="title p-0">
					<h1 class="lh-1 text-center mb-3">{MESSAGE_TITLE}</h1>
				</div>
<!-- ENDIF -->
				<div class="alert alert-warning mb-0" role="alert">
					<p class="text-center mb-0">
						{MESSAGE_BODY}
					</p>
					<div class="d-flex justify-content-center">
<!-- BEGIN: MESSAGE_CONFIRM -->
						<a id="confirmYes" href="{MESSAGE_CONFIRM_YES}" class="confirmButton btn btn-success btn-sm fw-bold mx-2 text-uppercase w-25">{PHP.L.Yes}</a>
						<a id="confirmNo" href="{MESSAGE_CONFIRM_NO}" class="confirmButton btn btn-danger btn-sm bold fw-bold text-uppercase mx-2 w-25">{PHP.L.No}</a>
<!-- END: MESSAGE_CONFIRM -->
					</div>
				</div>
<!-- IF !{AJAX_MODE} -->
			</div>
		</div>
	</div>
</main>
<!-- ENDIF -->

<!-- END: MAIN -->

За ним plugin.tpl:

<!-- BEGIN: MAIN -->
<div class="container">
	<div class="row">
		<div class="col">
			<h1>{PLUGIN_TITLE}</h1>
			<div>
				{PLUGIN_BODY}
			</div>
		</div>
	</div>
</div>
<!-- END: MAIN -->

Далее poput.tpl:

<!-- BEGIN: MAIN -->
<!DOCTYPE html>
<html lang="{PHP.cfg.defaultlang}">
	<head>
		{POPUP_METAS}
		{POPUP_JAVASCRIPT}
		<base href="{PHP.cfg.mainurl}/" />
		<script type="text/javascript">
			//<![CDATA[
			function add(text) {
				insertText(document, "{POPUP_C2}", text);
			}
			//]]>
		</script>
		<link href="themes/{PHP.theme}/css/{PHP.scheme}.css" type="text/css" rel="stylesheet" />
	</head>
<body>
	{POPUP_BODY}
</body>
</html>
<!-- END: MAIN -->

И в завершение warnings.tpl:

<!-- BEGIN: ERROR -->
<div class="alert alert-danger" role="alert">
	<h4>{PHP.L.Error}</h4>
	<p class="m-0">
<!-- BEGIN: ERROR_ROW -->
		<span>{ERROR_ROW_MSG}</span>
<!-- END: ERROR_ROW -->
	</p>
</div>
<!-- END: ERROR -->

<!-- BEGIN: WARNING -->
<div class="alert alert-warning" role="alert">
	<h4>{PHP.L.Warning}</h4>
	<p class="m-0">
<!-- BEGIN: WARNING_ROW -->
		<span>{WARNING_ROW_MSG}</span>
<!-- END: WARNING_ROW -->
	</p>
</div>
<!-- END: WARNING -->

<!-- BEGIN: DONE -->
<div class="alert alert-success" role="alert">
	<h4>{PHP.L.Done}</h4>
	<p class="m-0">
<!-- BEGIN: DONE_ROW -->
		<span>{DONE_ROW_MSG}</span>
<!-- END: DONE_ROW -->
	</p>
</div>
<!-- END: DONE -->

Папки img и inc очищаем полностью, за исключением блокирующих просмотр файлов index.html.

Правка файлов стилей

Здесь будет немного радикальных перестановок. Настраивать стили будем под использование LESS -- динамического языка стилей, с помощью которого можно более гибко и просто работать со стилями нашего будущего веб-сайта:

  1. переименуем папку css в папку less,
  2. удалим файл reset.css (его функционал уже реализован в библиотеке Bootstrap),
  3. файл default.css очистим и переименуем в default.less,
  4. файл extras.css очистим и переименуем в responsive.css,
  5. файл modalbox.css переименуем в modalbox.less,
  6. создадим пустую папку css, в которой будут размещаться скомпилированные и минифицированные файлы стилей.

Настроим компилятор LESS и отразим наши исправления в файле-загрузчике:

<?php
/**
 * JavaScript and CSS loader for Kudos Theme
 *
 * @package Kudos
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

defined('COT_CODE') or die('Wrong URL.');

$R['theme-version'] = 1;

Resources::linkFileFooter($cfg['themes_dir'].'/'.$usr['theme'].'/css/modalbox.css');

Resources::linkFileFooter($cfg['themes_dir'].'/'.$usr['theme'].'/css/default.css?v='.$R['theme-version']);
Resources::linkFileFooter($cfg['themes_dir'].'/'.$usr['theme'].'/css/responsive.css?v='.$R['theme-version']);

Resources::linkFileFooter($cfg['themes_dir'].'/'.$usr['theme'].'/js/js.js');

Поясним такой выбор: стили в default.less прописываются м грузятся в первую очередь (mobile first), а в responsive.less мы будем списывать стили, использующие медиа-запросы (media queries). Переменная theme-version в загрузчике используется для кэширования стилей.

Чтобы использовать все возможности LESS и сделать работу со стилями еще более комфортной и продуктивной, создадим в папке less файл с переменными vars.less и подключим его в default.less и responsive.less директивой @import:

@import "vars.less";

Добавляем шаблоны модулей и плагинов

Прежде всего нам понадобятся четыре основных шаблона модуля Page, необходимые для просмотра, добавления и правки страницы, а также для просмотра раздела.

Шаблон page.tpl:

<!-- BEGIN: MAIN -->
<main id="page_{PAGE_ID}" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
				<div class="title mb-3">
					<h1 class="lh-1">{PAGE_SHORTTITLE}</h1>
					{PAGE_CRUMBS}
				</div>
			</div>
		</div>
		<div class="row">
			<div class="col">
				<div class="textbox">
					{PAGE_TEXT}
				</div>
{PAGE_COMMENTS_DISPLAY}
			</div>
		</div>
<!-- IF {PHP.usr.isadmin} -->
{FILE "{PHP.cfg.themes_dir}/{PHP.theme}/inc/admin-page.tpl"}
<!-- ENDIF -->
	</div>
</main>
<!-- END: MAIN -->

Шаблон page.add.tpl:

<!-- BEGIN: MAIN -->
<main id="page_add" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
{FILE "themes/{PHP.theme}/warnings.tpl"}
				<h1 class="lh-1 mb-3">{PAGEADD_PAGETITLE}</h1>
				<form action="{PAGEADD_FORM_SEND}" enctype="multipart/form-data" method="post" name="pageform" class="mb-3">
				<div class="table-responsive">
					<table class="table table-striped m-0">
						<tr>
							<td class="w-25">{PHP.L.Category}:</td>
							<td class="w-75">{PAGEADD_FORM_CAT}</td>
						</tr>
						<tr>
							<td>{PHP.L.Title}:</td>
							<td>{PAGEADD_FORM_TITLE}</td>
						</tr>
						<tr>
							<td>{PHP.L.Description}:</td>
							<td>{PAGEADD_FORM_DESC}</td>
						</tr>
						<tr>
							<td>{PHP.L.Author}:</td>
							<td>{PAGEADD_FORM_AUTHOR}</td>
						</tr>
						<tr>
							<td>{PHP.L.Begin}:</td>
							<td>{PAGEADD_FORM_BEGIN}</td>
						</tr>
						<tr>
							<td>{PHP.L.Expire}:</td>
							<td>{PAGEADD_FORM_EXPIRE}</td>
						</tr>
						<tr>
							<td>{PHP.L.Alias}:</td>
							<td>{PAGEADD_FORM_ALIAS}</td>
						</tr>
						<tr>
							<td>{PHP.L.page_metatitle}:</td>
							<td>{PAGEADD_FORM_METATITLE}</td>
						</tr>
						<tr>
							<td>{PHP.L.page_metadesc}:</td>
							<td>{PAGEADD_FORM_METADESC}</td>
						</tr>
<!-- BEGIN: TAGS -->
						<tr>
							<td>{PAGEADD_TOP_TAGS}:</td>
							<td>{PAGEADD_FORM_TAGS} ({PAGEADD_TOP_TAGS_HINT})</td>
						</tr>
<!-- END: TAGS -->
						<tr>
							<td>{PHP.L.Owner}:</td>
							<td>{PAGEADD_FORM_OWNER}</td>
						</tr>
						<tr>
							<td>{PHP.L.Parser}:</td>
							<td>{PAGEADD_FORM_PARSER}</td>
						</tr>
						<tr>
							<td colspan="2">
								{PAGEADD_FORM_TEXT}
							</td>
						</tr>
						<tr>
							<td colspan="2">
<!-- IF {PHP.usr_can_publish} -->
								<button type="submit" name="rpagestate" value="0" class="btn btn-success btn-sm">{PHP.L.Publish}</button>
<!-- ENDIF -->
								<button type="submit" name="rpagestate" value="2" class="submit btn btn-warning btn-sm">{PHP.L.Saveasdraft}</button>
								<button type="submit" name="rpagestate" value="1" class="btn btn-danger btn-sm">{PHP.L.Submitforapproval}</button>
							</td>
						</tr>
					</table>
				</div>
				</form>
			</div>
		</div>
	</div>
</main>

Шаблон page.edit.tpl:

<!-- BEGIN: MAIN -->
<main id="page_edit" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
{FILE "themes/{PHP.theme}/warnings.tpl"}
				<h1 class="lh-1 mb-3">{PAGEEDIT_PAGETITLE} #{PAGEEDIT_FORM_ID} ({PAGEEDIT_FORM_LOCALSTATUS})</h1>
				<form action="{PAGEEDIT_FORM_SEND}" enctype="multipart/form-data" method="post" name="pageform">
				<div class="table-responsive">
					<table class="table table-striped m-0">
						<tr>
							<td class="w-25">{PHP.L.Category}:</td>
							<td class="w-75">{PAGEEDIT_FORM_CAT}</td>
						</tr>
						<tr>
							<td>{PHP.L.Title}:</td>
							<td>{PAGEEDIT_FORM_TITLE}</td>
						</tr>
						<tr>
							<td>{PHP.L.Description}:</td>
							<td>{PAGEEDIT_FORM_DESC}</td>
						</tr>
						<tr>
							<td>{PHP.L.Author}:</td>
							<td>{PAGEEDIT_FORM_AUTHOR}</td>
						</tr>
						<tr>
							<td>{PHP.L.Date}:</td>
							<td>
								{PAGEEDIT_FORM_DATE}
								<div class="form-group m0">
									<div class="checkbox mb0">
										<label class="checkbox">
											<span class="title pt-1">
												<input type="checkbox" value="1" name="rpagedatenow" class="me-2">{PHP.L.page_date_now}
											</span>
										</label>
									</div>
								</div>
							</td>
						</tr>
						<tr>
							<td>{PHP.L.Begin}:</td>
							<td>{PAGEEDIT_FORM_BEGIN}</td>
						</tr>
						<tr>
							<td>{PHP.L.Expire}:</td>
							<td>{PAGEEDIT_FORM_EXPIRE}</td>
						</tr>
						<tr>
							<td>{PHP.L.Alias}:</td>
							<td>{PAGEEDIT_FORM_ALIAS}</td>
						</tr>
						<tr>
							<td>{PHP.L.page_metatitle}:</td>
							<td>{PAGEEDIT_FORM_METATITLE}</td>
						</tr>
						<tr>
							<td>{PHP.L.page_metadesc}:</td>
							<td>{PAGEEDIT_FORM_METADESC}</td>
						</tr>
<!-- BEGIN: TAGS -->
						<tr>
							<td>{PAGEEDIT_TOP_TAGS}:</td>
							<td>{PAGEEDIT_FORM_TAGS} ({PAGEEDIT_TOP_TAGS_HINT})</td>
						</tr>
<!-- END: TAGS -->
<!-- BEGIN: ADMIN -->
						<tr>
							<td>{PHP.L.Hits}:</td>
							<td>{PAGEEDIT_FORM_PAGECOUNT}</td>
						</tr>
						<tr>
							<td>{PHP.L.Owner}:</td>
							<td>{PAGEEDIT_FORM_OWNERID}</td>
						</tr>
<!-- END: ADMIN -->
						<tr>
							<td>{PHP.L.Parser}:</td>
							<td>{PAGEEDIT_FORM_PARSER}</td>
						</tr>
						<tr>
							<td colspan="2">
								{PAGEEDIT_FORM_TEXT}
							</td>
						</tr>
						<tr>
							<td>{PHP.L.page_deletepage}:</td>
							<td>{PAGEEDIT_FORM_DELETE}</td>
						</tr>
						<tr>
							<td colspan="2">
<!-- IF {PHP.usr_can_publish} -->
								<button type="submit" name="rpagestate" value="0" class="btn btn-success btn-sm">{PHP.L.Publish}</button>
<!-- ENDIF -->
								<button type="submit" name="rpagestate" value="2" class="submit btn btn-warning btn-sm">{PHP.L.Saveasdraft}</button>
								<button type="submit" name="rpagestate" value="1" class="btn btn-danger btn-sm">{PHP.L.Submitforapproval}</button>
							</td>
						</tr>
					</table>
				</div>
				</form>
			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

Шаблон page.list.tpl:

<!-- BEGIN: MAIN -->
<main id="list_{PHP.cat.id}" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
				<div class="title mb-3">
					<h1 class="lh-1">{LIST_CATTITLE}</h1>
					{LIST_CRUMBS}
				</div>
			</div>
		</div>
		<div class="row">
			<div class="col">
<!-- IF {LIST_ROW_NUM} -->
<!-- BEGIN: LIST_ROW -->
					<article class="card py-2 px-3">
						<a href="{LIST_ROW_URL}">{LIST_ROW_SHORTTITLE}</a>
							<ul class="list-inline mb-0">
								<li class="list-inline-item">
									{PHP.L.Views}: {LIST_ROW_COUNT}
								</li>
								<li class="list-inline-item">
									{PHP.L.Date}: {LIST_ROW_DATE}
								</li>
							</ul>
<!-- IF {LIST_ROW_DESC} -->
							<p class="mb-0">
								{LIST_ROW_DESC}
							</p>
<!-- ENDIF -->
					</article>
<!-- END: LIST_ROW -->
<!-- IF {LIST_TOP_PAGINATION} -->
				<nav id="pagination-container">
					<ul class="pagination">
						{LIST_TOP_PAGEPREV}{LIST_TOP_PAGINATION}{LIST_TOP_PAGENEXT}
					</ul>
				</nav>
<!-- ENDIF -->
<!-- ENDIF -->
			</div>
		</div>
<!-- IF {PHP.usr.isadmin} -->
{FILE "{PHP.cfg.themes_dir}/{PHP.theme}/inc/admin-list.tpl"}
<!-- ENDIF -->
	</div>
</main>
<!-- END: MAIN -->

Чтобы задействовать функционал "хлебных крошек", загрузим и установим плагин Crumbs. В админке (раздел Конфигурация / Темы) включим опцию "Ссылка на главную страницу в навигационной цепочке".

В папке inc разместим файлы подгрузки блоков администрирования страниц и разделов:

admin-page.tpl:

<div id="adminblock" class="row">
	<div class="col">
		<ul class="list-inline mt-3 mb-0">
			<li class="list-inline-item">
				<a href="{PHP|cot_url('admin')}">{PHP.L.Adminpanel}</a>
			</li>
			<li class="list-inline-item">{PAGE_ADMIN_UNVALIDATE}</li>
			<li class="list-inline-item">
				<a href="{PAGE_CAT|cot_url('page','m=add&c=$this')}">{PHP.L.page_addtitle}</a>
			</li>
			<li class="list-inline-item">
				{PAGE_ADMIN_EDIT}
			</li>
			<li class="list-inline-item">
				{PAGE_ADMIN_CLONE}
			</li>
			<li class="list-inline-item">
				{PAGE_ADMIN_DELETE}
			</li>
<!-- IF {PHP|cot_auth('plug', 'attach2', 'W')} -->
			<li class="list-inline-item">
				{PAGE_ID|att_widget('page', $this, 'attach2.link')}
			</li>
<!-- ENDIF -->
			<li class="list-inline-item">
				{PHP.out.loginout}
			</li>
		</ul>
	</div>
</div>

admin-list.tpl:

<div id="adminblock" class="row">
	<div class="col">
		<ul class="list-inline mt-3 mb-0">
			<li class="list-inline-item">
				<a href="{PHP|cot_url('admin')}">{PHP.L.Adminpanel}</a>
			</li>
			<li class="list-inline-item">
				<a href="admin.php?m=structure&n=page&id={PHP.cat.id}&x={PHP.sys.xk}">Настройки раздела</a>
			</li>
			<li class="list-inline-item">
				{LIST_SUBMITNEWPAGE}
			</li>
<!-- IF {PHP|cot_auth('plug', 'attach2', 'W')} -->
			<li class="list-inline-item">
				{PHP.cat.id|att_widget('list',$this,'attach2.link')}
			</li>
<!-- ENDIF -->
			<li class="list-inline-item">{PHP.out.loginout}</li>
		</ul>
	</div>
</div>

Для того, чтобы единообразить внешний вид кнопок, используем файл js.js, попутно проверив его загрузку:

$().ready(function() {

	if ($('div#adminblock').length) {
		$('div#adminblock ul > li > a').each(function() {
			$(this).addClass('btn btn-primary btn-sm');
		})
	}

});

Теперь займемся шаблонами модуля users.

users.details.tpl:

<!-- BEGIN: MAIN -->
<main id="users_details" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
{FILE "{PHP.cfg.themes_dir}/{PHP.cfg.defaulttheme}/warnings.tpl"}
				<div class="title mb-3">
					<h1 class="lh-1">
						{PHP.L.User} {USERS_DETAILS_NICKNAME}
<!-- BEGIN: USERS_DETAILS_ADMIN -->
						[ {USERS_DETAILS_ADMIN_EDIT} ]
<!-- END: USERS_DETAILS_ADMIN -->
					</h1>
					<ul class="breadcrumb">
						<li class="breadcrumb-item">
							<a href="{PHP.cfg.mainurl}" title="{PHP.L.Home}">{PHP.L.Home}</a>
						</li>
						<li class="breadcrumb-item">
							<a href="{PHP|cot_url('users')}">{PHP.L.Users}</a>
						</li>
						<li class="breadcrumb-item">
							{USERS_DETAILS_NICKNAME}
						</li>
					</ul>
				</div>
				<div class="table-responsive">
					<table class="table table-striped table-hover mb-0">
<!-- IF {PHP.cot_modules.pm} -->
						<tr>
							<td>{PHP.L.users_sendpm}:</td>
							<td>{USERS_DETAILS_PM}</td>
						</tr>
<!-- ENDIF -->
						<tr>
							<td class="w-25">{PHP.L.Maingroup}:</td>
							<td class="w-75">{USERS_DETAILS_MAINGRP}</td>
						</tr>
						<tr>
							<td>{PHP.L.Groupsmembership}:</td>
							<td>{USERS_DETAILS_GROUPS}</td>
						</tr>
						<tr>
							<td>{PHP.L.Country}:</td>
							<td>{USERS_DETAILS_COUNTRYFLAG} {USERS_DETAILS_COUNTRY}</td>
						</tr>
						<tr>
							<td>{PHP.L.Timezone}:</td>
							<td>{USERS_DETAILS_TIMEZONE}</td>
						</tr>
						<tr>
							<td>{PHP.L.Birthdate}:</td>
							<td>{USERS_DETAILS_BIRTHDATE}</td>
						</tr>
						<tr>
							<td>{PHP.L.Age}:</td>
							<td>{USERS_DETAILS_AGE}</td>
						</tr>
						<tr>
							<td>{PHP.L.Gender}:</td>
							<td>{USERS_DETAILS_GENDER}</td>
						</tr>
						<tr>
							<td>{PHP.L.Signature}:</td>
							<td>{USERS_DETAILS_TEXT}</td>
						</tr>
						<tr>
							<td>{PHP.L.Registered}:</td>
							<td>{USERS_DETAILS_REGDATE}</td>
						</tr>
<!-- IF {PHP.usr.isadmin} -->
						<tr>
							<td>
								Last seen:
							</td>
							<td>
								{USERS_DETAILS_LASTLOG_STAMP|cot_date('H:i j F Y', $this)}
							</td>
						</tr>
<!-- ENDIF -->
<!-- IF {USERS_DETAILS_AVATAR} -->
						<tr>
							<td>{PHP.L.Avatar}:</td>
							<td>{USERS_DETAILS_AVATAR}</td>
						</tr>
<!-- ENDIF -->
<!-- IF {USERS_DETAILS_PHOTO} -->
						<tr>
							<td>{PHP.L.Photo}:</td>
							<td>{USERS_DETAILS_PHOTO}</td>
						</tr>
<!-- ENDIF -->
					</table>
				</div>
			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

users.edit.tpl:

<!-- BEGIN: MAIN -->
<main id="users_edit" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
{FILE "{PHP.cfg.themes_dir}/{PHP.cfg.defaulttheme}/warnings.tpl"}
				<div class="title mb-3">
					<h1 class="lh-1">{PHP.L.Edit} {PHP.urr.user_name}</h1>
					<ul class="breadcrumb">
						<li class="breadcrumb-item">
							<a href="{PHP.cfg.mainurl}" title="{PHP.L.Home}">{PHP.L.Home}</a>
						</li>
						<li class="breadcrumb-item">
							<a href="{PHP|cot_url('users')}">{PHP.L.Users}</a>
						</li>
						<li class="breadcrumb-item">
							{PHP.urr.user_name}
						</li>
					</ul>
				</div>
				<form action="{USERS_EDIT_SEND}" method="post" name="useredit" enctype="multipart/form-data">
					<input type="hidden" name="id" value="{USERS_EDIT_ID}" />
					<div class="table-responsive">
						<table class="table table-striped table-hover mb-0">
							<tr>
								<td class="w-25">{PHP.L.users_id}:</td>
								<td class="w-75">#{USERS_EDIT_ID}</td>
							</tr>
							<tr>
								<td>{PHP.L.Username}:</td>
								<td>{USERS_EDIT_NAME}</td>
							</tr>
							<tr>
								<td>{PHP.L.Groupsmembership}:</td>
								<td>
									{PHP.L.Maingroup}:
									{USERS_EDIT_GROUPS}
								</td>
							</tr>
							<tr>
								<td>{PHP.L.Country}:</td>
								<td>{USERS_EDIT_COUNTRY}</td>
							</tr>
							<tr>
								<td>{PHP.L.Timezone}:</td>
								<td>{USERS_EDIT_TIMEZONE}</td>
							</tr>
							<tr>
								<td>{PHP.L.Theme}:</td>
								<td>{USERS_EDIT_THEME}</td>
							</tr>
							<tr>
								<td>{PHP.L.Language}:</td>
								<td>{USERS_EDIT_LANG}</td>
							</tr>
<!-- IF {USERS_EDIT_AVATAR} -->
							<tr>
								<td>{PHP.L.Avatar}:</td>
								<td>{USERS_EDIT_AVATAR}</td>
							</tr>
<!-- ENDIF -->
<!-- IF {USERS_EDIT_SIGNATURE} -->
							<tr>
								<td>{PHP.L.Signature}:</td>
								<td>{USERS_EDIT_SIGNATURE}</td>
							</tr>
<!-- ENDIF -->
<!-- IF {USERS_EDIT_PHOTO} -->
							<tr>
								<td>{PHP.L.Photo}:</td>
								<td>{USERS_EDIT_PHOTO}</td>
							</tr>
<!-- ENDIF -->
							<tr>
								<td>{PHP.L.users_newpass}:</td>
								<td>
									{USERS_EDIT_NEWPASS}
									<p class="small">{PHP.L.users_newpasshint1}</p>
								</td>
							</tr>
							<tr>
								<td>{PHP.L.Email}:</td>
								<td>{USERS_EDIT_EMAIL}</td>
							</tr>
							<tr>
								<td>{PHP.L.users_hideemail}:</td>
								<td>{USERS_EDIT_HIDEEMAIL}</td>
							</tr>
<!-- IF {PHP.cot_modules.pm} -->
							<tr>
								<td>{PHP.L.users_pmnotify}:</td>
								<td>{USERS_EDIT_PMNOTIFY}<br />{PHP.themelang.usersedit.PMnotifyhint}</td>
							</tr>
<!-- ENDIF -->
							<tr>
								<td>{PHP.L.Birthdate}:</td>
								<td>{USERS_EDIT_BIRTHDATE}</td>
							</tr>
							<tr>
								<td>{PHP.L.Gender}:</td>
								<td>{USERS_EDIT_GENDER}</td>
							</tr>
							<tr>
								<td>{PHP.L.Signature}:</td>
								<td>{USERS_EDIT_TEXT}</td>
							</tr>
							<tr>
								<td>{PHP.L.Registered}:</td>
								<td>{USERS_EDIT_REGDATE}</td>
							</tr>
							<tr>
								<td>{PHP.L.Lastlogged}:</td>
								<td>{USERS_EDIT_LASTLOG}</td>
							</tr>
							<tr>
								<td>{PHP.L.users_lastip}:</td>
								<td>{USERS_EDIT_LASTIP}</td>
							</tr>
							<tr>
								<td>{PHP.L.users_logcounter}:</td>
								<td>{USERS_EDIT_LOGCOUNT}</td>
							</tr>
							<tr>
								<td>{PHP.L.users_deleteuser}:</td>
								<td>{USERS_EDIT_DELETE}</td>
							</tr>
							<tr>
								<td colspan="2">
									<button type="submit" class="btn btn-primary">{PHP.L.Update}</button>
								</td>
							</tr>
						</table>
					</div>
				</form>
			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

users.passrecover.tpl:

<!-- BEGIN: MAIN -->
<main id="users_passrecover" class="my-4">
	<div class="container">
		<div class="row">
			<div class="mx-auto col col-lg-7 col-xl-6 col-xxl-5">
{FILE "{PHP.cfg.themes_dir}/{PHP.theme}/warnings.tpl"}
				<div class="title mb-3">
					<h1 class="lh-1">{PHP.L.pasrec_title}</h1>
					<ul class="breadcrumb">
						<li class="breadcrumb-item">
							<a href="{PHP.cfg.mainurl}">{PHP.cfg.maintitle}</a>
						</li>
						<li class="breadcrumb-item">{PHP.L.pasrec_title}</li>
					</ul>
				</div>
<!-- IF {PHP.msg} == 'request' -->
				<div class="alert alert-info mb-0">
					<p class="mb-0">
						{PHP.L.pasrec_mailsent}
					</p>
				</div>
<!-- ENDIF -->
<!-- IF {PHP.msg} == 'auth' -->
				<div class="alert alert-info mb-0">
					<p class="mb-0">
						{PHP.L.pasrec_mailsent2}
					</p>
				</div>
<!-- ENDIF -->
<!-- IF !{PHP.msg} -->
				<form role="form" name="reqauth" action="{PASSRECOVER_URL_FORM}" method="post" class="">
					<ol>
						<li>{PHP.L.pasrec_explain1}</li>
						<li>{PHP.L.pasrec_explain2}</li>
						<li>{PHP.L.pasrec_explain3}</li>
					</ol>
					<div class="input-group mb-3">
						<input type="text" class="form-control" name="email" />
						<button type="submit" class="btn btn-primary">{PHP.L.pasrec_request}</button>
					</div>
					<div class="alert alert-info mb-0">
						{PHP.L.pasrec_explain4}
					</div>
				</form>
<!-- ENDIF -->
			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

users.profile.tpl:

<!-- BEGIN: MAIN -->
<main id="users_profile" class="mb-4">
	<div class="container">
		<div class="row">
			<div class="col">
{FILE "{PHP.cfg.themes_dir}/{PHP.theme}/warnings.tpl"}
				<div class="title mb-3">
					<h1 class="lh-1">{PHP.L.Profile}</h1>
					<ul class="breadcrumb">
						<li class="breadcrumb-item">
							<a href="{PHP.cfg.mainurl}" title="{PHP.L.Home}">{PHP.L.Home}</a>
						</li>
						<li class="breadcrumb-item">
							{USERS_PROFILE_TITLE}
						</li>
					</ul>
				</div>
				<form action="{USERS_PROFILE_FORM_SEND}" method="post" enctype="multipart/form-data" name="profile">
					<input type="hidden" name="userid" value="{USERS_PROFILE_ID}" />
					<div class="table-responsive">
						<table class="table table-striped table-hover mb-0">
							<tr>
								<td class="w-25">{PHP.L.Username}:</td>
								<td class="w-75">{USERS_PROFILE_NAME}</td>
							</tr>
							<tr>
								<td>{PHP.L.Groupsmembership}:</td>
								<td>{USERS_PROFILE_GROUPS}</td>
							</tr>
							<tr>
								<td>{PHP.L.Registered}:</td>
								<td>{USERS_PROFILE_REGDATE}</td>
							</tr>
<!-- BEGIN: USERS_PROFILE_EMAILCHANGE -->
							<tr>
								<td>{PHP.L.Email}:</td>
								<td>
									{PHP.L.Email}:<br />{USERS_PROFILE_EMAIL}
<!-- BEGIN: USERS_PROFILE_EMAILPROTECTION -->
									<script type="text/javascript">
										$(document).ready(function(){
											$("#emailnotes").hide();
											$("#emailtd").click(function(){$("#emailnotes").slideDown();});
										});
									</script>
									<div>
										{PHP.themelang.usersprofile.Emailpassword}:<br />{USERS_PROFILE_EMAILPASS}
									</div>
									<div>{PHP.themelang.usersprofile.Emailnotes}</div>
<!-- END: USERS_PROFILE_EMAILPROTECTION -->
								</td>
							</tr>
<!-- END: USERS_PROFILE_EMAILCHANGE -->
							<tr>
								<td>{PHP.L.users_hideemail}:</td>
								<td>{USERS_PROFILE_HIDEEMAIL}</td>
							</tr>
<!-- IF {PHP.cot_modules.pm} -->
							<tr>
								<td>{PHP.L.users_pmnotify}:</td>
								<td>
									{USERS_PROFILE_PMNOTIFY}
									<p class="small mb-0">{PHP.L.users_pmnotifyhint}</p>
								</td>
							</tr>
<!-- ENDIF -->
							<tr>
								<td>{PHP.L.Theme}:</td>
								<td>{USERS_PROFILE_THEME}</td>
							</tr>
							<tr>
								<td>{PHP.L.Language}:</td>
								<td>{USERS_PROFILE_LANG}</td>
							</tr>
							<tr>
								<td>{PHP.L.Country}:</td>
								<td>{USERS_PROFILE_COUNTRY}</td>
							</tr>
							<tr>
								<td>{PHP.L.Timezone}:</td>
								<td>{USERS_PROFILE_TIMEZONE}</td>
							</tr>
							<tr>
								<td>{PHP.L.Birthdate}:</td>
								<td>{USERS_PROFILE_BIRTHDATE}
								</td>
							</tr>
							<tr>
								<td>{PHP.L.Gender}:</td>
								<td>{USERS_PROFILE_GENDER}</td>
							</tr>
<!-- IF {USERS_PROFILE_AVATAR} -->
							<tr>
								<td>{PHP.L.Avatar}:</td>
								<td>{USERS_PROFILE_AVATAR}</td>
							</tr>
<!-- ENDIF -->
<!-- IF {USERS_PROFILE_PHOTO} -->
							<tr>
								<td>{PHP.L.Photo}:</td>
								<td>{USERS_PROFILE_PHOTO}</td>
							</tr>
<!-- ENDIF -->
							<tr>
								<td>{PHP.L.Signature}:</td>
								<td>{USERS_PROFILE_TEXT}</td>
							</tr>
							<tr>
								<td>
									{PHP.L.users_newpass}:
									<p class="small">{PHP.L.users_newpasshint1}</p>
								</td>
								<td>
									{USERS_PROFILE_OLDPASS}
									<p class="small mb-2">{PHP.L.users_oldpasshint}</p>
									{USERS_PROFILE_NEWPASS1} {USERS_PROFILE_NEWPASS2}
									<p class="small m-0">{PHP.L.users_newpasshint2}</p>
								</td>
							</tr>
							<tr>
								<td colspan="2">
									<button type="submit" class="btn btn-primary">{PHP.L.Update}</button>
								</td>
							</tr>
						</table>
					</div>
				</form>
			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

users.register.tpl:

<!-- BEGIN: MAIN -->
<main id="users_register" class="my-4">
	<div class="container">
		<div class="row">
			<div class="mx-auto col col-lg-7 col-xl-6 col-xxl-5">
{FILE "{PHP.cfg.themes_dir}/{PHP.theme}/warnings.tpl"}
				<div class="title mb-3">
					<h1 class="lh-1">{USERS_REGISTER_TITLE}</h1>
					<ul class="breadcrumb">
						<li class="breadcrumb-item">
							<a href="{PHP.cfg.mainurl}">{PHP.cfg.maintitle}</a>
						</li>
						<li class="breadcrumb-item">
							{PHP.L.Register}
						</li>
					</ul>
				</div>
				<form name="login" action="{USERS_REGISTER_SEND}" method="post" enctype="multipart/form-data">
					<div class="mb-3">
						<label class="control-label" for="">{PHP.L.Username}</label>
						{USERS_REGISTER_USER}
					</div>
					<div class="mb-3">
						<label class="control-label" for="">{PHP.L.users_validemail} {PHP.L.users_validemailhint}</label>
						{USERS_REGISTER_EMAIL}
					</div>
					<div class="mb-3">
						<label class="control-label" for="">{PHP.L.Password}</label>
						{USERS_REGISTER_PASSWORD}
					</div>
					<div class="mb-3">
						<label class="control-label" for="">{PHP.L.users_confirmpass}</label>
						{USERS_REGISTER_PASSWORDREPEAT}
					</div>
					<div class="mb-3">
						<label class="control-label" for="">{USERS_REGISTER_VERIFYIMG}</label>
						{USERS_REGISTER_VERIFYINPUT}
					</div>
					<div class="btn-group w-100">
						<button type="submit" class="btn btn-success btn flex-fill">{PHP.L.Registration}</button>
						<a href="{PHP|cot_url('login')}" class="btn btn-primary btn flex-fill">{PHP.L.Login}</a>
						<a href="{PHP|cot_url('users','m=passrecover')}" class="btn btn-primary btn flex-fill">{PHP.L.users_lostpass}</a>
					</div>
				</form>
			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

users.tpl:

<!-- BEGIN: MAIN -->
<main id="users" class="my-4">
	<div class="container">
		<div class="row">
			<div class="col">
{FILE "{PHP.cfg.themes_dir}/{PHP.cfg.defaulttheme}/warnings.tpl"}
				<div class="title mb-3">
					<h1 class="lh-1">{PHP.L.Users}</h1>
					<ul class="breadcrumb">
						<li class="breadcrumb-item">
							<a href="{PHP.cfg.mainurl}" title="{PHP.L.Home}">{PHP.L.Home}</a>
						</li>
						<li class="breadcrumb-item">
							{PHP.L.Users}
						</li>
					</ul>
				</div>
				<div class="table-responsive">
					<table class="table table-striped table-hover">
						<thead>
							<tr class="text-center">
								<th class="w-5">{USERS_TOP_PM}</th>
								<th class="w-25">{USERS_TOP_NAME}</th>
								<th class="w-25">{USERS_TOP_GRPTITLE}</th>
								<th class="w-20">{USERS_TOP_GRPLEVEL}</th>
								<th class="w-25">{USERS_TOP_REGDATE}</th>
							</tr>
						</thead>
						<tbody>
<!-- BEGIN: USERS_ROW -->
							<tr class="text-center">
								<td>{USERS_ROW_PM}</td>
								<td>{USERS_ROW_NAME}&nbsp;{USERS_ROW_TAG}</td>
								<td>{USERS_ROW_MAINGRP}</td>
								<td>{USERS_ROW_MAINGRPSTARS}</td>
								<td>{USERS_ROW_REGDATE}</td>
							</tr>
<!-- END: USERS_ROW -->
						</tbody>
					</table>
					<p class="text-center mb-0">
						{PHP.L.users_usersperpage}: {USERS_TOP_MAXPERPAGE} | {PHP.L.users_usersinthissection}: {USERS_TOP_TOTALUSERS}
					</p>
	<!-- IF {USERS_TOP_PAGNAV} -->
					<nav id="pagination-container">
						<ul class="pagination">
							{USERS_TOP_PAGEPREV}{USERS_TOP_PAGNAV}{USERS_TOP_PAGENEXT}
						</ul>
					</nav>
	<!-- ENDIF -->
				</div>
			</div>
		</div>
	</div>
</main>
<!-- END: MAIN -->

Для того, чтобы вся эта история заработала, подключим Bootstrap. Например, при помощи нашего плагина Bootstrap.

Практически все стало красиво. Исключение -- некоторые локации модуля users:

  1. users.details, users.edit, users.profile -- список групп пользователя выводится в контейнере ul;
  2. login -- теги USERS_AUTH_USER, USERS_AUTH_PASSWORD и USERS_AUTH_REMEMBER не имеют классов Bootstrap;
  3. register -- теги USERS_REGISTER_USER, USERS_REGISTER_EMAIL, USERS_REGISTER_PASSWORD, USERS_REGISTER_PASSWORDREPEAT, USERS_REGISTER_VERIFYINPUT не имеют классов Bootstrap.

Можно исправить эти проблемы двумя способами:

  1. используя jQuery;
  2. переназначив соответствующие ресурсы миниплагином.

Поскольку jQuery мы уже использовали выше, выберем второй способ и создадим плагин Kudos с тремя частями и кастомным файлом ресурсов:

kudos.resources.php:

<?php
/*
 * Redefine some Users module resources
 */

$R['users_code_grplist_begin'] = '<ul class="list-unstyled mb-0">';

$R['form_guest_remember'] = '<input type="checkbox" name="rremember" class="form-check-input" title="'.$L['users_rememberme'].'" />';
$R['form_guest_remember_forced'] = '<input type="checkbox" name="rremember" class="form-check-input" title="'.$L['users_rememberme'].'" checked="checked" disabled="disabled" />';

kudos.login.php:

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=users.auth.tags
[END_COT_EXT]
==================== */

/**
 * Customization for Kudos theme
 *
 * @package Kudos
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

defined('COT_CODE') or die('Wrong URL');

require_once cot_incfile('kudos', 'plug', 'resources');

$t->assign(array(
	'USERS_AUTH_USER' => cot_inputbox('text', 'rusername', $rusername, array('size' => '12', 'maxlength' => '100', 'class' => 'form-control')),
	'USERS_AUTH_PASSWORD' => cot_inputbox('password', 'rpassword', '', array('size' => '12', 'maxlength' => '32', 'class' => 'form-control')),
	'USERS_AUTH_REMEMBER' => Cot::$cfg['forcerememberme'] ? Cot::$R['form_guest_remember_forced'] : Cot::$R['form_guest_remember']
));

kudos.register.php:

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=users.register.tags
[END_COT_EXT]
==================== */

/**
 * Customization for Kudos theme
 *
 * @package Kudos
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

defined('COT_CODE') or die('Wrong URL');

$t->assign(array(
	'USERS_REGISTER_USER' => cot_inputbox('text', 'rusername', $ruser['user_name'], array('size' => 24, 'maxlength' => 100, 'class' => 'form-control')),
	'USERS_REGISTER_EMAIL' => cot_inputbox('text', 'ruseremail', $ruser['user_email'], array('size' => 24, 'maxlength' => 64, 'class' => 'form-control')),
	'USERS_REGISTER_PASSWORD' => cot_inputbox('password', 'rpassword1', '', array('size' => 12, 'maxlength' => 32, 'class' => 'form-control')),
	'USERS_REGISTER_PASSWORDREPEAT' => cot_inputbox('password', 'rpassword2', '', array('size' => 12, 'maxlength' => 32, 'class' => 'form-control')),
	'USERS_REGISTER_VERIFYINPUT' => cot_inputbox('text', 'rverify', '', array('size' => 10, 'maxlength' => 20, 'class' => 'form-control')),
));

kudos.users.php:

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=users.edit.first,users.details.first,users.profile.first
[END_COT_EXT]
==================== */

/**
 * Customization for Kudos theme
 *
 * @package Kudos
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

defined('COT_CODE') or die('Wrong URL');

require_once cot_incfile('kudos', 'plug', 'resources');

Ничего сверхъестественного плагин не делает, всего лишь переназначает необходимые нам ресурсные строки, добавляя им необходимые CSS-классы.

Заключение

Мы создали стартовую (модельную) тему для движка Cotonti. Фактически, это тема-пустышка, адаптированная под Bootstrap, в которой проработаны все служебные шаблоны. Добавьте к ней тему админки Yukon, и у Вас будет готовая сборка для создания нового проекта "с нуля".

Для кастомизации данной стартовой темы нам понадобилось написать небольшой плагин Kudos и установить готовые плагины для загрузки Bootstrap и генерации "хлебных крошек". Дальнейшая разработка сайта, возможно, потребует большего их количества, однако этого не стоит опасаться: Cotonti именно так и создана. Тема универсальной "заготовки" будет развиваться и дальше.

Аватар

1. Sergeich

  • 29.03.2024 12:43

Спасибо за статью. Берём на вооружение :)

Новый комментарий

Имя:
Для редактирования комментария осталось 10 минут