Свой модуль "очистка папки"
Готовый код можно скачать в моем репозитории на GitFlic.
Cоздадим модуль, который будет удалять из папки /upload/iblock/
файлы отсутствующие в таблице b_file
. Логика работы простая, если файл физически существует но его нет в базе, значит файл забыли удалить, например при редактирование страницы.
Модуль имеет ряд настроек, доступных из админки, например можно делать резервную копию удаляемых файлов, которые будут сохранены в папке /upload/iblock_Backup/
. Информация об удаленных файлах записывается в таблицу hmarketing_delete
, которая автоматически будет создана при установке модуля и текстовый файл который будет создан в директории /upload/iblock_Backup/
при запуске модуля из админки сайта.
Структура модуля
- Папка
hmarketing.upload
-
Папка
admin
- Файл
menu.php
меню в админке Битрикс
- Файл
-
Папка
install
- Файл
index.php
основной файл установки - Файл
version.php
файл с версией и датой выхода модуля - Файл
instalInfo.php
вывод сообщения в админке сайта об ошибке или успехе при установке модуля - Файл
deInstalInfo.php
вывод сообщения в админке сайта об ошибке или успехе при удалении модуля
- Файл
-
Папка
lang
-
Папка
ru
-
Папка
lib
- Файл
data.php
языковой файл базы данных
- Файл
-
Папка
install
- Файл
instalInfo.php
языковой файл вывода сообщения в админке сайта об ошибке при установке модуля - Файл
deInstalInfo.php
языковой файл вывода сообщения в админке сайта об ошибке при удалении модуля - Файл
index.php
языковой файл основного файла установки
- Файл
-
Папка
-
Папка
-
Папка
lib
- Файл
Main.php
основной класс модуля - Файл
dataFile.php
сущность ORM для таблицыb_file
- Файл
dataTable.php
сущность ORM для таблицыhmarketing_upload_delete
- Файл
- Файл
include.php
подключение файлов модуля - Файл
options.php
настройка модуля в админке
Файл /admin/menu.php
Файл вызывается ядром Битрикс автоматически при установке модуля.
Данный файл создаёт пункты меню в административном интерфейсе Битрикс:
В файле небходимо создать массив $aMenu
, в котором указываются параметры меню, полный состав массива можно посмотреть на официальном сайте.
local/modules/hmarketing.upload/admin/menu.php<?php
/**
* расположение модуля в админки
*
*/
defined('B_PROLOG_INCLUDED') and (B_PROLOG_INCLUDED === true) or die();
// пространство имен для подключений ланговых файлов
use Bitrix\Main\Localization\Loc;
// подключение ланговых файлов
Loc::loadMessages(__FILE__);
// основной массив $aMenu
$aMenu = array(
// оснавная ветка меню
array(
// пункт меню в разделе Контент
'parent_menu' => 'global_menu_services',
// сортировка
'sort' => 1,
// название пункта меню
'text' => "Очистка папки upload",
// идентификатор ветви
"items_id" => "menu_webforms",
// иконка
"icon" => "form_menu_icon",
// дочерния ветка меню
'items' => array(
array(
// название подпункта меню
'text' => 'Удаление файлов в /upload/iblock/',
// ссылка для перехода
'url' => 'settings.php?lang=ru&mid=hmarketing.upload',
),
)
),
);
// возвращаем основной массив $aMenu
return $aMenu;
Файл /install/index.php
Файл вызывается ядром Битрикс автоматически при установке модуля.
Инсталлятор должен находиться в директории /install/index.php
. Имя класса должно соответствовать названию папке модуля и являться наследником от CModule
. Только вместо точки, если мы делаем партнерский модуль
стоит прописать нижние подчеркивание, это нужно для определения модуля в системе. Файл выполняется при установке или удалении модуля через административный интерфейс.
local/modules/hmarketing.upload/install/index.php<?php
// пространство имен для подключений ланговых файлов
use Bitrix\Main\Localization\Loc;
// пространство имен для управления (регистрации/удалении) модуля в системе/базе
use Bitrix\Main\ModuleManager;
// пространство имен с абстрактным классом для любых приложений, любой конкретный класс приложения является наследником этого абстрактного класса
use Bitrix\Main\Application;
// пространство имен для работы c ORM
use \Bitrix\Main\Entity\Base;
// пространство имен для автозагрузки модулей
use \Bitrix\Main\Loader;
// пространство имен для работы с параметрами модулей хранимых в базе данных
use Bitrix\Main\Config\Option;
// подключение ланговых файлов
Loc::loadMessages(__FILE__);
/**
* основной класс для установки модуля
*
*/
class Hmarketing_Upload extends CModule
{
/**
* ID модуля
*
* @var string
*/
public $MODULE_ID;
/**
* версия модуля
*
* @var string
*/
public $MODULE_VERSION;
/**
* дата релиза версии модуля
*
* @var string
*/
public $MODULE_VERSION_DATE;
/**
* название модуля
*
* @var string
*/
public $MODULE_NAME;
/**
* описание модуля
*
* @var string
*/
public $MODULE_DESCRIPTION;
/**
* имя партнера выпустившего модуль
*
* @var string
*/
public $PARTNER_NAME;
/**
* ссылка на рисурс партнера выпустившего модуль
*
* @var string
*/
public $PARTNER_URI;
/**
* в конструкторе заполняем свойства
*
* @return void
*/
function __construct()
{
// создаем пустой массив для файла version.php
$arModuleVersion = array();
// подключаем файл version.php
include_once(__DIR__ . '/version.php');
// версия модуля
$this->MODULE_VERSION = $arModuleVersion['VERSION'];
// дата релиза версии модуля
$this->MODULE_VERSION_DATE = $arModuleVersion['VERSION_DATE'];
// id модуля
$this->MODULE_ID = "hmarketing.upload";
// название модуля
$this->MODULE_NAME = "Удаление файлов в /upload/iblock/";
// описание модуля
$this->MODULE_DESCRIPTION = "Удаление ненужных файлов в директории /upload/iblock/";
// имя партнера выпустившего модуль
$this->PARTNER_NAME = "Эйч Маркетинг";
// ссылка на рисурс партнера выпустившего модуль
$this->PARTNER_URI = "https://hmarketing.ru";
}
/**
* метод отрабатывает при установке модуля
*
* @return void
*/
function DoInstall()
{
// глобальная переменная с обстрактным классом
global $APPLICATION;
// регистрируем модуль в системе
ModuleManager::RegisterModule("hmarketing.upload");
// создаем таблицы баз данных, необходимые для работы модуля
$this->InstallDB();
// подключаем скрипт с административным прологом и эпилогом
$APPLICATION->includeAdminFile(
Loc::getMessage('INSTALL_TITLE'),
__DIR__ . '/instalInfo.php'
);
// для успешного завершения, метод должен вернуть true
return true;
}
/**
* метод отрабатывает при удалении модуля
*
* @return void
*/
function DoUninstall()
{
// глобальная переменная с обстрактным классом
global $APPLICATION;
// удаляем таблицы баз данных, необходимые для работы модуля
$this->UnInstallDB();
// удаляем регистрацию модуля в системе
ModuleManager::UnRegisterModule("hmarketing.upload");
// подключаем скрипт с административным прологом и эпилогом
$APPLICATION->includeAdminFile(
Loc::getMessage('DEINSTALL_TITLE'),
__DIR__ . '/deInstalInfo.php'
);
// для успешного завершения, метод должен вернуть true
return true;
}
/**
* метод для создания таблицы баз данных
*
* @return void
*/
function InstallDB()
{
// подключаем модуль для того что бы был видем класс ORM
Loader::includeModule($this->MODULE_ID);
// через класс Application получаем соединение по переданному параметру, параметр берем из ORM-сущности (он указывается, если необходим другой тип подключения, отличный от default), если тип подключения по умолчанию, то параметр можно не передавать. Далее по подключению вызываем метод isTableExists, в который передаем название таблицы полученное с помощью метода getDBTableName() класса Base
if (!Application::getConnection(\Hmarketing\Upload\DataTable::getConnectionName())->isTableExists(Base::getInstance("\Hmarketing\Upload\DataTable")->getDBTableName())) {
// eсли таблицы не существует, то создаем её по ORM сущности
Base::getInstance("\Hmarketing\Upload\DataTable")->createDbTable();
}
}
/**
* мметод для удаления таблицы баз данных
*
* @return void
*/
function UnInstallDB()
{
// подключаем модуль для того что бы был видем класс ORM
Loader::includeModule($this->MODULE_ID);
// делаем запрос к бд на удаление таблицы, если она существует, по подключению к бд класса Application с параметром подключения ORM сущности
Application::getConnection(\Hmarketing\Upload\DataTable::getConnectionName())->queryExecute('DROP TABLE IF EXISTS ' . Base::getInstance("\Hmarketing\Upload\DataTable")->getDBTableName());
// удаляем параметры модуля из базы данных битрикс
Option::delete($this->MODULE_ID);
}
/**
* метод для создания обработчика событий
*
* @return bool для успешного завершения, метод должен вернуть true
*/
function InstallEvents()
{
// для успешного завершения, метод должен вернуть true
return true;
}
/**
* метод для удаления обработчика событий
*
* @return bool для успешного завершения, метод должен вернуть true
*/
function UnInstallEvents()
{
// для успешного завершения, метод должен вернуть true
return true;
}
/**
* метод для копирования файлов модуля при установке
*
* @return bool для успешного завершения, метод должен вернуть true
*/
function InstallFiles()
{
// для успешного завершения, метод должен вернуть true
return true;
}
/**
* метод для удаления файлов модуля при удалении
*
* @return bool для успешного завершения, метод должен вернуть true
*/
function UnInstallFiles()
{
// для успешного завершения, метод должен вернуть true
return true;
}
}
Файл /install/version.php
Файл вызывается при установки модуля из /install/index.php
Номер версии модуля должен храниться в файле /install/version.php
в виде массива. Плюс к этому нужно в классе модуля записывать эти значения. В связи с этим нужно налепить небольшую городушку, которая будет брать значение из этого файла и записывать его в модуль:
local/modules/hmarketing.upload/install/version.php<?php
/**
* версия модуля
*
*/
$arModuleVersion = array(
'VERSION' => '1.0.0',
'VERSION_DATE' => '2023-01-01 10:00:00'
);
Файл /install/instalInfo.php
Файл вызывается при установки модуля из /install/index.php
Файл вывод сообщения в админке сайта об ошибке или успехе при установке модуля:
local/modules/hmarketing.upload/install/instalInfo.php<?php
/**
* статус установки
*
*/
// пространство имен для подключений ланговых файлов
use Bitrix\Main\Localization\Loc;
// подключение ланговых файлов
Loc::loadMessages(__FILE__);
// метод возвращает объект класса CApplicationException, содержащий последнее исключение
if ($errorException = $APPLICATION->getException()) {
// вывод сообщения об ошибке при установке модуля
CAdminMessage::showMessage(
Loc::getMessage('INSTALL_FAILED') . ': ' . $errorException->GetString()
);
} else {
// вывод уведомления при успешной установке модуля
CAdminMessage::showNote(
Loc::getMessage('INSTALL_SUCCESS')
);
}
?>
<!-- Кнопка возврата к списку модулей -->
<form action="<?= $APPLICATION->getCurPage(); ?>">
<input type="submit" value="<?= Loc::getMessage('RETURN_MODULES'); ?>">
</form>
Файл /install/deInstalInfo.php
Файл вызывается при удалении модуля из /install/index.php
Файл вывод сообщения в админке сайта об ошибке или успехе при удалении модуля:
local/modules/hmarketing.upload/install/deInstalInfo.php<?php
/**
* статус удаления
*
*/
// пространство имен для подключений ланговых файлов
use Bitrix\Main\Localization\Loc;
// подключение ланговых файлов
Loc::loadMessages(__FILE__);
// метод возвращает объект класса CApplicationException, содержащий последнее исключение
if ($errorException = $APPLICATION->getException()) {
// вывод сообщения об ошибке при удалении модуля
CAdminMessage::showMessage(
Loc::getMessage('DEINSTALL_FAILED') . ': ' . $errorException->GetString()
);
} else {
// вывод уведомления при успешном удалении модуля
CAdminMessage::showNote(
Loc::getMessage('DEINSTALL_SUCCESS')
);
}
?>
<!-- Кнопка возврата к списку модулей -->
<form action="<?= $APPLICATION->getCurPage(); ?>">
<input type="submit" value="<?= Loc::getMessage('RETURN_MODULES'); ?>">
</form>
Файлы в дириктории /lang/ru/
Файл вызывается ядром Битрикс автоматически при установке модуля.
Файлы служат для реализации переводов, в них находится простой массив $MESS
в котором хранятся пары ключ=>значение
перевода, часть ru
в пути к файлу является указанимем на язык перевода:
Файл /lib/Main.php
Файл подключается из файла /include.php
.
В данном основном файле будет храниться логика работы модуля, основной класс со всеми методами.
local/modules/hmarketing.upload/lib/Main.php<?php
/**
* @author Эйч Маркетинг <info@hmarketing.ru>
* @copyright 2014-2024 The hmarketing.ru
*/
// пространство имен модуля
namespace Hmarketing\Upload;
// пространство имен для работы с датой
use Bitrix\Main\Type\DateTime;
// пространство имен для ORM
use \Hmarketing\Upload\DataTable;
// пространство имен для b_file
use \Hmarketing\Upload\FileTable;
/**
* основной класс модуля
*
*/
class Main
{
/**
* удалять найденые файлы
*
* @var string
*/
public $deleteFiles;
/**
* создавать бэкап файлов
*
* @var string
*/
public $saveBackup;
/**
* папка для бэкапа
*
* @var string
*/
public $patchBackup;
/**
* целевая папка для поиска файлов
*
* @var string
*/
public $rootDirPath;
/**
* файл для записи данных
*
* @var mixed
*/
public $file;
/**
* массив для записи файлов из таблицы b_file
*
* @var array
*/
public $arFilesCache = array();
/**
* конструктор
*
* @return void
*/
function __construct()
{
// папка для бэкапа
$this->patchBackup = $_SERVER['DOCUMENT_ROOT'] . "/upload/iblock_Backup/";
// целевая папка для поиска файлов
$this->rootDirPath = $_SERVER['DOCUMENT_ROOT'] . "/upload/iblock";
// создаем пустой файл
file_put_contents($this->file = $this->patchBackup . date('H.i.s_d.m.Y') . '.txt', '');
// вызываем метод получения данных модуля из базы
$this->Option();
// вызываем метод создания папки для бекапа
$this->DirPatchBackup();
// вызываем метод создания массива с файлами из базы
$this->ArFiles();
// вызываем метод создания пути
$this->Path();
}
/**
* получение из базы опций настройки модуля
*
* @return void
*/
function Option()
{
// получаем значения из настроек модуля всех полей
$dataArr = \Bitrix\Main\Config\Option::getForModule("hmarketing.upload");
// перебираем данные полученные из базы
foreach ($dataArr as $key => $value) {
switch ($key) {
case 'deletefiles':
$this->deleteFiles = $value;
break;
case 'savebackup':
$this->saveBackup = $value;
break;
}
}
}
/**
* cоздание папки для бэкапа
*
* @return void
*/
function DirPatchBackup()
{
if (!file_exists($this->patchBackup)) {
CheckDirPath($this->patchBackup);
}
}
/**
* запись файлов в массив из базы
*
* @return void
*/
function ArFiles()
{
// получаем записи из таблицы b_file
$result = FileTable::getList(array(
'select' => array('FILE_NAME', 'SUBDIR'),
'filter' => array('=MODULE_ID' => 'iblock'),
));
// перебираем записи из таблицы b_file
while ($row = $result->Fetch()) {
$this->arFilesCache[$row['FILE_NAME']] = $row['SUBDIR'];
}
}
/**
* получение пути
*
* @return void
*/
function Path()
{
// открываем целевую папку с файлами /upload/iblock
$rootDir = opendir($this->rootDirPath);
// запускаем цикл и получает элемент подкатигории по его дескриптору из папки /upload/iblock
while (false !== ($subDirName = readdir($rootDir))) {
// проверяем на точку и прирываем итерацию, в каталоге самая первая запись всегда точка, вторая две точки, после этого идут подпапки и файлы
if ($subDirName == '.' || $subDirName == '..') {
continue;
}
// путь до подкатегории /upload/iblock/..
$subDirPath = "$this->rootDirPath/$subDirName";
// открываем папку подкатигории /upload/iblock/..
$subDir = opendir($subDirPath);
// запускаем цикл и получает элемент подкатигории по его дескриптору из папки /upload/iblock/..
while (false !== ($subFileName = readdir($subDir))) {
// проверяем на точку и прирываем итерацию, в каталоге самая первая запись всегда точка, вторая две точки, после этого идут подпапки и файлы
if ($subFileName == '.' || $subFileName == '..') {
continue;
}
// путь до подкатегории или файла /upload/iblock/../..
$subFilePath = "$this->rootDirPath/$subDirName/$subFileName";
// проверяем на директорию/файл и вызываем соответствующий метод
if (is_dir($subFilePath)) {
$this->TwoDir($subFilePath, $subDirName, $subFileName, $subDirPath);
} else {
$this->OneDir($subDirPath, $subFileName, $subDirName);
}
}
}
// закрываем целевую папку с файлами /upload/iblock
closedir($rootDir);
}
/**
* обработка одной папки
*
* @param string $subDirPath
* @param string $fileName
* @param string $subDirName
* @return void
*/
function OneDir($subDirPath, $fileName, $subDirName)
{
// пометка для файла
$filesCount = 0;
// если файл с диска есть в списке файлов базы, значит пропуск
if (array_key_exists($fileName, $this->arFilesCache)) {
// увеличиваем счетчик нужных файлов
$filesCount++;
}
// полный путь до файла
$fullPath = "$subDirPath/$fileName";
// переменная сигнализирующая о наличии поддириктории
$backTrue = false;
// если задано удаление найденных файлов и найденный файл не нужный
if ($this->deleteFiles === 'Y' && $filesCount == 0) {
// если задано делать бекап, делаем
if ($this->saveBackup === 'Y') {
// проверяем наличие поддиректории в папке для бекапа /upload/iblock_Backup/
if (!file_exists($this->patchBackup . $subDirName)) {
// если в папке для бекапов /upload/iblock_Backup/ нет поддириктории, создаем ее
if (CheckDirPath($this->patchBackup . $subDirName)) {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
} else {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
// если поддириктория есть
if ($backTrue) {
// создаем копию в бэкап
CopyDirFiles($fullPath, $this->patchBackup . $subDirName . '/' . $fileName);
}
}
// метод записи в информационный файл
$this->Save('Файл удален: ', $fullPath);
// удаление файла
unlink($fullPath);
// удаление поддириктории
rmdir($subDirPath);
}
// если задано не удаление найденных файлов и найденный файл не нужный
if ($this->deleteFiles != 'Y' && $filesCount == 0) {
// проверяем наличие поддиректории в папке для бекапа /upload/iblock_Backup/
if (!file_exists($this->patchBackup . $subDirName)) {
// если в папке для бекапов /upload/iblock_Backup/ нет поддириктории, создаем ее
if (CheckDirPath($this->patchBackup . $subDirName)) {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
} else {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
// если поддириктория есть
if ($backTrue) {
// создаем копию в бэкап
CopyDirFiles($fullPath, $this->patchBackup . $subDirName . '/' . $fileName);
}
// метод записи в информационный файл
$this->Save('Файл не удален и скопирован: ', $fullPath);
}
}
/**
* обработка двух папок
*
* @param string $subSubDirPath
* @param string $subDirName
* @param string $subFileName
* @param string $subDirPath
* @return void
*/
function TwoDir($subSubDirPath, $subDirName, $subFileName, $subDirPath)
{
// пометка для файла
$filesCount = 0;
// открываем папку с файлом
$hSubDir = opendir($subSubDirPath);
// запускаем цикл и получает уже элемент по его дескриптору из подкатигории /upload/iblock/../..
while (false !== ($fileName = readdir($hSubDir))) {
// проверяем на точку и прирываем итерацию, в каталоге самая первая запись всегда точка, вторая две точки, после этого идут подпапки и файлы
if ($fileName == '.' || $fileName == '..') {
continue;
}
// если файл с диска есть в списке файлов базы, значит пропуск
if (array_key_exists($fileName, $this->arFilesCache)) {
// увеличиваем счетчик нужных файлов
$filesCount++;
continue;
}
// полный путь до файла
$fullPath = "$subSubDirPath/$fileName";
// переменная сигнализирующая о наличии поддириктории
$backTrue = false;
// если задано удаление найденных файлов
if ($this->deleteFiles === 'Y') {
// проверяем наличие поддиректории в папке для бекапа /upload/iblock_Backup/
if (!file_exists($this->patchBackup . $subDirName . '/' . $subFileName . '/')) {
// если в папке для бекапов /upload/iblock_Backup/ нет поддириктории, создаем ее
if (CheckDirPath($this->patchBackup . $subDirName . '/' . $subFileName . '/')) {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
} else {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
// если поддириктория есть и нужно создавать бекап файла
if ($backTrue && $this->saveBackup === 'Y') {
// создаем копию в бэкап
CopyDirFiles($fullPath, $this->patchBackup . $subDirName . '/' . $subFileName . '/' . $fileName);
}
// метод записи в информационный файл
$this->Save('Файл удален: ', $fullPath);
// удаление файла
unlink($fullPath);
// удаление поддиректории, если каталог пуст
if ($this->deleteFiles === 'Y' && $filesCount == 0) {
rmdir($subSubDirPath);
rmdir($subDirPath);
}
}
// если задано не удаление найденных файлов
if ($this->deleteFiles != 'Y') {
// проверяем наличие поддиректории в папке для бекапа /upload/iblock_Backup/
if (!file_exists($this->patchBackup . $subDirName . '/' . $subFileName . '/')) {
// если в папке для бекапов /upload/iblock_Backup/ нет поддириктории, создаем ее
if (CheckDirPath($this->patchBackup . $subDirName . '/' . $subFileName . '/')) {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
} else {
// меняем переменную сигнализирующая о наличии поддириктории
$backTrue = true;
}
// если поддириктория есть
if ($backTrue) {
// создаем копию в бэкап
CopyDirFiles($fullPath, $this->patchBackup . $subDirName . '/' . $subFileName . '/' . $fileName);
}
// метод записи в информационный файл
$this->Save('Файл не удален и скопирован: ', $fullPath);
}
// удаляем переменные
unset($fileName, $backTrue);
}
// закрываем папку подкатигории
closedir($hSubDir);
}
/**
* сохранения информации о затронутых файлах
*
* @param mixed $name
* @param mixed $path
* @return void
*/
function Save($name, $path)
{
// записываем в базу
DataTable::add(array(
'DATE' => new DateTime(date('Y-m-d H:i:s'), "Y-m-d H:i:s"),
'TIP' => $name,
'PATH' => $path,
));
// записываем в файл
$fd = fopen($this->file, 'a');
// записываем в информационный файл
fputs($fd, $name . $path . "\n");
// закрываем информационный файл
fclose($fd);
}
}
Файл /lib/dataFile.php
Файл подключается из файла /include.php
.
Данный файл служит для организации доступа к таблице с помощью ORM
, в нём создаётся класс, который наследуется от класса Entity\DataManager
, который в свою очередь реализует парадигму ORM
.
local/modules/hmarketing.upload/lib/dataFile.php<?php
// пространство имен модуля
namespace Hmarketing\Upload;
// пространство имен для ORM
use Bitrix\Main\Localization\Loc,
Bitrix\Main\ORM\Data\DataManager,
Bitrix\Main\ORM\Fields\DatetimeField,
Bitrix\Main\ORM\Fields\IntegerField,
Bitrix\Main\ORM\Fields\StringField,
Bitrix\Main\ORM\Fields\Validators\LengthValidator,
Bitrix\Main\Type\DateTime;
Loc::loadMessages(__FILE__);
/**
* сущность ORM унаследованная от DataManager
*
*/
class FileTable extends DataManager
{
/**
* Returns DB table name for entity.
*
* @return string
*/
public static function getTableName()
{
return 'b_file';
}
/**
* Returns entity map definition.
*
* @return array
*/
public static function getMap()
{
return [
new IntegerField(
'ID',
[
'primary' => true,
'autocomplete' => true,
'title' => Loc::getMessage('FILE_ENTITY_ID_FIELD')
]
),
new DatetimeField(
'TIMESTAMP_X',
[
'default' => function () {
return new DateTime();
},
'title' => Loc::getMessage('FILE_ENTITY_TIMESTAMP_X_FIELD')
]
),
new StringField(
'MODULE_ID',
[
'validation' => [__CLASS__, 'validateModuleId'],
'title' => Loc::getMessage('FILE_ENTITY_MODULE_ID_FIELD')
]
),
new IntegerField(
'HEIGHT',
[
'title' => Loc::getMessage('FILE_ENTITY_HEIGHT_FIELD')
]
),
new IntegerField(
'WIDTH',
[
'title' => Loc::getMessage('FILE_ENTITY_WIDTH_FIELD')
]
),
new IntegerField(
'FILE_SIZE',
[
'title' => Loc::getMessage('FILE_ENTITY_FILE_SIZE_FIELD')
]
),
new StringField(
'CONTENT_TYPE',
[
'default' => 'IMAGE',
'validation' => [__CLASS__, 'validateContentType'],
'title' => Loc::getMessage('FILE_ENTITY_CONTENT_TYPE_FIELD')
]
),
new StringField(
'SUBDIR',
[
'validation' => [__CLASS__, 'validateSubdir'],
'title' => Loc::getMessage('FILE_ENTITY_SUBDIR_FIELD')
]
),
new StringField(
'FILE_NAME',
[
'required' => true,
'validation' => [__CLASS__, 'validateFileName'],
'title' => Loc::getMessage('FILE_ENTITY_FILE_NAME_FIELD')
]
),
new StringField(
'ORIGINAL_NAME',
[
'validation' => [__CLASS__, 'validateOriginalName'],
'title' => Loc::getMessage('FILE_ENTITY_ORIGINAL_NAME_FIELD')
]
),
new StringField(
'DESCRIPTION',
[
'validation' => [__CLASS__, 'validateDescription'],
'title' => Loc::getMessage('FILE_ENTITY_DESCRIPTION_FIELD')
]
),
new StringField(
'HANDLER_ID',
[
'validation' => [__CLASS__, 'validateHandlerId'],
'title' => Loc::getMessage('FILE_ENTITY_HANDLER_ID_FIELD')
]
),
new StringField(
'EXTERNAL_ID',
[
'validation' => [__CLASS__, 'validateExternalId'],
'title' => Loc::getMessage('FILE_ENTITY_EXTERNAL_ID_FIELD')
]
),
];
}
/**
* Returns validators for MODULE_ID field.
*
* @return array
*/
public static function validateModuleId()
{
return [
new LengthValidator(null, 50),
];
}
/**
* Returns validators for CONTENT_TYPE field.
*
* @return array
*/
public static function validateContentType()
{
return [
new LengthValidator(null, 255),
];
}
/**
* Returns validators for SUBDIR field.
*
* @return array
*/
public static function validateSubdir()
{
return [
new LengthValidator(null, 255),
];
}
/**
* Returns validators for FILE_NAME field.
*
* @return array
*/
public static function validateFileName()
{
return [
new LengthValidator(null, 255),
];
}
/**
* Returns validators for ORIGINAL_NAME field.
*
* @return array
*/
public static function validateOriginalName()
{
return [
new LengthValidator(null, 255),
];
}
/**
* Returns validators for DESCRIPTION field.
*
* @return array
*/
public static function validateDescription()
{
return [
new LengthValidator(null, 255),
];
}
/**
* Returns validators for HANDLER_ID field.
*
* @return array
*/
public static function validateHandlerId()
{
return [
new LengthValidator(null, 50),
];
}
/**
* Returns validators for EXTERNAL_ID field.
*
* @return array
*/
public static function validateExternalId()
{
return [
new LengthValidator(null, 50),
];
}
}
Файл /lib/dataTable.php
Файл подключается из файла /include.php
.
Данный файл служит для организации доступа к таблице с помощью ORM
, в нём создаётся класс, который наследуется от класса Entity\DataManager
, который в свою очередь реализует парадигму ORM
.
local/modules/hmarketing.upload/lib/dataTable.php<?php
// пространство имен модуля
namespace Hmarketing\Upload;
// пространство имен для подключений ланговых файлов
use Bitrix\Main\Localization\Loc;
// пространство имен для ORM
use Bitrix\Main\Entity;
// подключение ланговых файлов
Loc::loadMessages(__FILE__);
/**
* сущность ORM унаследованная от DataManager
*
*/
class DataTable extends Entity\DataManager
{
/**
* название таблицы в базе данных, если не указывать данную функцию, то таблица в бд сформируется автоматически из неймспейса
*
* @return void
*/
public static function getTableName()
{
return "hmarketing_upload_delete";
}
/**
* подключение к БД, если не указывать, то будет использовано значение по умолчанию подключения из файла .settings.php. Если указать, то можно выбрать подключение, которое может быть описано в .setting.php
*
* @return void
*/
public static function getConnectionName()
{
return "default";
}
/**
* метод возвращающий структуру ORM-сущности
*
* @return void
*/
public static function getMap()
{
/*
* Типы полей:
* DatetimeField - дата и время
* DateField - дата
* BooleanField - логическое поле да/нет
* IntegerField - числовой формат
* FloatField - числовой дробный формат
* EnumField - список, можно передавать только заданные значения
* TextField - text
* StringField - varchar
*/
return array(
// ID
new Entity\IntegerField(
// имя сущности
"ID",
array(
// первичный ключ
"primary" => true,
// AUTO INCREMENT
"autocomplete" => true,
)
),
// дата и время заполнения
new Entity\DatetimeField(
// имя сущности
"DATE",
array(
'required' => true,
)
),
// описание картинки
new Entity\StringField(
// имя сущности
"TIP",
array(
// обязательное поле
"required" => true,
)
),
// описание картинки
new Entity\StringField(
// имя сущности
"PATH",
array(
// обязательное поле
"required" => true,
)
),
);
}
}
файл /include.php
Файл вызывается ядром Битрикс автоматически при установке модуля.
Файл необходим для подключения классов или дополнительных файлов модуля. Если соблюдать соответствие namespace
и имени модуля, то поддерживается автозагрузка класса. Автозагрузка работает медленнее, чем поключение файла в include.php
.
local/modules/hmarketing.upload/include.php "lib/Main.php",
"Hmarketing\\Upload\\DataTable" => "lib/dataTable.php",
"Hmarketing\\Upload\\FileTable" => "lib/dataFile.php",
)
);
файл /options.php
Файл вызывается ядром Битрикс автоматически при установке модуля.
Иногда полезно выносить какие-то настройки решения на отдельную страницу, отвлечённую от компонентов, к тому же компонентов может не быть вовсе, а всё равно надо дать возможность администратору сайта как-то влиять на работу модуля. В Битрикс довольно легко создавать страницы с параметрами для своих модулей.
В панели Битрикс сама страница с настройками находится по адресу Настройки -> Настройки модулей -> Имя_модуля
:
local/modules/hmarketing.upload/options.php<?php
/**
* административный раздел модуля
*
*/
// пространство имен для подключений ланговых файлов
use Bitrix\Main\Localization\Loc;
// пространство имен для получения ID модуля
use Bitrix\Main\HttpApplication;
// пространство имен для загрузки необходимых файлов, классов, модулей
use Bitrix\Main\Loader;
// пространство имен для работы с параметрами модулей хранимых в базе данных
use Bitrix\Main\Config\Option;
// подключение ланговых файлов
Loc::loadMessages(__FILE__);
// получаем id модуля
$request = HttpApplication::getInstance()->getContext()->getRequest();
$module_id = htmlspecialcharsbx($request["mid"] != "" ? $request["mid"] : $request["id"]);
// подключение модуля
Loader::includeModule($module_id);
// настройки модуля для админки в том числе значения по умолчанию
$aTabs = array(
array(
// значение будет вставленно во все элементы вкладки для идентификации
"DIV" => "edit",
// название вкладки в табах
"TAB" => "Удаление ненужных файлов из папки /upload/iblock",
// массив с опциями секции
"OPTIONS" => array(
"Удалять найденые файлы?",
array(
// имя элемента формы
"deletefiles",
// поясняющий текст
"Если флажок не активен, бекап автоматически создастся но файлы из /upload/iblock/ не будут удалены. Если флажок активен, можно выбрать ниже пораметр 'Сохранять в бекап найденые файлы'.",
// значение checkbox по умолчанию "Нет"
"N",
// тип элемента формы "checkbox"
array("checkbox"),
),
"Сохранять в бекап найденые файлы?",
array(
// имя элемента формы
"savebackup",
// поясняющий текст
"Если флажок активен, бекап создастся, файлы будут сохранены в /upload/iblock_Backup",
// значение checkbox по умолчанию "Нет"
"N",
// тип элемента формы "checkbox"
array("checkbox"),
),
)
)
);
// проверяем текущий POST запрос и сохраняем выбранные пользователем настройки
if ($request->isPost() && check_bitrix_sessid()) {
// проверяем POST запрос, если инициатором выступила кнопка с name="Update" сохраняем введенные настройки в базу данных
if ($request["Update"]) {
// цикл по заполненым пользователем вкладкам
foreach ($aTabs as $aTab) {
foreach ($aTab["OPTIONS"] as $arOption) {
// если это название секции, переходим к следующий итерации цикла
if (!is_array($arOption)) {
continue;
}
// получаем в переменную $optionValue введенные пользователем данные
$optionValue = $request->getPost($arOption[0]);
// устанавливаем выбранные значения параметров и сохраняем в базу данных, перед сохранением проверяем если массив то соединяем данные, если не массив сохраняем как есть
Option::set($module_id, $arOption[0], $optionValue);
}
}
}
// проверяем POST запрос, если инициатором выступила кнопка с name="dalete", выполняем действия с файлами
if ($request["dalete"]) {
new Hmarketing\Upload\Main();
}
}
// отрисовываем форму, для этого создаем новый экземпляр класса CAdminTabControl, куда и передаём массив с настройками
$tabControl = new CAdminTabControl(
"tabControl",
$aTabs
);
// отображаем заголовки закладок
$tabControl->Begin();
?>
<form action="<?= ($APPLICATION->GetCurPage()) . '?mid=' . ($module_id) . '&lang=' . (LANG) ?>" method="post">
<? foreach ($aTabs as $aTab) {
if ($aTab["OPTIONS"]) {
// завершает предыдущую закладку, если она есть, начинает следующую
$tabControl->BeginNextTab();
// отрисовываем форму из массива
__AdmSettingsDrawList($module_id, $aTab["OPTIONS"]);
}
}
// выводит стандартные кнопки отправки формы
$tabControl->Buttons();
// выводим скрытый input с идентификатором сессии
echo (bitrix_sessid_post()); ?>
<input class="adm-btn-save" type="submit" name="Update" value="Сохранить настройки" />
<input type="submit" name="dalete" value="Очистить папку" />
</form>
<?
// обозначаем конец отрисовки формы
$tabControl->End();