Pull to refresh

Гибкая cms для смелых проектов

Reading time 14 min
Views 17K
В этой статье мы расскажем о невероятно гибкой системе управления сайтом – Boolive, сочетающей в себе мощь и простоту.

Система для создания и управления сайтами Boolive объединяет лучшие качества модульности, универсальности и гибкости. Программистов избавит от рутинных операций, сосредоточит на полезном программировании. Средствами раздела администрирования позволит создать любую структуру данных, настроить правила работы, создать сайт в точном соответствии с требованиями. Чтобы вы не делали, всё доступно для повторного использования. Для менеджеров, администраторов, редакторов, программистов сайта – для всех система старается быть простой с интуитивно понятным красивым интерфейсом.

Фундамент гибкости – две иерархии


Идея проекта Boolive обретала чёткие очертания на протяжении нескольких лет в экспериментах, из практических применений и в увлекательных дискуссиях с разносторонними личностями.

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

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



Объект – это совокупность данных и логики. У каждого объекта есть своё имя, значение и логика. Сами по себе объекты примитивны. Но у них могут быть подчиненные объекты, которыми образуется иерархия. Подчинённые объекты используются как свойства родительского объекта или просто для образования вложенной структуры.



Так как объекты выстраиваются в иерархию, у них появляется адрес – URI. Фактически как путь к файлу. Адрес используется для обращения к объекту, в том числе и в строке браузера. Адрес – основной идентификатор объекта.

Свобода и легкость создания новых объектов приведет к дублированию уже ранее созданных объектов. Утомительно повторять однотипные операции создания сложных объектов – состоящих из нескольких подчиненных. Вручную нужно соблюдать единство структуры, именования, логики однотипных объектов. Для разрешения этой утомительной сложности применяется прототипирование. Это самая главная особенность системы. Новые объекты создаются на основе существующих. Иными словами один объект наследует значение, логику и структуру другого объекта. При этом может переопределять себе значение, логику и иметь новых подчиненных или удалять унаследованных. Прототипирование оптимизирует создание сложных объектов, даёт возможность повторного использования. Кроме того, любой объект можно доработать под свои задачи без порчи существующих объектов, ориентированных на иные задачи, сохраняя обратную связь для обновлений. Объекты сохраняют связь со своим прототипом.



Каждый объект одновременно находится в двух иерархиях – в иерархии структуры и в иерархии наследования. Всего две иерархии образуют удивительную гибкость для создания сложных структур данных. Если нужно связать один объект с другим, например, статью связать с пользователем, то используется прототипирование. В подчинение добавляется новый объект, прототипом для него будет тот объект, с которым нужна связь.



Возможность создания новых объектов на основе существующих подсказывает о существовании библиотеки объектов. Это ветвь иерархии сайта, в которой хранятся объекты для повторного применения. Повторно применить можно любой объект, где бы он не находился, но библиотека – это коллекция разнообразных заготовок и полностью готовых объектов для создания из них сайта. Можно формировать свою библиотеку или пакет с объектами под конкретный проект. Свои эталоны публикаций, товара, пользователя, виджеты, готовые сайты и всё, что угодно.

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

Гибкость в деле


Необычная админка

Знакомство начнём с раздела администрирования (админки). Основная задача админки – предоставить доступ к любому объекту сайта с учётом прав пользователя и выполнить необходимые операции с объектом – создать, изменить, удалить. Смысл в админке в удобном графическом интерфейсе, в оптимизации работы над сайтом. Для неопытных пользователей нужно показать привычные элементы интерфейса. Для продвинутых раскрыть всю гибкость системы.



Работа в админке начинается с перехода к нужному объекту, например, к странице для последующего её редактирования. В центральной области отображается текущий объект с его подчиненным, можно зайти внутрь них. Сверху имеется меню пути (адреса) текущего объекта для быстрых возвратов назад. В левой части отображаются закладки для быстрых переходов к часто используемым объектам. Закладку можно добавить в любой момент на любой объект.

Так как сведений об объекте достаточно много, чтобы поместить их на один экран, в нижнем меню выбирается, что именно об объекте нас интересует. Чаще всего – это структура объекта или его свойства. Для продвинутых пользователей полезны будут логика, значение объекта, а также просмотр прототипов и наследников объекта. При обращении к объекту по умолчанию отображается структура.

Третий вид навигации – функции, выполняемые над объектами. Меню функций расположено в правой части админки. Основные функции – просмотр объекта, добавление новых, удаление и смена признаков. Доступные функции зависят от выделенного объекта, от выбранных сведений и некоторых других состояний в админке, например, сколько объектов одновременно выделено в списке, в том числе и от прав доступа. Набор функций легко расширяется. Можно добавлять свои обозреватели, редакторы объектов, назначая их на определённые типы объектов или другие условия работы. С их помощью админка наделяется более специфичными функциями, затачивается под удобства конкретного проекта. Можно провести аналогию: раздел администрирования как операционная система, объекты сайта как файлы, а функции как программы.

Выходит, если нам нужно отредактировать существующую страницу, мы переходим в содержимое, находим там страницу, переходим в неё и редактируем её. Должно быть просто!

Содержимое – предметная область проекта

К содержимому относится всё, что предполагается публиковать на сайте. Например: статьи, новости, разделы, товар, фотографии или специфичный для проекта тип содержимого. Обычно, мы имеем дело со страницами и разделами. В иерархии сайта есть специальный раздел «Содержимое» для хранения публикаций. Но это не значит, что только в нём можно хранить страницы сайта. Раздел заранее сделан только для удобства и оптимизации, чтобы не выполнять поиск по всей иерархии.

Чтобы добавить новую страницу, нужно для начала перейти в раздел «Содержимое». Можно перейти в страницу или подраздел, если новую страницу нужно добавить внутри них. После перехода в правом меню выбираем функцию «Добавить». В списке быстрого выбора уже предлагается страница. Но мы можем выбрать любой другой объект сайта. После добавления страница оказывается с признаком «Черновик». Рекомендуется сначала отредактировать страницу – полностью подготовить её для публикации, только потом убрать признак черновик.



Теперь пощупаем гибкость. К странице добавим ещё одно свойство текста. Находясь в редакторе страницы, для примера добавляем «Из библиотеки» из пакета «Простые» объект «HTML Текст». При нажатии на «Добавить» появится окно выбор объекта. Для выбора доступны все объекты сайта, но нам нужен текст, который есть в библиотеке.



Новый текст появится в редакторе и отобразится на странице сайта в соответствии со своим порядком.



В данном примере дополнительное свойство «текст» добавлено только одной странице. Если нужно всем страницам сайта иметь дополнительное свойство, то проще изменить прототип или создать свой и использовать его.

Под проект лучше создавать пакет в библиотеке, и коллекционировать в нём прототипы со спецификой проекта. Например, для сайта салона автомобилей создать объект «автомобиль», сразу определив все необходимые свойства автомобиля, а перед этим создать прототипы «Тип кузова», «Производитель» и многие другие, чтобы использовать их в самом автомобиле. Таким способом создаются прототипы под предметную область проекта. В раздел «Содержимое» уже добавляются непосредственно автомобили салона, списки производителей и так далее. Заметьте, что к «автомобилю» мы можем добавлять не только простые свойства – «текст», «число», но и сложные – любые объекты сайта и образовывать сложные структуры! Свойства, которые помечены как обязательные, сразу появляются у новых объектов. Если свойство необязательное, то оно доступно в качестве дополнения, т.е. его можно добавить позже при желании.

Виджеты отобразят всё

Для отображения сайта в браузере используются виджеты. Виджет – это объект с функцией отображения, возвращающей HTML код. Виджет может сам по себе что-то отобразить, какую-то статическую информацию, быть элементом оформления, отобразить определенный объект, например, новость, а также отобразить внутри себя подчиненные виджеты.

Из виджетов выстраивается ветвь иерархии в разделе «Интерфейс». Виджетами полностью определяется представление и динамика сайта в браузере. Корневым виджетом выводится базовая структура HTML документа. В область body вставляется результат отображения его подчиненного виджета, им задаётся разметка сайта, например шапка, боковые панели, подвал, центр. В каждую область вставляются подчиненные виджеты, и так далее. Это типовая структура, возможны разные варианты, можно одним виджетом показать весь сайт, но знайте – гибкость в детализации.



У виджетов есть функция условия работы, если она возвращает true, то виджет работает, иначе нет. В функции проверяются входящих данные, настройки или состояние системы. Виджет можно настроить на работу по определенному адресу, например, админка работает, если адрес начинается с /admin. Виджет не будет работать, если он в черновике или нет доступа к нему. Можно запрограммировать любое условие, например, работать только в ночное время, проверять тип отображаемого объекта, сверять параметры запроса. Большинство условий можно задать правилом на входящие данные.

При работе с виджетом в админке полезными будут режимы «Логика» и «Значение» для редактирования соответственно логики виджета и его шаблона. Логика – это файл с php классом, как у всех объектов. Шаблон – это значение виджета в виде файла, от расширения файла зависит тип шаблона. Логика и шаблон также доступны для редактирования в любимой IDE. Система Boolive сама выполняет рутинные операции создания файлов, нужно только в админке указать, что объекту нужна своя логика или свой шаблон. Файл класса с заготовкой самого класса будет создан автоматически. Останется только дополнить функцию новой логикой или переопределить другие функции.



Для создания интерфейса сайта проще использовать готовые виджеты из библиотеки, немного изменяя их шаблон, логику и стили. В библиотеке имеются виджеты навигации, виджеты содержимого, слайдеры, формы и будут появляться новые. Благодаря прототипированию виджет можно добавить в разные области сайта и каждый экземпляр по-своему настроить. Не просто настроить, а изменить логику, шаблон, стили, скрипты. В библиотеке также есть готовые макеты, фактически готовые сайты. Если в большинстве CMS выбираются темы оформления под «стандартный» макет, то в Boolive одним выбором простейший сайт превращается в портал. Взяв за основу готовый макет из библиотеки, вы сможете доработать его, получить свой макет без порчи оригинального.

Там где нужна универсальность необходимо использовать универсальные виджеты. Одним из таких является виджет содержимого в центральной области сайта. У виджета содержимого в подчинении имеются различные виджеты под конкретные объекты – виджет страницы, раздела, товара, пользователя. По очереди запускается каждый виджет, пока один из них не сработает. У всех есть условие работы – проверка, наследует ли отображаемый объект конкретный объект. В итоге, страница отобразится виджетом страницы, раздел виджетом раздела. Можно сделать уникальное отображение для конкретной страницы.

Для отображения свойств объекта тоже применима автоматизация. Примерами являются виджеты страницы, раздела, меню, слайдер и многие другие, особенно в админке. Этими виджетами выбираются свойства объекта и для каждого свойства подбирается виджет из списка.

Благодаря универсальности мы можем в страницу вставить любой объект, даже виджет. Этому есть практическое применение – создание форм обратной связи, авторизации, калькуляторов. Сначала создаём виджет «Калькулятор», а потом вставляем его в текст любой страницы. Ещё интересный пример универсальности – отображение фотографий в слайдере (карусели). Вместо фотографии в список слайдов можно добавить страницу. Самое важное, что это не будет хаком, мы сохраняем удобства редактирования страницы в слайдах.

Обработка любого запроса

Система Boolive имеет единственную точку входа – файл index.php. С него начинается обработка всех запросов – запускается работа сайта. Выбирается корневой объект сайта и вызывается его функция start().Тот в свою очередь запускает объект Интерфейс, мы его видим при входе в админку. Интерфейс по очереди запускает всех своих подчиненных. Как в итоге будет обработан запрос, зависит от структуры Интерфейса.



В Интерфейсе, мы уже знаем, располагается иерархия виджетов (виджет HTML разметка). Большинство запросов именно она обрабатывает, возвращая клиенту HTML документ. Кроме виджетов в интерфейсе есть другие обработчики, каждый из них запускается при соблюдении своих условий работы. Например, обработчик RESTful сработает, если в заголовке запроса указан формат ответа – JSON. Обработчик форм сработает, если указан параметр адреса формы, которая принимает запрос. С легкостью можно добавить свой обработчик, например для интеграции с внешними системами. Интерфейс запускает по очереди всех своих подчиненных, но так как у всех свои условия работы – выполнится только один. Дальше процесс зависит от самих обработчиков.



Гибкая настройка прав пользователей и групп

Гибкость модели данных распространилась и на структурирование пользователей. Можно создавать группы пользователей, группы в группах, в них добавлять пользователей. Система не запретит пользователя добавить внутрь другого пользователя, если это вдруг нужно для уникальных функций сайта. Естественно, у пользователя могут быть любые свойства в его профиле. Администраторам сайта остается определиться, что запретить или разрешить пользователям.

У пользователей и групп есть свойство «Права доступа».



Для структурирования прав используются роли. В «Роль» добавляются объекты «действия», например, «чтение», «запись». Можно добавлять свои действия – это обычный объект, имя которого соответствует названию действия. Действия могут иметь вложенные действия, например, изменение значения объекта, логики объекта, исполнение функций объекта. Запретив запись, нельзя будет ни создавать, не изменять объект. В действия добавляются объекты условий. Их задача возвратить условие, при котором соответствующее действие можно или нельзя выполнять. Сейчас используются два вида условия – «Допуск» и «Запрет», соответственно, допуском определяется, на какие объекты есть право совершать действие, а запретом, на какие нет. Именно в условиях сосредоточена гибкость определения прав, так как условием может быть всё что угодно. Можно просто сверить идентификаторы объектов, входят ли они в список тех, что у объектов, которые в подчинении объекта допуска. Можно проверять наследование, родителей, подчиненных, авторство, просто сверить атрибуты, например, значения объектов. Можно в обще объекты не трогать, а определять допуск по состоянию системы, например по времени. В общем, объект условия возвращает условие на языке запросов к базе данных (о нём ниже)

Проверка в программном коде:

// Проверка доступа на изменение значения объекта
if ($object->isAccessible('write/change/value'){
    echo 'Доступ на изменение значения объекта имеется';
}
// Права пользователя – полное условие, которым можно 
// проверить объект или применить его для поиска объектов
$cond = $user->getAccessCond('write/change');

Права самого пользователя дополняются правами всех групп, в которых он состоит. Объединение прав – это объединение условий логическими операциями «И», «ИЛИ», так, чтобы права вложенной группы или пользователя имели приоритет над родительской группой. Корневой группе можно установить запрет на всё, а вложенным группам или пользователям указывать, что им разрешается. Допустимо наоборот, сначала все разрешить, потом точечно запрещать.

Где объекты? Везде! Хранилища данных

При работе с объектами на уровне программного кода – при сохранении, удалении или их поиске, мы не заботимся о том, где реально объекты хранится, в какой СУБД. Работа с объектами полностью абстрагирована от СУБД. Мы обращаемся к модулю данных, тот уже сам понимает по конфигурации, в каком хранилище должен быть объект и обращается к модулю соответствующего хранилища, например к MySQLStrore.php. Для хранения объектов сайта могут использоваться несколько хранилищ, причём разного типа. Хранилище определяется по URI объекта.

Мы проводили интересные эксперименты с внешним хранилищем HTTPStrore.php. Если URI объекта начинается с «http:», то работает именно оно. Выполняются HTTP REST запросы к другому сайту, и если сайт тоже на Boolive 2, то получаем желаемый результат. Да, система позволяет прототипировать объекты между сайтами!

Так как работа с данными абстрагирована от конкретной СУБД, да ещё и запросы на выборку могут ходить по сети, то использовать SQL мы просто напросто не можем. Нужен язык запросов, с одной стороны понятный и отвечающий особенностям прототипной модели данных, с другой стороны легко структурируемый, чтобы его можно было представить строкой в URL или в массивах PHP и быстро конвертировать между форматами.

Запрос на массивах

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

$cond = array(
    'from' => '/Contents/news',                  // Выбор объектов из /Contents/news
    'depth' => 3,                                // Глубина выбора из from.
    'select' => 'children',                      // Что выбирать? self, children, tree, heirs, parents, protos
    'where' => array(                            // Условия выборки объединенные логическим AND
        array('attr', 'uri', '=', '?'),          // Сравнение атрибута
        array('not', array(                      // Отрицание всех условий
            array('attr', 'value', '=', '%?%')
        )),
        array('any', array(                      // Условия, объединенные логическим OR
            array('child', 'title', array(       // Условия на подчиненный объект title
                array('attr', 'value', '>', 10),
                array('attr', 'value', '<', 100),
            )),
            array('is', '/Library/basic/Number') // Кем объект является? Проверка прототипирования
        ))        
    ),
    'order' => array(                           // Сортировка
        array('uri', 'DESC'),                   // по атрибуту uri
        array('childname', 'value', 'ASC')      // по атрибуту value подчиненного с именем childname
    ),
    'limit' => array(10, 15),                   // Ограничение - выбирать с 10-го не более 15 объектов
    'key' => 'name',                            // Атрибут, который использовать для ключей массива результата
);

Запрос в URL формате

В URL формате параметр from сокращен – в итоге получается полноценный URL с указанием ресурса. Этот вариант полностью удовлетворяет RESTful и избавляет от придумывания его API для сложных выборок, хотя, об ограничениях тоже нужно думать.

$cond = "
   /Contents/news&
   depth=max&
   select=children&
   where=all(
       attr(uri,like,%25А%25)
       not(attr(value,eq,m))
       any(
           child(title,all(
               attr(value,gte,10)
               attr(value,lt,100)
           ))
           is(/Library/basic/Number)
       )       
   )&
   order=(uri,desc),(childname,value,asc)&
   limit=10,15
";

Работает так:

$result = Data::read($cond); // массив объектов
$result = Data::read("/Contents/news/news1"); // объект новости

На языке запроса описываются условия прав доступа пользователей, условия работы виджетов и другие условия. Проверить, соответствует ли выбранный ранее объект нужному условию можно программно без обращения к базе данных. А для хранилища не составляет труда структурированные условия конвертировать в свой язык, например в SQL.

Нет конфликтам в команде. Свои версии под своё дело

При установке системы или объектов сайта (читать модулей) не используются SQL дампы. Весь сайт со всеми данными экспортируется в *.info файлы JSON формата. Эти файлы используются при установке. Функция экспорта и установки объектов доступны в админке. В любой момент весь сайт можно экспортировать, перенести его файлы на другой сервер и установить. Это удобно для подготовки специальных версий систем для распространения или использования в студии под свои типовые проекты, но также для обмена модулями.

Использование info файлов решает проблему слияния баз данных от разных разработчиков при работе над сайтом или в командной разработке системы Boolive. Кроме того, данные в виде info файлов попадают в систему контроля версий и с её помощью разрешаются конфликты при объединении разных версий данных.



Если значением объекта является файл или у объекта своя логика или объект был экспортирован в info файл, то мы обнаружим папку под объект в файловой системе. Путь к папке совпадает с URI объекта. Структура папок в файловой системе совпадает со структурой данных сайта. Но не обязательно под каждый объект будет своя папка, даже если экспортирован весь сайт в info файлы. Потому что объекты-свойства не создают своего info файла, а компонуются в info файл своего родителя.

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

Ещё


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

Если не терпится посмотреть систему в действии, и вы затрудняетесь самостоятельно установить её, то обращайтесь лично ко мне.

Гитхаб: https://github.com/Boolive/Boolive
Промо: http://boolive.ru
Tags:
Hubs:
+19
Comments 67
Comments Comments 67

Articles