предыдущая статья: Использование XSLT при создании сайта на Umbraco

01.12.2013

Обзор архитектуры Umbraco CMS

Все нижесказанное применимо к системе управления содержимым Umbraco текущего четвертого поколения (версии 4.x). Переход разработчиков и архитекторов системы в наступающем, пятом, поколении к парадигме MVC сулит нам, вероятно, совершенно новые архитектурные решения, однако это тема находится за рамками данного обзора.

В первом же абзаце хочется донести до читателя ключевую концепцию построения, на которую все будет опираться: система Umbraco построена на основе принципа, я бы сказал, буквальной расшифровки аббревиатуры CMS - Система Управления Контентом (содержимым). Исходя из этого принципа, разработка веб сайта основывается на такой сущности как документ. Umbracо, можно однозначно говорить, - система управления документами. И все в ней построено вокруг этого базового архитектурного момента.

пример иерархии типов документов в UmbracoИтак, основной информационной единицей (но не атомарной, конечно, это мы далее рассмотрим), является документ - фактически связанный меж собой смысловыми связями набор разнородных данных, объединенных в общий контейнер. Примеры: от самого простого - документа «новость» со строковым заголовком, датой выхода, абзацем анонса, «длинным текстом», необязательным к заполнению, и картинкой для вывода в анонсе, до совсем «сложносочиненных» многоэтажных конструкций с десятками полей данных разного типа.

Документы в системе объединяются в иерархию, визуально представленную в дереве содержимого; также, заметим, можно управлять не только набором и типами полей данных в документе, но и, что немаловажно, правилами подчиненности документов. То есть силами администратора сайта, во время и после создания сайта, в пару кликов буквально можно, например, разрешить создавать в документе-контейнере «новости» только документы типа «новость», и никакие другие, что позволит в дальнейшем избежать массы потенциальных проблем с конечными пользователями, могущими поместить «валенки» в контейнер для «бубликов»…

Редактирование дочерних узлов документа Umbraco

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

Типы данных

Редактирование полей данных в типе документа Umbraco

Документ, как мы уже определили, состоит из различного рода «полей данных». Поля в документе могут быть различных типов, спектр которых фактически ничем не ограничен - можно разрабатывать свои типы данных и внедрять их в систему путем помещения несложных в разработке сборок в папку bin проекта и простейшей регистрации типа в системе. В базовой поставке системы таких типов данных (data types) около двух десятков, известный пакет расширения Умбрако uComponents к примеру добавляет к системе еще примерно десятка три. Тип данных - это именованная совокупность трех составных частей: физического типа данных хранилища в таблице БД (их может быть четыре: целое число (integer), дата (datetime), строка (nvarchar) и длинный текст (ntext), визуального редактора для полей данных этого типа в рамках общего редактора документа, а также выбранный разработчиком этого типа данных способ преобразования хранимых данных (особенно сложных) между хранилищем БД и внутренним представлением времени исполнения. Во многих нетривиальных типах данных присутствуют настроечные параметры для конфигурирования редактора и/или правила хранения.

Пользовательский тип данных Umbraco - основан на выпадающем списке, фиксированные варианты выбора

Поясним это на паре примеров. Для типа данных «Дата и время» в качестве хранилища берется поле в БД типа datetime, в качестве редактора - какой-то выбранный разработчиками визуальный datepicker, а в качестве правила хранения - прямое помещение информации в поле БД. Для типа данных «выбор множества медиа-материалов» в качестве хранилища например выбирается поле ntext, редактор выполняется к примеру в виде списка узлов медиа-дерева с возможностью множественного выбора, а правила хранения и настройки определяют, будет ли тип данных во время выполнения содержать лишь список числовых идентификаторов выбранных медиа-материалов через запятую или готовый собранный фрагмент XML-дерева для представления всех полей выбранных материалов.

Набора типов данных из стандартной поставки Умбрако вполне хватает для решения типовых задач хранения информации, а упоминаемый пакет uComponents расширяет систему до совсем уж универсального набора. Если и этого не хватит - к услугам разработчиков масса пакетов расширения с новыми типами данных на сайте официального сообщества our.umbraco.org на многие случаи жизни, а также возможность разработать свои неповторимые типы данных в случае крайней надобности.

Типы документов

Итак, у нас есть возможность «собрать» структуру документа (document type) из различных полей данных разного типа. Каждому полю в документе дается текстовое название и пояснительная подсказка (на любом языке), а также alias, по которому к полю можно будет обращаться в дальнейшем (только символы латинского алфавита). У каждого поля можно отметить флажком признак обязательности заполнения при редактировании документа, при установке которого система не позволит публиковать материалы с недозаполненными полями, а лишь сохранять их как черновики. Также для полей, допускающих простой ввод с клавиатуры, можно задать регулярные выражения для валидации вводимых данных.

Дабы избежать в документах приличной сложности длиннющих «простыней» из большого списка полей, предусмотрена возможность создавать в рамках документа вкладки (tabs), и помещать поля данных на различные «страницы». Поля в рамках вкладки могут быть перемещены, для изменения порядка их следования в редакторе документа. Сортировка порядка вкладок также предусмотрена.

Редактирование документа Umbraco, закладки документа

Одна из важнейших архитектурных особенностей Umbraco - аппарат «наследования» типов документов, в результате которой разработчики получают возможность строить модели документов в Умбрако в полном соответствии с моделью данных своей текущей области деятельности. При указании у нового типа документа предка из числа уже созданных, в создаваемом типе будут присутствовать все поля и вкладки из родительского типа. В качестве примера приведем уже упомянутую нами в статьях технологию работы с типами документов, которую мы постепенно приняли на вооружение у себя: в базовом типе данных мы добавляем на существующую вкладку общих полей типа данных различные служебные поля, такие как «скрывать документ в навигации» или «название url документа», затем наследуем от базового типа другой тип, являющийся предком для всех видимых страниц сайта, - «SEO-страницы», в который добавляем отдельную вкладку, на которую помещаем поля meta-title, meta-keywords и meta-description вполне понятного назначения. Далее все видимые страницы сайта кроме своих собственных полей получают в наследство все вышеупомянутые.

Зарезервированные поля Umbraco на закладке свойств документа

Типу документа как целому также назначается читаемое имя и псевдоним (alias) для работы в программном коде, иконка и описание, ставятся в соответствие уже упомянутые ранее правила создания дочерних документов, а также допустимые шаблоны представления (templates).

Шаблоны

Шаблоны (templates) - еще один системообразующий краеугольный камень Umbraco.

В 4-й версии системы, о которой здесь идет речь, шаблоны - это стандартные мастер-страницы ASP.NET (masterpages). В центре администрирования Умбрако шаблоны, как и все остальные сущности, представлены в виде фрагмента дерева, что позволяет наглядно видеть иерархию шаблонов. В шаблоны выносится вся «статическая» разметка страниц, вложенность шаблонов позволяет проектировать страницы с «переиспользованием» повторяюихся частей разметки, меняя лишь нужные фрагменты путем выделения их в отдельные контейнеры-плэйсхолдеры (placeholders).

Пример иерархии шаблонов документов Umbraco

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

Кроме секций «статической» разметки в шаблоны можно интегрировать различные «системные» вызовы Умбрако - вставку полей документа и «макросы».

Поля документа могут быть использованы на странице, определенной данным шаблоном, путем вставки в нужные места специализированных тэгов, определяющих псевдоним (alias) выводимого поля и всевозможные опции вывода. Спец-тэги эти формируются редактором шаблонов в результате вызова специального диалогового окна «вставить поле данных» или вручную. Разумеется, в первую очередь для вставки доступны поля того документа, который в настоящий момент «строится» для показа на странице по шаблону. Однако, с помощью специального атрибута (рекурсии) можно дать системе указание искать нужное поле с заданным алиасом, поднимаясь «вверх» по дереву документов, пока не будет найдено подходящее. Ярким примером применения данной опции служит вывод всевозможных «глобальных» данных сайта, которые по довольно распространенной практике являются полями документа «главная страница сайта», взять хотя бы название сайта, составляющее в любой странице вместе с заголовком самой страницы содержимое тэга <title>.

Окно вставки поля данных в шаблон страницы Umbraco

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

Макросы

Макросами в терминах Умбрако называются именованные фрагменты кода, выполняющие различные функции по выводу информации, а также по ее вводу, сохранению и обработке.

Модель данных времени выполнения

Чуть более подробно остановимся на доступе к данным во время выполнения. Во-первых, конечно же можно осуществлять непосредственный доступ к документам из хранилища БД, используя Umbraco documents API. С помощью этого интерфейса можно как получать доступ к свойствам уже сохраненных документов с целью их показа на страницах, так и редактировать свойства документов, и создавать новые документы, сохраняя их. Для этого нужно создать свой ascx-контрол, который может в принципе и не генерировать никакого вывода в выходной поток, и поместить весь написанный код в его code-behind файл, и либо свою скомпилированную сборку поместить в каталог bin своего сайта, либо положить исходный файл code-behind прямо в папку App_Code. Сам файл контрола ascx помещается в специальную папку usercontrols в корневом каталоге сайта, или в любую из подпапок внутри usercontrols.

XML-кэш и работа с ним

Самый большой процент задач связан с доступом к сохраненным данным только на чтение. Здесь мы подходим к основному принципу доступа к данным в Умбрако. Во время выполнения все опубликованные документы на сайте доступны в виде кэша, представленного единым XML-деревом содержимого, в котором соблюдена полная иерархия документов, такая, какую мы можем видеть в центре администрирования. Также в дереве представлены все свойства каждого документа, включая как набор «системных» свойств, таких как идентификатор документа или даты его создания и обновления, так и свойства, созданные разработчиками сайта.

NodeFactory

Первым в ряду методов доступа к глобальному кэшу документов мы упомянем еще один API - так называемый NodeFactory. Он предоставляет собой строго-типизированную C#-библиотеку, осуществляющую быстрый доступ только на чтение к кэшированным документам.

XSLT и Razor

Самым распространенным и ходовым методом разработки сайтов на Umbraco стало построение макросов и трансформация данных из XML-кэша через скрипты на языке трансформации XSL. Поскольку все вопросы работы с XSLT-макросами освещены в отдельной статье, здесь кратко отметим лишь основные положения:

  • В такие макросы, как и во все остальные можно передавать параметры.
  • Параметром, передаваемым по-умолчанию является текущий узел XML-документа (currentPage), разный в зависимости от текущего местоположения на сайте. От этого узла далее по осям навигации Xpath можно построить пути до любого узла дерева.
  • В макросах, написанных на XSLT-трансформациях, доступны библиотеки расширений (XSLT-Extensions), методы которых могут быть вызваны для осуществления различных нетривиальных операций - от обработки параметров строки URL до отправки почты прямо из тела макроса.
  • Результатом исполнения такого рода макросов как правило являются результирующие фрагменты разметки HTML для помещения в поток вывода при формировании страницы, поэтому эти результаты могут быть закэшированы с неким указанным «времением жизни», что способно существенно повысит производительность.

В последних версиях Умбрако произошло следующее архитектурное изменение: аппарат рендеринга макросов вынесен в отдельный класс подключаемых блоков кода, именуемых Macro Engines. XSL - теперь лишь один из «движков» в помощь разработчику веб-сайта.

Вторым и стремительно набирающим обороты способом разработки сайтов на Умбрако стал так называемый Razor-движок - аппарат, позволяющий строить макросы на технологии Razor View Engine от Microsoft, которому во время выполнения также доступны данные кэша опубликованных документов Умбрако, однако это уже не фрагменты XML-дерева, а днамически построенные на их основе объекты документов, с которыми можно работать как с коллекциями, применяя все «вкусности» технологии LINQ. Для этой темы мы заготовили отдельную статью.

Регистрация макросов и параметров

Окно параметров макроса в Umbraco

Зарегистрировать макрос в системе можно в дереве «макросы» в модуле «Для разработчиков». Макросу, как почти любой сущности в системе, дается человеко-читаемое название, присваивается псевдоним-alias для обращения в программном коде, а также ставится в соответствие программный код, реализованный одним из ранее рассмотренных способов. Далее возможно указать системе параметры кэширования результатов работы макроса, и на отдельной вкладке управлять списком параметров.

Параметры и кэширование макросов

Отдельно рассмотрим вопросы передачи параметров в макросы, а также кэширование результатов работы макросов.

Как уже говорилось, в макросы можно передавать параметры. К макросам на «скриптовых» движках списки параметров нужно редактировать вручную через специальный интерфейс панели администрирования, макросы же, выполненные как ascx-контролы, способны отдавать информацию о своих параметрах автоматически, для чего все параметры в коде нужно оформить как публичные свойства класса, а затем при регистрации макроса получить о них все данные, нажав на специальную кнопку «Browse properties».

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

  1. [#propertyAlias] - передаст в макрос значение поля propertyAlias из текущего документа
  2. [$propertyAlias] - передаст в макрос значение поля propertyAlias, пытаясь найти его рекурсивно от текущего документа у всех предков «вверх по дереву»
  3. [@requestParam] - передаст значение requestParam из коллекции Request (там могут быть и значения, переданные по GET чероез строку URL, и поля формы, например).
  4. [%cookieName] - передаст значение cookie с именем cookieName. Из-за до сих пор неисправленного бага пункт 4, к сожалению, не работает как документировано.

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

<umbraco:macro alias="myMacro" myParam="[#fromEmail],[$sysFromEmail],address not configured" runat="server"/>

Расширенный синтаксис передачи параметров в макросы рассмотрен столь подробно еще и потому, что его применение напрямую связано с кэшированием результатов выполнения макросов. Дело в том, что для сохранения результата работы макроса в коллекцию кэша строится уникальный ключ, который включает в себя кроме идентификатора страницы и алиаса макроса, еще и все передаваемые параметры с их алиасами и значениями. Таким образом, с помощью данного синтаксиса можно очень гибко управлять кэшем макросов, вплоть до ситуации, когда какой-то из параметров реально внутри макроса нам не интересен, но его можно зарегистрировать и передавать в тэге лишь для того, чтобы для разных значений параметра создавались различные ключи и соответственно разные копии результатов работы макроса.

Реальный пример - передача параметра «текущая страница» в макрос, реализующий отрисовку пейджера - списка ссылок на постранично разбитую коллекцию докуметов. Несмотря на наличие в библиотеке расширений XSLT методов работы с параметрами строки URL, передавать номер текущей страницы лучше всего через параметр макроса и конструкцию [@page] в нем, что позволит кэшировать макрос пейджера на каждой странице. Здесь стоит отметить, что ликвидация всех багов, связанных впрямую с ключами кэширования макросов, полностью была закончена только к последним версиям Umbraco, так что настоятельно рекомендуем пользоваться самой новой на сей момент  (4.7).

Медиа-материалы

Хранилище медиа-материалов в Умбрако реализовано с точки зрения административного центра в виде все того же дерева, в которое можно добавлять различные виды материалов. В поставке изначально их три вида: изображение, файл/документ и папка - для предоставления возможности организации вложенных упорядоченных каталогов. Однако, поскольку весь механизм работы с медиа-материалами построен ровно на тех же принципах, что и работа с документами и типами данных в них, можно с легкостью как модифицировать имеющиеся типы медиа-данных, так и создать свои под любые нужды. Примером весьма показательным может служить пакет расширения PhotoMetaData для добавления фотографий с поддержкой полного спектра мета-информации о снимках, которую библиотека пакета помещает в дополнительные свойства, добавляемые по желанию пользователем к типу данных «изображение».

Внутри системы сами файлы, добавленные в медиа-библиотеку, хранятся в специальной папке media непосредственно в виде файлов, а в БД хранятся только дескрипторы и вышеупомянутые свойства. Для изображений еще отдельно создаются «иконки» уменьшенного размера (100 пикселей по максимальной из сторон). Решить вопрос с созданием на лету при загрузке изображений «иконок» другого размера можно, отредактировав стандартный тип данных «Upload», в котором есть специальное поле, где можно через точку с запятой перечислить все нужные размеры уменьшенных копий изображения. Отдельно заметим, что это поведение не системы в целом, а конкретно типа данных «Upload», поэтому при массовой загрузке изображений в медиа-библиотеку с помощью каких-либо внешних пакетов расширений, не использующих этот тип данных, не стоит ожидать описанного поведения по созданию «иконок» на лету.

Доступ к медиа-данным во время выполнения осуществляется через API, который доступен при всех способах создания макросов, включая, разумеется, и XSLT.

Многоязычность и словарь

В разделе дерева установок есть пункт «языки». Там можно (и нужно) добавить из прилагаемого списка культур нужные Вам для Вашего варианта сайта языки. Во-первых, как уже отмечалось в наших статьях, это позволит системе более правильно относиться к локализованным данным и форматам, а во-вторых, появится возможность использовать такой нужный при разработке многоязычных сайтов аппарат системы Умбрако, как словарь.

Суть его предельно проста: в него можно добавлять неограниченное количество именованных словарных статей (для удобства можно делать их вложенными), при редактировании которых будет выведено нужное количество текстовых полей согласно установленным языкам. Если заполнить все поля статьи переводом текста на все нужные языки, то во время выполнения с помощью специальной функции API можно выбирать статью по заданному имени (ключу), и выводить разный текст статьи при генерации страницы, делая ее таким образом мультиязычной.

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

Пользователи сайта, посетители (участники) сайта и регистрация

В системе Умбрако, в отличие от многих иных, существует четкое разделение людей, работающих с сайтом на пользователей (users) и участников (members). Разделение это не только «идеологическое», но и архитектурное, и техническое.

Первые - это администраторы, редакторы и разработчики сайта разного уровня привилегий и доступа. Они имеют свой логин и пароль для входа в административный бэк-энд сайта, а также роль, назначаемую из списка имеющихся встроенных ролей. При создании пользователям можно назначить язык, на котором им будет предоставляться интерфейс администрирования (из имеющихся штатно языков или добавляемых путем скачивания и загрузки языковых файлов). Также любому пользователю можно ограничить видимость основных разделов системы, отметив только нужные чек-боксы в списке, а равно и ограничить доступ к содержимому и медиа-библиотеке, задав узлы обоих деревьев, которые после этого станут для данного пользователя корневыми. Данные о пользователях хранятся в отдельной таблице БД, обособлено от данных посетителей (участников) сайта.

Редактирование пользователя административной части Umbraco

Вторые - это в сущности регистрируемые посетители фронт-энда сайта, если сайт поддерживает работу с регистрацией посетителей. Слишком подробно останавливаться на этой теме в данной статье не будем, отметим лишь, что все здесь организовано через стандартный аппарат .NET Membership Provider-ов, причем при использовании поставляемого в комплекте провайдера по-умолчанию, идеология работы с полями «личных карточек» участников максимально напоминает работу со свойствами типов документов и медиа-материалов - все процессы в едином стиле. Да и хранятся дополнительные свойства посетителей в том же мета-хранилище, что и все остальные свойства документов. Остается только добавить список созданных свойств согласно документации Microsoft по работе с membership-провайдерами в главный конфигурационный файл проекта. Во время выполнения .NET framework-ом будет сгенерирован класс-наследник общего профиля посетителя со всеми свойствами, либо Вы можете создать такой класс вручную, опять же руководствуясь документацией по .NET. А далее к Вашим услугам API по работе с участниками для манипуляций внутри своих макросов.

следующая статья: Использование Razor при разработке сайтов на Umbraco