Создание настроек сайта
Выбираем в админке раздел "Настройки сайта" и не видим никаких настроек:
Жмём "Создать настройки", и создаём:
Название может быть любое, идентификатор - только латиница. Если создаем настройки для русской версии сайта, на английской они видны не будут. Что в принципе логично.
Теперь видим, что настройки появились:
Вопрос только - что с ними делать? Ставим рядом галку, в пиктографическом меню нажимаем "Редактировать" - и видим ту же самую форму, что только что заполнили. Где логотип, где копирайт? Так мы незаметно подошли к большой теме - Создание шаблонов данных.
Вывод настроек в шаблоне
Добавим в настройки логотип и копирайт:
Теперь попробуем вывести всё это на страницах сайта.
И тут мы сталкиваемся с очередной засадой UMI CMS. Казалось бы, каждому сайту должен соответствовать какой-то один набор настроек. Но в интерфейсе видим, что этих наборов можно создать сколько угодно. Господа разработчики, может, стоило бы для упрощения ограничить эти возможности? Кто-то вообще использует больше одного набора настроек для конкретной языковой версии сайта? Было бы шикарно получать настройки прямо в массиве $variables, как вы считаете?
Зато есть повод поупражняться с API системы. Один из способов получить настройки - использовать заданный нами идентификатор настроек, в данном случае 'demo':
$settings = $this->getObjectById($this->macros('umiSettings', 'getIdByName', 'demo'])); var_dump($settings);
Здесь мы использовали метод getIdByName('...') модуля umiSettings для получения id настроек по названию (это именно название, не идентификатор), а потом получили сам объект настроек при помощи метода getObjectById().
Добавим этот код в самое начало common.phtml. К счастью, в настройках разных языковых версий можно задавать один и тот же идентификатор, а то было бы совсем грустно. В общем, получилось. Если добавить на страницу <?= $settings->copyright ?>, то увидим копирайт, который ввели.
Теперь попробуем другой путь, ведь мы не фанаты делать кучу настроек:
$set = new selector('objects'); $set->types('object-type')->name('umiSettings', 'settings'); $set->where('domain_id')->equals($variables['domain-id']); $set->where('lang_id')->equals($variables['lang-id']); $set->limit(0, 1); $settings = $set->result(); var_dump($settings);
В этом коде был использован самый мощный класс ядра UMI - selector. Он подробно описан в документации. Чего в документации нет, так это - что подставлять в качестве 'object-type'. Но в админке есть где посмотреть: 'Шаблоны данных' - 'Настройки модуля' (ссылка справа вверху). Для начала лучше в этих настройках ничего не менять, но в качестве справочника - бесценно!
Здесь мы ищем селектором те единственные настройки, что соответствуют конкретной языковой версии нашего сайта. Синтаксически это почти SQL-запрос, на мой взгляд, тут всё просто.
UMI CMS в конце каждой страницы выдает время её формирования, что очень удобно. Легко убедиться, что второй способ на 0.001 секунды быстрее, помимо прочих его преимуществ. Конечно, неплохо бы проверить, что хоть какие-то настройки нашлись. Кроме этого, хотелось бы получить настройки в самом начале, а использовать их в произвольных фрагментах нашего шаблона. В результате модифицируем код common.phtml как-то так:
<?php $set = new selector('objects'); $set->types('object-type')->name('umiSettings', 'settings'); $set->where('domain_id')->equals($variables['domain-id']); $set->where('lang_id')->equals($variables['lang-id']); $set->limit(0, 1); $variables['settings'] = array_shift($set->result()); if (empty($variables['settings'])) { echo $this->translate('no settings'); exit(); } ?> <!DOCTYPE html> <html> <?= $this->render($variables, 'layout/head') ?> <body> <?= $this->render($variables, 'layout/header') ?> <?= $this->render($variables, 'layout/main') ?> <?= $this->render($variables, 'layout/footer') ?> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> </body> </html>
Копирайт мы собирались использовать в подвале сайта, поэтому пишем в footer.phtml:
<footer> <div class="container"> <?= $variables['settings']->copyright ?><?= date("Y") ?> </div> </footer>
Проверяем результат - всё получилось! Теперь надо разобраться с логотипом. Добавляем <?php var_dump($variables['settings']->logo); ?> в файл header.phtml, и видим, что это объект. Причем - ещё одна засада UMI CMS - все свойства без исключения protected!!! Зато в нем есть все, что нам нужно. Итак, изучаем документацию по классам umiFile и umiImageFile, и новый header.phtml будет выглядеть примерно так:
<?php $pageId = isset($variables['pageId'])?$variables['pageId']:0; $menuTree = $this->macros('content', 'menu', [0, 2, 0, true, $pageId]); $logo = $variables['settings']->logo; ?> <header> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <a class="navbar-brand" href="/"> <?php if ($logo): ?> <img src="/<?= $logo->getFilePath() ?>" title="<?= $logo->getTitle() ?>" alt="<?= $logo->getAlt() ?>"> <?php endif; ?> </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <?php foreach ($menuTree['void:lines'] as $item) { $dropdown = !empty($item['items']['nodes:item']); $active = !empty($item['attribute:status']); if (isset($item['@link']) && isset($item['@name'])) { if ($dropdown) { ?> <li class="nav-item dropdown <?=$active?'active':''?>"> <a class="nav-link dropdown-toggle" href="<?= $item['@link'] ?>" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><?= $item['@name'] ?></a> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <?php foreach ($item['items']['nodes:item'] as $sub) { if (isset($sub['@link']) && isset($sub['@name'])) { ?> <a class="dropdown-item" href="<?= $sub['@link'] ?>"><?= $sub['@name'] ?></a> <?php } } ?> </div> </li> <?php } else { ?> <li class="nav-item <?=$active?'active':''?>"> <a class="nav-link" href="<?= $item['@link'] ?>"><?= $item['@name'] ?></a> </li> <?php } } } ?> </ul> </div> </nav> </header>
Почему перед адресом изображения стоит '/'? Потому что getFilePath() зачем-то перед адресом ставит точку, хоть адрес возвращает абсолютный. Загадка. В качестве alt и title пробуем получить значения, которые должны были задать в админке при заливке файла. Но поскольку ничего не задали, они будут пустые. А вообще, по-хорошему, надо добавить в настройки еще одно поле - название компании, и выводить именно его.
Edit-in-place для настроек
Теперь осталось добавить возможность изменять эти поля прямо на сайте. В принципе, ничего сложного:
<img umi:object-id="<?= $logo->getId() ?>" umi:field-name="logo" src="/<?= $logo->getFilePath() ?>" title="<?= $logo->getTitle() ?>" alt="<?= $logo->getAlt() ?>">
Это для логотипа, а для копирайта:
<span umi:object-id="<?= $logo->getId() ?>" umi:field-name="logo" umi:empty="<?= $this->translate('empty_copyright') ?>"> <?= $variables['settings']->copyright ?> </span> <?= date("Y") ?>
Пришлось добавить дополнительный <span>, чтобы копирайт был в отдельном контейнере.
Другие модули системы
Пока нам для сайта хватало модуля content, немного использовали umiSettings. Однако полезных модулей гораздо больше, и пора наконец добавить на сайт раздел Новости.