Прошлая статья на хабре вызвала некоторый резонанс среди пользователей. Со многими удалось пообщаться в IM. Из разговоров стало ясно, что очень многие хотят сделать СВОЮ систему, заточенную под их нужды. Требования и желания различаются очень сильно и существующие на рынке решения не удовлетворяют потребностей.
В статье я постараюсь рассказать о технической стороне проекта. А начну с беглого осмотра существующих решений.
У владельцев собственного бизнеса, желающих внедрить подобную систему, есть несколько путей:
1) Сравнительно дешёвый. Заиметь толкового IT-спеца в штат, который будет суетится искать, изучать и внедрять. Helpdesk, ERP, CRM, систему документооборота и т.д.
2) Дороже — заказать разработку проекта на стороне. Самая большая проблема — очень мало руководителей способны отвлечься от мысли «хочу штуку, которая может всё» и написать реальное ТЗ. Скорее всего, именно на создание такого ТЗ, уйдёт значительная доля времени, если идея полностью не заглохнет.
3) Заказать продукт у 1С. Очень дорого. Но руководитель скорее всего останется доволен.
4) Ну и продвинутый способ — использовать SaaS, облака, социальные сети, и т. д. Плюсы — дешевле на определённый отрезок времени. Минусы — всё хранится не известно где, никакой кастомизации как таковой нет.
В России из известных представителей две системы: Битрикс-24 (владелец 1С) и Мегаплан (половина акций принадлежит также 1С). Как оказалось и Мегаплан и Битрикс-24 сейчас активно заняты созданием собственной платформы (не SaaS).
Хабр — IT ресурс, поэтому дальше технические подробности о системе.
Главный недостаток workapp — система использует собственный фреймворк. Причин на то несколько:
1) У системы один разработчик. И первоочередной задачей всегда было — реализовать необходимый функционал. Тем не менее, фреймворк — MVC. В последней своей версии система активно использует namespaces, использует структуру фреймворка symfony2, некоторые бандлы фреймворка symfony2 и шаблонизатор twig.
2) Система модулей. Модуль скорее является плагином. Т.е. может быть добавлен или удалён без дополнительных действий.
3) Маршрутизация. Вместо того, чтобы жёстко прописывать существующие маршруты — системы ищет необходимый модуль или показывает страницу 404.
Эти три пункта позволили максимально ускорить процесс создания системы, но усложнили порог входа для других программистов.
Использование структуры фреймворка symfony2 должна позволить наиболее просто перейти к полноценному использованию этого фреймворка.
Нерешённые проблемы для полной миграции на него в данный момент:
1) PDO вместо ORM.
2) Singleton вместо DI.
Классы и функции довольно подробно продукоментированы. Вся документация также лежит в папке /docs/. Github: https://github.com/Zazza/workapp
Система
В директории /src/Otms/System/ расположена отдельная часть приложения, которая отвечает за работу всей системы в целом, работу некоторых базовых функций системы, поддержку пользователей и логирование. Также, как и модули — это отдельное MVC приложение.
Общий для всех страниц шаблон: /src/Otms/System/View/layouts/page.html
Функции системы:
1) Логирование (/src/Otms/System/Model/Logs.php). Все действия происходящие в системе могут быть записаны в базу данных. Такой подход делает возможным работу dashboard (или событий) (/src/Otms/System/Model/Dashboard.php). События в системе представлены двумя подсистемами:
а) Страница события. Выводит все события начиная с нужной даты и более ранее, подгружая их при прокрутке страницы.
б) Выпадающий вверху страницы список событий. Позволяет показывать каждому пользователю новые события которые непосредственно относятся к нему. События могут быть удалены из этого списка, если будут выполнены или больше не требуются. Таким образом данное выпадающее меню должно быть своего рода «индикатором» новых дел или задач и уведомлять о событиях, которые требуют внимания пользователя.
2) История (/src/Otms/System/Model/Logs.php). Позволяет показывать все изменения в любой задаче или объекте.
Запись события (лога):
$this->registry["logs"]->uid = $uid;
$this->registry["logs"]->set($type, $string, $oid, $data);
int $uid — UID пользователя являющегося инициатором события (лога).
string $type:
«mail» — письмо
«com» — комментарий к задаче
«obj» — объект
«info» — информация
«service» — сервисное сообщение
«task» — задача
string $string — текст события
int $oid — ID (объекта, задачи и т.д.)
string $data — данные для хранений связанные с данным логом, нужны для работы «истории». Например: изменение в задаче — хранит предыдущее состояние задачи.
3) Поддержка работы пользователей:
а) /src/Otms/System/Model/Ui.php. Работа текущего пользователя. Авторизация. Изменение профиля пользователя. Запись начала и конца сессии.
б) /src/Otms/System/Model/User.php. Структура пользователей, регистрация новых, правка и удаление существующих. Функции для обеспечения работы многопользовательского режима.
4) API обеспечивает доступ ко все методам системы и её модулей. Командная строка (/src/Otms/System/Model/CmdCommands.php) может быть полезна для тестирования работы системы, её модулей, а также API.
Модуль
Каждый модуль это плагин системы. Т.е. он может быть добавлен или удалён из системы и не должен быть нигде прописан. Чтобы при каждой инициализации приложения не перечитывать наличие модулей, а также их конфигурационные файлы, может быть задействован модуль memcached, который хранит в оперативной памяти все модули и их настройки.
Важно: если в систему будет добавлен новый модуль или же изменён файл config.ini (сюда же относится изменение CSS и JS файлов) необходимо очистить memcached или перезапустить его.
Все функциональные модули для системы workapp должны располагаться в директории: /src/Otms/Modules/. При инициализации приложения выполняется поиск модулей в директории. Результат хранится в Singleton:
$this->registry[«mods»] — массив со всеми найденными модулями
$this->registry[«module_NAME»] (например, $this->registry[«module_task»]) — экземпляр модуля.
Структура директорий модуля:
config.ini — содержит настройки модуля. Пример файла config.ini из файлового менеджера:
[fm]
rgb = 0xFFFFFF
quality = 100
maxUploadSize = "20 MB"
[css]
0 = "css/main.css"
[js]
0 = "js/swfupload.js"
1 = "js/swfupload.queue.js"
2 = "js/fileprogress.js"
3 = "js/handlers.js"
4 = "js/scripts.js"
[path]
tpl = "View"
Index.php — главный для модуля файл. Пример:
<?php
namespace OtmsModules[NAME];
use EngineModulesPreModule;
use EngineModulesModule;
use ReflectionClass;
class Index extends PreModule implements Module {
function __construct() {
$module = new ReflectionClass($this);
parent::__construct($module->getName());
}
function preInit() {
}
function postInit() {
}
}
где [NAME] имя модуля.
Модуль также должен располагаться в директории [NAME].
Каждый модуль представляет отдельное MVC приложение. Контроллеры должны быть расположены в директории Controller, модели в Model, а вид в View. В секции [path], переменной tpl можно изменить расположение вида (шаблонов).
Каждый контроллер, который должен по окончанию своей работы передать контент в шаблон (page.html) для отображения должен заканчиваться: $this->view->showPage().
Метод preInit класса Index выполняет роль preController приложения.
Метод postInit класса Index выполняет роль postController приложения.
Метод postRouterInit() (/vendor/Engine/Modules/PreModule.php) вызывается из класса Bootstrap (метод _pos()). Данный метод вызывает следующие два метода:
1) initView() — инициализирует экземпляр вида модуля. Если модуль работал после вызова роутером — результат его работы будет передан в главный экземпляр вида: $this->registry[«view»].
2) initModules() — если модуль использует собственные JS и CSS файлы, их содержимое будет передано в шаблон страницы: /src/Otms/System/View/layouts/page.html
За чтение JS и CSS файлов отвечает класс Resource. Например, workapp/resource/?module=Chat&file=css/main.css для каждого типа файла выставляется соответствующие заголовки (headers).
Наличие JS и CSS файлов определяется в файле настроек config.ini. Секции [css] и [js].
Резюме: т.к. проект opensource, буду рад разработчикам, дизайнерам и остальным. В первую очередь ищется способный перенести систему на фреймворк symfony2.
Автор: Zazza