Разработка плагина для Osclass: полное руководство

Интересные разработки

Введение

Osclass предоставляет мощную, но специфичную архитектуру для создания плагинов. В отличие от WordPress, Osclass требует строгого соблюдения собственных стандартов и подходов. В этой статье я поделюсь современными практиками разработки плагинов, основанными на реальном опыте.

Подготовка к разработке

Требования

  • Установленная Osclass 8.x (рекомендуется PHP 8+)

  • Понимание MVC-архитектуры Osclass

  • Знакомство с DAO (Database Access Object) паттерном

  • Базовые знания PHP 8, SQL, jQuery

Важное отличие от WordPress

Osclass не использует WordPress-подход с отдельными файлами install.php и uninstall.php. Вся логика установки и удаления должна находиться внутри класса модели.

Структура плагина

Плагины располагаются в /oc-content/plugins/название_плагина/

Правильная структура плагина:

название_плагина/
├── index.php                          # Главный файл (мета-информация, хуки, роуты)
├── functions.php                      # Все функции плагина
├── email.php                          # Email-шаблоны (опционально)
├── model/
│   ├── ModelName.php                  # Модель с install/uninstall
│   └── struct.sql                     # SQL-схема таблиц
├── admin/
│   ├── configure.php                  # Страница настроек
│   ├── list.php                       # Список элементов
│   └── form.php                        # Форма создания/редактирования
├── user/
│   └── dashboard.php                  # Пользовательская страница
├── form/
│   └── unsubscribe.php                # Формы (опционально)
├── js/
│   └── script.js
├── css/
│   └── style.css
└── languages/
    ├── en_EN/
    └── ru_RU/

Обратите внимание:

  • Файлы install.php и uninstall.php — устаревший подход!

  • Все установочные методы должны быть в модели и вызываться из index.php

Создание базовой структуры плагина

1. Файл модели (model/ModelName.php)

Модель должна наследовать DAO и содержать методы установки/удаления:

<?php
class ModelName extends DAO {
    private static $instance;

    public static function newInstance() {
        if(!self::$instance instanceof self) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    function __construct() {
        parent::__construct();
    }

    // Получение имен таблиц
    public function getTable_main() {
        return DB_TABLE_PREFIX . 't_plugin_name';
    }

    // Импорт SQL
    public function import($file) {
        $path = osc_plugin_resource($file);
        $sql = file_get_contents($path);
        
        if(!$this->dao->importSQL($sql)) {
            throw new Exception("Error importSQL: " . $this->dao->getErrorDesc());
        }
    }

    // УСТАНОВКА - ВАЖНО!
    public function install($version = '') {
        if($version == '') {
            $this->import('plugin_name/model/struct.sql');
            osc_set_preference('version', 100, 'plugin-name', 'INTEGER');
        }
    }

    // УДАЛЕНИЕ - ВАЖНО!
    public function uninstall() {
        // Удаление таблиц
        $this->dao->query(sprintf('DROP TABLE IF EXISTS %s', $this->getTable_main()));
        
        // Удаление настроек
        $db_prefix = DB_TABLE_PREFIX;
        $query = "DELETE FROM {$db_prefix}t_preference WHERE s_section = 'plugin-name'";
        $this->dao->query($query);
    }

    // CRUD методы
    public function getItem($id) {
        $this->dao->select('*');
        $this->dao->from($this->getTable_main());
        $this->dao->where('pk_i_id', $id);
        
        $result = $this->dao->get();
        return $result ? $result->row() : false;
    }
}
?>

2. SQL-схема (model/struct.sql)

SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS /*TABLE_PREFIX*/t_plugin_name;
CREATE TABLE /*TABLE_PREFIX*/t_plugin_name (
    pk_i_id INT NOT NULL AUTO_INCREMENT,
    fk_i_user_id INT NOT NULL,
    s_name VARCHAR(200),
    i_status TINYINT(1) DEFAULT 0,
    dt_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (pk_i_id),
    KEY idx_user (fk_i_user_id)
) ENGINE=InnoDB DEFAULT CHARACTER SET 'UTF8' COLLATE 'UTF8_GENERAL_CI';

SET FOREIGN_KEY_CHECKS=1;

3. Главный файл (index.php)

<?php
/*
  Plugin Name: Название плагина
  Plugin URI: https://вашсайт.ru
  Description: Описание плагина
  Version: 1.0.0
  Author: Ваше имя
  Author Email: email@example.com
  Short Name: plugin_name
  Support URI: https://вашсайт.ru/support
*/

// Подключение необходимых файлов
require_once osc_plugins_path() . osc_plugin_folder(__FILE__) . 'model/ModelName.php';
require_once osc_plugins_path() . osc_plugin_folder(__FILE__) . 'functions.php';
require_once osc_plugins_path() . osc_plugin_folder(__FILE__) . 'email.php';

// Подключение стилей и скриптов
function plugin_styles() {
    osc_enqueue_style('plugin-style', osc_base_url() . 'oc-content/plugins/plugin_name/css/style.css');
    osc_register_script('plugin-script', osc_base_url() . 'oc-content/plugins/plugin_name/js/script.js', array('jquery'));
    osc_enqueue_script('plugin-script');
}
osc_add_hook('header', 'plugin_styles');

// Регистрация маршрутов
osc_add_route('plugin-page', 'user/plugin', 'user/plugin', osc_plugin_folder(__FILE__) . 'user/dashboard.php', true, 'plugin', 'dashboard', __('Plugin Page', 'plugin'));

// Установка/удаление
function plugin_after_install() {
    ModelName::newInstance()->install();
}
osc_register_plugin(osc_plugin_path(__FILE__), 'plugin_after_install');

function plugin_after_uninstall() {
    ModelName::newInstance()->uninstall();
}
osc_add_hook(osc_plugin_path(__FILE__) . '_uninstall', 'plugin_after_uninstall');

// Регистрация хуков
function plugin_init() {
    osc_add_hook('hook_name', 'plugin_function_name');
    osc_add_hook('ajax_plugin_action', 'plugin_ajax_handler');
}
plugin_init();
?>

Основные концепции разработки плагинов

1. Работа с хуками (Hooks)

В Osclass хуки регистрируются в index.php, а функции-обработчики располагаются в functions.php:

// В index.php - регистрация хуков
osc_add_hook('init', 'plugin_init_function');
osc_add_hook('admin_menu_init', 'plugin_admin_menu');
osc_add_hook('ajax_plugin_action', 'plugin_ajax_handler');

// В functions.php - реализация функций
function plugin_init_function() {
    // Ваш код здесь
}

function plugin_admin_menu() {
    echo '<h3><a href="#">Plugin Menu</a></h3>
    <ul>
        <li><a href="' . osc_admin_render_plugin_url('plugin_name/admin/configure.php') . '">' . __('Settings', 'plugin') . '</a></li>
    </ul>';
}
osc_add_hook('admin_menu', 'plugin_admin_menu', 1);

2. AJAX-обработка

Правильный подход к AJAX в Osclass:

// В functions.php
function plugin_ajax_handler() {
    if(!osc_is_web_user_logged_in()) {
        echo json_encode(array('status' => 'error', 'message' => 'Please login'));
        exit;
    }
    
    $action = Params::getParam('action');
    $user_id = Params::getParam('user_id');
    
    // Ваша логика
    
    echo json_encode(array('status' => 'success', 'message' => 'Done'));
    exit;
}

Внимание: Хуки для AJAX регистрируются в index.php без префикса ajax_:

// index.php
osc_add_hook('ajax_plugin_action', 'plugin_ajax_handler');

Вызов AJAX:

$.ajax({
    url: osc_base_url + 'index.php?page=ajax&action=runhook&hook=ajax_plugin_action',
    type: 'POST',
    data: { action: 'follow', user_id: userId },
    success: function(response) { console.log(response); }
});

3. Работа с настройками

// Сохранение настроек
osc_set_preference('option_name', $value, 'plugin-name', 'STRING');

// Получение настроек
function plugin_param($name) {
    return osc_get_preference($name, 'plugin-name');
}

// Обновление настроек через форму
function mb_param_update($param_name, $update_param_name, $type = NULL, $plugin_var_name = NULL) {
    // Стандартный обработчик настроек
}

4. Создание административной страницы

// admin/configure.php
<?php
$title = __('Plugin Settings', 'plugin');
plugin_menu($title);

$option = mb_param_update('option', 'plugin_action', 'value', 'plugin-name');

if(Params::getParam('plugin_action') == 'done') {
    message_ok(__('Settings saved', 'plugin'));
}
?>

<div class="mb-body">
    <form action="<?php echo osc_admin_base_url(true); ?>" method="POST">
        <input type="hidden" name="page" value="plugins" />
        <input type="hidden" name="action" value="renderplugin" />
        <input type="hidden" name="file" value="plugin_name/admin/configure.php" />
        <input type="hidden" name="plugin_action" value="done" />
        
        <div class="mb-row">
            <label><?php _e('Option', 'plugin'); ?></label>
            <input type="text" name="option" value="<?php echo $option; ?>" />
        </div>
        
        <button type="submit"><?php _e('Save', 'plugin'); ?></button>
    </form>
</div>

<?php echo plugin_footer(); ?>

5. Работа с базой данных через DAO

// В ModelName.php
public function insertData($user_id, $data) {
    return $this->dao->insert($this->getTable_main(), array(
        'fk_i_user_id' => $user_id,
        's_data' => $data,
        'dt_date' => date('Y-m-d H:i:s')
    ));
}

public function getDataByUser($user_id, $limit = null, $offset = 0) {
    $this->dao->select('*');
    $this->dao->from($this->getTable_main());
    $this->dao->where('fk_i_user_id', $user_id);
    $this->dao->orderby('dt_date DESC');
    
    if($limit != null) {
        $this->dao->limit($offset, $limit);
    }
    
    $result = $this->dao->get();
    return $result ? $result->result() : array();
}

Важные правила разработки

1. Только фигурные скобки

В Osclass НЕ используйте сокращенный синтаксис endifendforeach и т.д.:

// ✅ ПРАВИЛЬНО
<?php if(condition) { ?>
    HTML code
<?php } else { ?>
    HTML code
<?php } ?>

// ❌ НЕПРАВИЛЬНО (WordPress-стиль)
<?php if(condition): ?>
    HTML code
<?php else: ?>
    HTML code
<?php endif; ?>

2. Функции должны быть обернуты в проверку существования

if(!function_exists('mb_param_update')) {
    function mb_param_update($param_name, $update_param_name, $type = NULL, $plugin_var_name = NULL) {
        // Тело функции
    }
}

3. Использование правильных URL

// Для AJAX
osc_base_url() . 'index.php?page=ajax&action=runhook&hook=ajax_plugin_action'

// Для страниц пользователя
osc_route_url('plugin-page-name')

// Для админки
osc_admin_render_plugin_url('plugin_name/admin/page.php')

4. Работа с языковыми файлами

// Функции перевода
__('Text to translate', 'plugin-name')
_e('Text to echo', 'plugin-name')

// В JavaScript передача переводов
var plugin_translations = {
    follow: "<?php echo osc_esc_js(__('Follow', 'plugin')); ?>",
    unfollow: "<?php echo osc_esc_js(__('Unfollow', 'plugin')); ?>"
};

Тестирование плагина

Включение режима отладки

В файле oc-config.php добавьте:

define('OSC_DEBUG', true);
define('OSC_DEBUG_LOG', true);

Логирование 

// Запись в лог
error_log('Plugin debug: ' . print_r($data, true));

// Использование файла логов
$log_file = osc_base_path() . 'oc-content/plugins/plugin_name/debug.log';
file_put_contents($log_file, date('Y-m-d H:i:s') . ' - ' . $message . PHP_EOL, FILE_APPEND);

Заключение

Разработка плагинов для Osclass требует понимания уникальной архитектуры системы. Ключевые отличия от WordPress:

  1. Установка/удаление через модель, а не отдельные файлы

  2. Все хуки регистрируются в index.php

  3. AJAX-хуки должны быть зарегистрированы специальным образом

  4. Только фигурные скобки в шаблонах

  5. Функции должны иметь проверку существования

Следуя этим правилам, вы создадите совместимые и стабильные плагины для Osclass 8.x и PHP 8.

Полезные ресурсы

  • Официальная документация Osclass

  • Примеры плагинов от MB Themes

  • Форумы сообщества Osclass

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

Свободен!

Оцените автора
( Пока оценок нет )
Osclass
Добавить комментарий

Получите скидку на разработку приложения!

Нативное приложение для Osclass. Управление приложением с сайта, поддерживает плагины, все нужные функции из коробки! Заполните заявку и получите лучшее предложение!

Скидка 50% на приложение Android!
32