Белорусская CMS с использованием Lua

В рамках проектов Robodile и IGD разработана новая разновидность системы управления контентом Kion CMS+L, в которой миграция данных, структур данных и сценарии по их обработке реализуются за счет использования языка Lua. Для этих целей были написаны трансляторы из Lua в PHP/JavaScript и обратно. Помимо этого предусмотрено множество дополнительных возможностей.

Kion CMS+L — это разновидность Kion CMS с поддержкой Lua. Kion CMS является высокопроизводительной системой управления контентом, написанной на стандартной связке: PHP/MySQL/CSS/JavaScript(jQuery). Вариант с использованием Lua предполагает дополнительные возможности по сериализации данных, их последующей обработке на сервере и/или клиенте, написанию сценариев действий.

Важно понимать, что язык Lua в рамках Kion CMS+L не используется в своем классическом представлении, которое вы можете сейчас встретить в разработках компьютерных игр и десктопных/серверных приложений. В Kion CMS+L используется только синтаксис Lua и типы данных плюс специфика работы с ними. Об использовании интерпретатора и компилятора уровня LuaJIT речь не идет.

Для интеграции Lua в Kion CMS достаточно подключить два файла: kion_lua.php и kion_lua.js. Эти файлы позволяют работать с Lua-кодом соответственно в PHP и JavaScript.

Зачем это нужно?

  1. Хранение и миграция структур данных (без SQL).
  2. Написание сценариев обработки данных. Миграция методов обработки данных.
  3. Шифрование/дешифрование данных.
  4. Синхронизация данных.
  5. Расширенные возможности клиентской части за счет интеграции Lua и JavaScript.

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

Если говорить о работе со структурами данных, то встраивание Lua можно сравнить с использованием YAML, который хорошо знаком программистам Symfony, а также с JSON. Но при этом в самом файле сценария (Lua-файле) вы можете не только хранить данные, но и прописывать условия их обработки.

Язык Lua очень удобен и прост в программировании, является С-подобным, имеет ряд уникальных особенностей. Одна из них — это тип данных table, который подразумевает, по существу, ассоциативные массивы с данными гетерогенного типа. В качестве ключей и значений элементов могут выступать любые типы данных (в т.ч. другие таблицы, функции, которые в данном языке также являются отдельным типом и т.п.), кроме nil (неопределенный тип).

Также на уровне Lua вы можете производить взаимодействие с другими Lua-файлами (импорт), таким образом можно собирать более сложные структуры.

Для демонстрации того, как это работает, покажем несколько внутренних механизмов Kion CMS+L.

Базовые функции трансляции и выборки

Для трансляции/перемещения кода без шифрования предусмотрено семь базовых функций:

  • lua_add(data, tablename); - для PHP и JS.
  • lua_add_to_file(data, tablename, filename); - для PHP и JS.
  • lua_parse(variablename); - для PHP и JS.
  • lua_parse_file(filename); - для PHP и JS.
  • lua_get_element(elementname, variablename); - для PHP и JS.
  • lua_get_element_from_file(elementname, filename); - для PHP и JS.
  • lua_delete_file(filename); - только для PHP.

Преобразование данных из PHP и JavaScript в Lua-строку производится с помощью функции lua_add(data, tablename), в которой может использоваться два входящих аргумента — переносимый массив с данными и имя таблицы(массива), в которую эти данные помещаются. Приведем пример для PHP:

$lua_array = array("foo" => "bar");

$lua=lua_add($lua_array, ‘larr’);

Сформированная Lua-строка после преобразования будет иметь вид:

larr={foo=”bar”}

Функцию lua_add() можно использовать бесконечное число раз, добавляя или модифицируя данные:

$lua_array = array("bar" => "foo");

$lua=lua_add($lua_array, ‘larr’);

Сформированная/преобразованная lua-строка будет выглядеть:

larr={foo=”bar”, bar=”foo”}

Если элемент указанного массива с соответствующим ключом уже существует, его значение при использовании lua_add() переписывается.

Если вы передаете пустое значение, соответствующий элемент массива (таблицы) автоматически удаляется.

$lua_array = array("foo" => "");

$lua=lua_add($lua_array, ‘larr’);

В результате lua-строка преобразуется в:

larr={bar=”foo”}

Функция lua_add_to_file(data, tablename, filename) работает аналогично lua_add(), только запись данных производится в указанный lua-файл (кодировка UTF-8). Имеет три входящих аргумента (требуемые к переносу данные, имя таблицы(массива), в которую эти данные помещаются, и имя файла). Вызов выглядит так:

lua_add_to_file($lua_array, ‘larr’, 'lua_data.lua');

В качестве имени файла можно указать адрес url, начинающийся с «http://» или «https://».

Для случаев изменения значений существующих элементов таблиц, а также удаления этих элементов функция работает идентично lua_add().

Для обратной операции в PHP и JavaScript используются две функции: lua_parse(variablename) и lua_parse_file(filename). Обратное преобразование подразумевает непосредственно трансляцию структуры данных и функций (в случае файла) из Lua в PHP или в JavaScript, в зависимости от того, откуда оно вызывается.

Для функции lua_parse_file(filename) в качестве имени файла можно указать адрес url, начинающийся с «http://» или «https://».

Для получения определенных элементов из таблиц используются две функции lua_get_element(variablename, elementname) и lua_get_element_from_file(elementname, filename).

Первая из них читает данные из строки, в аргументах указываются: конкретно элемент, который нужно заполучить и имя переменной, содержащей lua-строку. Пример для PHP:

$lua_array = array("foo" => "bar");

$lua=lua_add($lua_array, ‘larr’);

$lua_v1= lua_get_element(larr, $lua) //заберет весь массив из таблицы larr в строке $lua

$lua_v2= lua_get_element(larr[“foo”], $lua) //заберет значение элемента larr[“foo”] в строке $lua

Как видите, данная функция очень удобна, то есть она может забирать не только конкретные значения, но и массивы. Если в larr[“foo”] будут содержаться элементы следующего уровня, например, larr[“foo”] [1], larr[“foo”] [2] и т.п., то, соответственно, в переменную $lua_v2 загрузится опять же массив. 

Функция lua_get_element_from_file(elementname, filename) работает аналогично, с той лишь разницей, что в качестве второго аргумента нужно указать не имя переменной, содержащей строку, а название файла или его url, начинающийся с «http://» или «https://».

Шифрование данных

В рамках Kion CMS+L может использоваться обратимое шифрование данных ключом, соответственно, для этого разработаны специальные функции, аналогичные описанным выше, но имеющими префикс «s» в наименовании, и в них добавлен еще один аргумент — ключ шифрования:

  • slua_add(key, data, tablename); - для PHP и JS.
  • slua_add_to_file(key, data, tablename, filename); - только для PHP.
  • slua_parse(key, variablename); - для PHP и JS.
  • slua_parse_file(key, filename); - для PHP и JS.
  • slua_get_element(key, elementname, variablename); - для PHP и JS.
  • slua_get_element_from_file(key, elementname, filename); - для PHP и JS.

Алгоритмов шифрования предусмотрено всего пять, включая Blowfish. Переключение между ними производится в настройках kion_lua.php и kion_lua.js.

Синхронизация данных

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

  • lua_sync_files (filename1, filename2)
  • slua_sync_files (key, filename1, filename2)
  • lua_sync_batch (filename1, filename2, depth)
  • slua_sync_batch (key, filename1, filename2, depth)

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

Что касается имен файлов, то подойдут как обычные относительные ссылки, так и url, начинающиеся с «http://» или «https://».

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

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

lua_sync_files (‘/data1.lua’, ‘http://sitename.ru/luascripts/data1.lua’);//изменили файл данных на втором сервере

lua_sync_files (‘/picture1.jpg’, ‘http://sitename.ru/images/picture1.jpg’);//загрузили картинку на второй сервер

Если имена файлов одинаковы, и таких много, вы можете использовать две функции пакетной обработки — lua_sync_batch() и slua_sync_batch(). Для этого достаточно поставить «*» в имени вместо тех символов, которые меняются. Также добавлен еще один аргумент — глубина сканирования, который указывается в цифрах. Если указан 0, то вложенные папки относительно указанных файлов не сканируются, сверка идет только в узлах, где эти файлы расположены, 1 — сканируются и дочерние папки. Если с одной из сторон какой-либо файл отсутствует, с другой копируется имеющийся.

Пример:

lua_sync_batch (‘/*.lua’, ‘http://sitename.ru/luascripts/*.lua’, 0);

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

Таймлайн

На данный момент Kion CMS+L тестируется на коммерческих проектах, в будущем планируется выложить файлы интеграции в свободный доступ.

Владимир Бодов a.k.a. Кристофер

www.robodile.com

Версия для печатиВерсия для печати

Рубрики: 

  • 1
  • 2
  • 3
  • 4
  • 5
Всего голосов: 0
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя savely

Нда, настало время, когда в статье вроде как про программирование я вижу кучу новых слов. Ну, и вообще в статьях по IT, кстати. 

Мысль в том, что выросло IT. В полноценную отрасль, где не может быть универсалов. 

Аватар пользователя igd

Ну, сама идея использовать Lua была не спроста. Был запрос от немцев, им нужно было разработать безопасную CRM с многосайтовостью. То есть, много форм, которые размещаются на разных сайтах и даже разных CMS, но они имеют прямой и обратный траффик по лидам, сделкам и т.п. Я уже тогда подумал о Lua. Потом один сайт, который базируется на моей CMS, попросил синхронизацию с другим сайтом в другом регионе (на другом сервере и на другом сайте). В июне я начал писать синхронизатор, в ноябре были сделаны трансляторы Lua->PHP/JS и обратно. Почему был выбран именно Lua, а не С? Lua имеет динамическое приведение типов, то есть, он ближе к PHP и JavaScript, и может стать универсальным мостом, что и получилось. Все тесты - за:)

Аватар пользователя leo3

igd - на страничке http://www.igd.by/about/ нужно исправить забавную и двусмысленную  очепятку "покупки придуктов Битрикс с 40% скидкой":) DNA для вашего веб-бизнеса - хороший слоган. Про необходимость lua, признаюсь, не понял ничего, но готов согласиться с авторитетом:)