○○○○ ○○○○
○○○○○ ○○○○○○
○○○ ○○○
○○○○○○○ ○○○○○○○○○○○○○○ ○○○○○○○ ○○○○○○○ ○○ ○○○ ○○○○○○○
○○○○ ○○○○ ○○○○○○○○○○○○ ○○○ ○○○ ○○○ ○○○ ○○○ ○○○ ○○○
○○○ ○○○ ○○○ ○○○ ○○ ○○ ○○ ○○ ○○ ○○
○○○○○○○○○○○○○○ ○○○ ○○○ ○○ ○○ ○○ ○○ ○○○○○○○○○○○○○○
○○○ ○○○ ○○○ ○○ ○○ ○○ ○○ ○○
○○○○ ○○○○ ○○○ ○○○ ○○○ ○○○ ○○○ ○○○ ○○ ○○○ ○○○
○○○○○○○ ○○○ ○○○ ○○○○○○○ ○○○○○○○ ○○ ○○○○○○○
○○○○ ○○○○
○○○○ ○○○○EFFCORE — это мини-CMS (система управления содержимым) и мини-CMF (фреймворк управления содержимым) нового поколения. Была разработана в промежутке между 2016 и 2024 годам. Использует такие технологии как: HTML5, CSS3, IP v6, SVG, SMIL, UTF8, UTC, WAI-ARIA, NoSQL, Markdown, UML, Composer, Docker…
Может использоваться в качестве инструмента для создания простых веб-сайтов без необходимости программирования. Может использоваться в качестве инструмента для создания веб-порталов и веб-сервисов с необходимостью программирования дополнительного функционала или поиска готовых решений.
Название системы является акронимом и происходит от фразы effective core.
Система была разработана с нуля. Её главный принцип — отсутствие стороннего кода (для
исключения правовых претензий), а также отсутствие сторонних идей (для выработки
инновационных решений).
Стимулом для создания системы послужила массовая деградация в развитии Open Source проектов. Первая причина — это распределённая команда разработки. По своей сути — это группа лиц с различным уровнем квалификации, различными взглядами и слабым уровнем координации в таких проектах. Вторая причина — это непосредственно подход к разработке. Вместо интенсивного пути развития они выбрали экстенсивный. Интенсивный путь развития подразумевает разработку собственного кода и его тесную интеграцию с другими компонентами системы. Экстенсивный путь — это использование готовых библиотек и сборка этих библиотек в единое целое. При этом из каждой такой библиотеки задействуется лишь часть функционала. Каждая такая библиотека была создана для абстрактных целей. В результате объём кода растёт, нагрузка на оборудование растёт, количество ошибок растёт, надёжность и безопасность падает, а функционал увеличивает лишь незначительно.
Основной упор в системе сделан на получение максимальной производительности. Оценочным критерием является простое и понятное условие: система, установленная на хостинге с самым дешёвым тарифным планом, должна генерировать главную страницу за 0,01 секунду. Это позволит обслуживать одновременно до ~100 запросов в секунду. Тарифный план должен соответствовать минимальным требованиям установки и включать в себя такие базовые возможности как OPCache + JIT и твёрдотельный накопитель. Примерная стоимость тарифного плана должна варьироваться в пределах 3-5$ в месяц.
Любая страница в системе (кроме административного интерфейса) может иметь собственный макет с различным количеством регионов. Каждый регион может иметь любое количество различных блоков. Каждый блок — это любой элемент системы, имеющий блочное представление (меню, форма, текст, опрос и другие).
Интерфейс системы может быть переведён на любой язык. Система уже поставляется с некоторым числом переводов. Изменить язык интерфейса можно в любой момент времени при помощи раздела Управление → Локализации.
В свою очередь, любая страница (кроме административного интерфейса) может переопределить глобальные настройки и выбрать иной язык, что-бы соответствовать языку контента на этой странице. Настройка каждой страницы осуществляется в разделе Управление → Данные → Содержимое → Страницы.
В системе реализована более совершенная система "Plural".
Это система позволяет выполнить вставку любого контента из Вашей
функции в зависимости от значения переменной во фразе.
Пример: %%_number секунд%%_plural(number|a-ji) при number = 1
будет возвращать 1 секунда, а при number = 10
будет возвращать 10 секунд.
Организовать мультиязычный веб-сайт/веб-портал можно двумя способами:
http://example.com/EN/about);http://EN.example.com/about).Примечание: И первая и вторая версии требуют наличия дубликатов страниц и блоков на различных языках. Данный подход является оправданным т.к. часто разные языковые версии контента имеют отличия не только в содержании, но и в структуре. Например, главное меню на одной языковой версии может иметь одни пункты меню, а на другой — совсем иные — будут отличаться и названия этих пунктов и их адреса, и их количество.
В модуле "Профиль "Классический" Вы можете увидеть пример реализации мультиязычности по способу №1.
В системе нет такого понятия как тема оформления. Вместо тем используется особый вид модуля под названием "Профиль". Любой профиль может содержать следующие виды элементов:
*.tpl/*.data;*.css/*.cssd;*.js/*.jsd;robots.txt, sitemap.xml;Профиль устанавливается как обычный модуль.
Если в файле профиля module.data указать enabled: yes тогда он
появиться в списке профилей на странице установки системы.
При включении профиля он может как переопределить какие-либо настройки
оформления, так и не производить никаких изменений, а лишь добавлять
дополнительные возможности которые пользователь должен активировать
самостоятельно.
Располагать файлы профилей как и любых сторонних модулей следует
в директории modules. В ином случае все изменения могут быть утеряны
при обновлении — когда система будет приведена к эталонной копии из
репозитория.
Для работы с оформлением в административном интерфейсе системы имеется раздел Управление → Вид, который включает в себя следующие подразделы:
Все макеты, имеющиеся в системе (а также Выборки с типом оформления "Таблица (адаптивная)") уже способны адаптироваться к мобильной версии.
Интуитивно-понятное расположение файлов в системе позволяет определить их назначение, не прибегая к документации:
module_*/frontend располагается
всё необходимое для frontend-разработки;module_*/backend располагается
всё необходимое для backend-разработки;module_*/data располагаются
NoSQL-данные.Система имеет встроенный парсер и загрузчик классов.
Работа файлов не зависит от их расположения и при необходимости
все файлы будут найдены и обработаны если они располагаются
в директориях modules и system.
Размещение в файловой системе основных модулей системы, сторонних модулей и пакетов библиотек можно представить следующей схемой:
├─ modules
│ ├─ module_custom_0
│ ├─ module_custom_1 …
│ ├─ module_custom_N
│ │ ├─ backend
│ │ ├─ data
│ │ └─ frontend
│ └─ vendors
│ └─ packages
│ ├─ package_0
│ ├─ package_1 …
│ └─ package_N
└─ system
├─ module_0
├─ module_1 …
└─ module_N
├─ backend
├─ data
└─ frontendВносить изменения в директорию system нельзя, иначе при обновлении
системы её содержимое будет восстановлено до эталонной копии и все изменения
в ней будут утеряны.
Сторонние модули следует размещать в директории modules.
Пакеты библиотек следует размещать в директории modules\vendors\packages.
Информация о модулях и пакетах библиотек хранится в кэше поэтому
при изменении состояния их файлов, следует сбрасывать кэш.
Для сброса кэша необходимо перейти в административный интерфейс
в раздел Управление → Модули → Установить и нажать кнопку ↺.
Архитектура выполнена по классической схеме MVC. Хранение данных осуществляется в SQL и NoSQL-хранилищах. Для структурированных данных используется SQL-хранилище. Для неструктурированных данных (например, формы, цветовые профили, тесты, настройки модулей) используется NoSQL-хранилище. Описание SQL и NoSQL приводится в соответствующих разделах.
Система оперирует двумя типами классов:
Описание экземпляров классов-паттернов (будущих PHP-объектов) храниться в NoSQL. В момент выборки этого описания и происходит создание экземпляра (объекта).
Код системы следует принципу DRY (Don’t Repeat Yourself; с англ. — "не повторяйтесь") и KISS (Keep It Short and Simple; с англ. — "будьте краткими и простыми"). Каждый класс состоит из небольшого числа методов, состоящих из небольшого числа строк. Код адаптирован для повторного использования, а такой подход существенно облегчает восприятие кода.
Процесс разработки следует следующим правилам:
В разделе Разработка → Структуры → Диаграмма генерируется диаграмма классов, зарегистрированных в системе. Здесь же имеется и ссылка для загрузки этой диаграммы в виде JSON-файла, для программы StarUML. Данный раздел станет доступен после включения модуля "Разработка".
В разделе Разработка → Консоль можно включить отображение консоли для разработчиков. В консоли показывается порядок действий при генерации страницы (вызов классов, подключение файлов, запуск событий, запросы к БД и другие). Данный раздел станет доступен после включения модуля "Разработка".
В разделе Разработка → Тесты имеются базовые тесты. Тест "Безопасность настроек сервера" позволяет проверить серверное ПО на безопасность. Тест "Безопасность ролей" позволяет проверить безопасность ролевой системы проекта. Данный раздел станет доступен после включения модуля "Тест".
*.data. NoSQLОдной из сильных сторон проекта является формат *.data.
Он схож с форматом YAML, однако имеет следующие преимущества:
ключ: значение;*.data приводит
к изменению одной строки в git diff.Пример файла *.data:
example
string: text
string_empty:
integer: 123
float: 0.000001
boolean: true
null: null
array
- key_1: value 1
- key_2: value 2
- key_3: value 3
array_empty|_empty_array
object
property_name_1: value 1
property_name_2: value 2
property_name_3: value 3
object_empty
object_text|Text
text: some translated textТакой файл будет преобразован в PHP-файл /dynamic/cache/data--example.php
с примерно следующим содержанием:
Cache::$data['example'] = new \stdClass;
Cache::$data['example']->string = 'text';
Cache::$data['example']->string_empty = '';
Cache::$data['example']->integer = 123;
Cache::$data['example']->float = 0.000001;
Cache::$data['example']->boolean = true;
Cache::$data['example']->null = null;
Cache::$data['example']->array['key_1'] = 'value 1';
Cache::$data['example']->array['key_2'] = 'value 2';
Cache::$data['example']->array['key_3'] = 'value 3';
Cache::$data['example']->array_empty = [];
Cache::$data['example']->object = new \stdClass;
Cache::$data['example']->object->property_name_1 = 'value 1';
Cache::$data['example']->object->property_name_2 = 'value 2';
Cache::$data['example']->object->property_name_3 = 'value 3';
Cache::$data['example']->object_empty = new \stdClass;
Cache::$data['example']->object_text = new \effcore\Text;
Cache::$data['example']->object_text->text = 'some translated text';При вызове Cache::select('example') этот файл будет загружен
в память и данные станут доступны без задержки.
Если используется PHP OPCache, тогда все данные будут скомпилированы в оп-код и станут храниться в разделяемой памяти, что не потребует времени на загрузку PHP-файла и его анализ при каждом запросе. Если используется PHP JIT то части кода преобразуются уже в байт-код и выполняются ещё быстрее.
С помощью такого формата разработчик может описать любую структуру с любым уровнем вложенности — он ограничен только своей фантазией. Для каждой строки в таком формате существуют лишь следующие вариаций записи:
имя_сущностиимя_сущности|Имя_классаимя_свойства_обьекта: значение- имя_ключа_массива: значениеКаждый модуль может иметь любое число файлов *.data и располагать их
где угодно, но традиционно все такие файлы будут храниться в директории
data каждого модуля.
Набор таких файлов *.data, а также механизм их парсинга, хранения
и выборки, по своей сути и является NoSQL-хранилищем.
Фактически это гибрид из документ-ориентированной, объектно-ориентированной
и иерархической модели БД.
Парсинг всех файлов *.data происходит один раз — при очистке кэша.
Очистка кэша — это очень редкая процедура, которая требуется лишь после
обновления модулей в системе. После парсинга всё содержимое помещается
в файл dynamic/cache/data_original.php. Также для каждого вида сущности
создаётся отдельный файл. Вот пример такой организации файлов:
dynamic/cache/data--forms.phpdynamic/cache/data--pages.phpdynamic/cache/data--menus.phpКогда необходимо внести изменение в дерево NoSQL, применяется механизм
"Changes". Он описывает то, какие изменения следует внести в это дерево.
Процесс внесения изменений можно описать следующей процедурой: производится
полная загрузка дерева NoSQL из файла data_original.php, далее в это
дерево вносятся изменения, далее производится пофайловое сохранение
каждой сущности дерева NoSQL (пример выше). Если для какой-либо сущности
не было изменений — файл не перезаписывается. Механизм "Changes" также
применяется редко — главным образом при сохранении системных настроек
через административный интерфейс.
Примечание: пример внесения изменений показан в файле
test--data--changes.data модуля "Тест".
Скорость обновления кэша в среднем не превышает одной секунды. Скорость обновления через "Changes" выполняется за десятые доли секунды. Таким образом NoSQL работает в основном в режиме чтения и выдаёт максимально возможную производительность при использовании OPCache + JIT.
В качестве SQL-хранилища могут быть использованы MySQL или SQLite.
Требуемые версии можно узнать в файле docs/software.md.
Основной упор в системе сделан на ANSI SQL и кроссплатформенность.
Поддерживаются следующие возможности:
check (SQLite, MySQL v.8+);transaction (begin, rollback, commit);collate (nocase, binary);constraint (primary, unique, foreign с каскадным действием);index, unique index);Поддерживаются каскадные действия внешнего ключа:
cascade (restrict и no action не были протестированы);cascade (restrict и no action не были протестированы).Поддерживаются кроссплатформенные типы полей:
autoincrementvarchar (MySQL: varchar | SQLite: text)integer (MySQL: int | SQLite: integer)real (MySQL: double | SQLite: real)time (MySQL: time | SQLite: text)date (MySQL: date | SQLite: text)datetime (MySQL: datetime | SQLite: text)boolean (MySQL: tinyint | SQLite: integer)blob (MySQL: blob | SQLite: blob)Набор указанных типов достаточен для большинства задач. Другие типы допускаются, но они не были протестированы. Рекомендуется использовать только данные типы для обеспечения кроссплатформенности.
Хранение дат в любой СУРБД имеет свои особенности. Так, тип timestamp хранит
дату в виде числа, поэтому имеет малый диапазон значений — от 1970-01-01 00:00:01 UTC до
2038-01-19 03:14:07 UTC. Также дополнительной проблемой является его преобразование
к часовому поясу. Поэтому в системе не используется данный тип, а вместо него
рекомендуется использовать тип integer. Однако есть идеальное решение и для
полноценных дат — это использование типов time, date и datetime. Так,
типы date и datetime имеют широкие диапазоны значений от 0001-01-01
до 9999-12-31 и не привязаны к часовому поясу. При добавлении значений
в поля таких типов их следует приводить к часовому поясу UTC±0:00.
Примечание: SQLite поддерживает только 4 типа данных: integer, real, text и blob.
Если используется иной тип, то его значение приводится к этим базовым типам.
Так, тип datetime приводится к text, а boolean к integer и так далее.
Такая реализация не производит контроля целостности домена данных, однако данная
система осуществляет такой контроль на стороне полей форм и внести недействительные
значения будет невозможно.
Примечание: MySQL до версии 8 не поддерживал проверки check, однако данная
система осуществляет такой контроль на стороне полей форм и внести недействительные
значения будет невозможно.
Примечание: В процессе разработки был исключён из поддержки PostgreSQL как СУРБД,
наименее соответствующая ANSI-стандартам и имеющая особенности в работе со счётчиками
autoincrement.
В системе имеются особые типы файлов — это *.cssd, *.jsd,
*.svgd, *.htmld, *.txtd, *.xmld и возможно другие
если в file_types.data они были описаны как kind: dynamic.
Данные файлы не кэшируются и имеют динамическую обработку — на каждый запрос такого типа файла происходит его обработка на стороне PHP (если в системе была зарегистрирована функция-обработчик такого типа или же функция-обработчик всех подобных типов).
Динамическая обработка даёт возможность организовать в таких файлах вывод переменных системы или произвести любую другую операцию с их контентом.
Пример переменных, которые могут быть использованы в динамических файлах:
%%_color(main)
%%_color(main|profile=dark|r=10|g=20|b=30|o=.5)
%%_return_if_scope_is_dark(text|#000|#fff)
%%_return_if_token(color(text)|#fff|1|0)
%%_avatar_path
%%_page_width_min(context)
%%_page_width_max(context)
%%_request(scheme)
%%_request(host)
%%_translation(simple string)По факту:
*.cssd — это классический CSS-файл, содержащий каскадные таблицы стилей,
но который может содержать динамический контент;*.jsd — это классический JS-файл, содержащий код JavaScript,
но который может содержать динамический контент;*.svgd — это классический SVG, содержащий векторную графику в XML формате,
но который может содержать динамический контент.Примечание: больше примеров можно увидеть в файле
develop.cssd.
Система имеет прозрачную и предсказуемую событийную модель.
Достаточно найти или создать файл events.data в пользовательском модуле,
указать в нём функцию-обработчик события и её вес, а далее сбросить кэш
и событие станет обрабатываться.
В административном интерфейсе системы в разделе Разработка → NoSQL данные → События можно просмотреть все зарегистрированные события. Данный раздел станет доступен после включения модуля "Разработка".
Архитектура системы выполнена таким образом, чтобы работать максимально быстро и не требовать кэширования страниц. На проектах любого уровня система будет работать также быстро как и другие системы с включенным кэшированием. Для сильно нагруженных проектов можно организовать кэширование страниц средствами веб-сервера NGINX, Apache или IIS, при этом никаких дополнительных действий со стороны системы не потребуется.
Примечание: Динамические файлы не кэшируются (*.cssd, *.jsd, *.svgd
и другие). При организации их кэширования разработчик берёт всю ответственность
на себя по обновлению такого кэша.
Для повышения производительности следует:
dynamic/cache и dynamic/tmp в ОЗУ при этом
для повышения уровня надёжности веб-сервера такая ОЗУ должна поддерживать коды
исправления ошибок (англ. error-correcting code, ECC), а сам сервер использовать
источник бесперебойного питания (англ. Uninterruptible Power Supply, UPS).Лучший способ увеличения производительности — это грамотное каскадирование стилей. Такой подход позволяет обойтись без препроцессоров SAS и LESS, основной задачей которых является копирование существующих стилей на множество новых элементов в результате чего объём каждого CSS-файла начинает кратно увеличиваться, а сама идея каскадности нивелируется.
Хороший способ увеличения производительности — это минификация JS-файлов путём редукционной реорганизации кода сторонними программами или сервисами. Также хорошим решением является отказ от "тяжёлых" библиотек подобных jQuery и переход на CSS3-анимацию, SMIL-анимацию, современные возможности JavaScript и HTML5.
Спорный способ увеличения производительности — это включить технологию потокового сжатия GZIP. Сделать это можно средствами веб-сервера NGINX, Apache, IIS. Однако следует помнить, что сжатие и распаковка GZIP-трафика приводит к увеличению нагрузки на процессор, создаёт задержку при загрузке и распаковке сжатого трафика, а также снижает время автономной работы мобильного устройства.
Обновление системы или модулей предоставляет:
Для обновления файлов системы в ручном режиме необходимо зайти на её официальный
сайт effcore.com и загрузить текущую версию дистрибутива
в виде архива. Далее следует распаковать загруженный архив локально.
Важно: Среди распакованных файлов имеются директории modules и dynamic.
В эти директории необходимо перенести файлы из существующего проекта.
Далее следует скопировать полученные файлы на веб-сервер. Обновление
сторонних модулей выполняется отдельно.
Для обновления файлов системы или модуля через Git-репозиторий необходимо в административном интерфейсе системы перейти в раздел Управление → Модули → Обновить → Файлы из репозитория и нажать кнопку "обновить". Если кнопка "обновить" недоступна, но доступна кнопка "восстановить репозиторий", тогда необходимо выполнить процедуру восстановления репозитория. Если недоступны кнопки "обновить" и "восстановить репозиторий" значит система или модуль не имеет собственного репозитория и его обновление через Git невозможно.
Обновление файлов системы через Git можно выполнить из командной строки
если зайти на веб-сервер через SSH соединение, перейти в директорию shell
и выполнить команду ./update.sh. Такое обновление возможно только в случае,
если в веб-корне имеется директория .git. Обновление сторонних модулей
выполняется отдельно.
Обновление файлов системы и модулей через Composer можно выполнить из командной
строки если зайти на веб-сервер через SSH соединение, перейти в веб-корень и выполнить
команду composer update. Такое обновление возможно только в случае, если
на веб-сервере установлен Composer. Все модули, которые не были добавлены
через composer require или не были зарегистрированы в composer.json
или composer.lock не будут обновлены.
После обновления файлов системы или модуля следует выполнить обновление данных. Такое обновление производится в разделе Управление → Модули → Обновить → Данные.
Система является открытой и бесплатной.
Лицензионное соглашение является простым и минималистичным и не ограничивает права добропорядочных пользователей.
Согласно лицензионному соглашению злонамеренные пользователи, которые хотели бы выдать данное произведение как своё собственное, уже будут находиться вне рамок правового поля.