close
Skip to content

va-proger/wordpress-migrations-plugin

Repository files navigation

Migrations Plugin

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

WordPress PHP License

📋 Содержание

📖 Описание

Migrations Plugin — это мощный инструмент для управления изменениями базы данных WordPress. Плагин позволяет версионировать изменения структуры БД, автоматически применять их при обновлениях и безопасно откатывать при необходимости.

Зачем нужен этот плагин?

  • Версионирование изменений БД — все изменения структуры базы данных хранятся в виде миграций
  • Автоматическое выполнение — миграции выполняются автоматически при активации/обновлении плагина
  • Безопасный перенос сущностей — перенос постов, пользователей, терминов с проверкой существования
  • Откат изменений — возможность откатить любую миграцию через админ-панель
  • Логирование — полная история выполненных миграций с временем выполнения и ошибками
  • Админ-панель — удобный интерфейс для управления миграциями

🚀 Основные возможности

Управление миграциями

  • ✅ Автоматическое выполнение миграций при активации/обновлении плагина
  • ✅ Ручной запуск миграций через админ-панель
  • ✅ Откат миграций (rollback) в обратном порядке
  • ✅ Логирование всех выполненных миграций
  • ✅ Отслеживание статуса выполнения (completed/failed)
  • ✅ Обработка ошибок с детальными сообщениями

Безопасный перенос сущностей WordPress

  • Перенос постов с проверкой существования по ID, slug, мета-полям
  • Перенос пользователей с автоматическим обновлением существующих
  • Перенос терминов (категории, теги, таксономии)
  • Проверка существования таблиц и колонок перед созданием
  • Обновление существующих элементов вместо создания дубликатов
  • Выбор элементов для миграции через Entity_Selector
  • Поддержка мета-данных и терминов при переносе

Безопасность

  • ✅ Защита от SQL Injection (использование $wpdb->prepare())
  • ✅ Защита от XSS (экранирование всех выходных данных)
  • ✅ Защита от CSRF (проверка nonce для всех действий)
  • ✅ Защита от Local File Inclusion
  • ✅ Проверка прав доступа для всех административных функций
  • ✅ Валидация всех входных данных

Подробный отчет о безопасности см. в SECURITY.md

📦 Установка

Требования

  • WordPress 5.0 или выше
  • PHP 7.2 или выше
  • MySQL 5.6 или выше

Шаги установки

  1. Скачайте плагин

    # Скопируйте папку migrations-plugin в wp-content/plugins/
  2. Активируйте плагин

    • Перейдите в ПлагиныУстановленные плагины
    • Найдите "Migrations Plugin"
    • Нажмите Активировать
  3. Проверьте настройки

    • Перейдите в ИнструментыМиграции
    • Убедитесь, что таблица миграций создана

🎯 Быстрый старт

Создание первой миграции

  1. Создайте файл миграции в папке migrations/:

    <?php
    // migrations/001_create_example_table.php
    class Migration_001_Create_Example_Table {
        public function up() {
            global $wpdb;
            
            $table_name = $wpdb->prefix . 'example_table';
            $charset_collate = $wpdb->get_charset_collate();
            
            $sql = "CREATE TABLE IF NOT EXISTS $table_name (
                id bigint(20) NOT NULL AUTO_INCREMENT,
                name varchar(255) NOT NULL,
                created_at datetime DEFAULT CURRENT_TIMESTAMP,
                PRIMARY KEY (id)
            ) $charset_collate;";
            
            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
            dbDelta($sql);
        }
        
        public function down() {
            global $wpdb;
            $table_name = $wpdb->prefix . 'example_table';
            $wpdb->query("DROP TABLE IF EXISTS $table_name");
        }
    }
  2. Запустите миграцию

    • Перейдите в ИнструментыМиграции
    • Нажмите "Запустить все миграции" или "Запустить" для конкретной миграции

Безопасный перенос поста

<?php
$post_data = array(
    'post_title' => 'Название поста',
    'post_name' => 'post-slug',
    'post_content' => 'Содержимое',
    'post_status' => 'publish',
    'post_type' => 'post',
    'meta' => array(
        'custom_field' => 'значение',
    ),
);

$result = Entity_Migrator::migrate_post($post_data, array(
    'update_if_exists' => true, // Обновлять если существует
));

if ($result['success']) {
    echo "Действие: " . $result['action']; // 'created', 'updated' или 'skipped'
    echo "ID поста: " . $result['post_id'];
}

📚 Документация

Плагин включает подробную документацию:

  • MIGRATIONS_GUIDE.md — Руководство по созданию миграций

    • Что должно и не должно попадать в миграции
    • Принципы написания миграций
    • Примеры правильных миграций
    • Чеклист перед созданием миграции
  • ENTITY_MIGRATION_GUIDE.md — Руководство по миграции сущностей

    • Безопасный перенос постов, пользователей, терминов
    • Проверка существования элементов
    • Массовый импорт с выбором элементов
    • Примеры использования Entity_Migrator и Entity_Selector
  • ADMIN_UI_GUIDE.md — Руководство по админ-панели

    • Интерфейс управления миграциями
    • Запуск и откат миграций
    • Просмотр логов выполнения
  • SECURITY.md — Отчет о безопасности

    • Защита от SQL Injection
    • Защита от XSS
    • Защита от CSRF
    • Проверка прав доступа

💡 Примеры использования

Пример 1: Создание таблицы

<?php
class Migration_002_Create_Products_Table {
    public function up() {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'products';
        $charset_collate = $wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE IF NOT EXISTS $table_name (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            name varchar(255) NOT NULL,
            price decimal(10,2) NOT NULL,
            description text,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY idx_name (name)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }
    
    public function down() {
        global $wpdb;
        $table_name = $wpdb->prefix . 'products';
        $wpdb->query("DROP TABLE IF EXISTS $table_name");
    }
}

Пример 2: Добавление колонки с проверкой

<?php
class Migration_003_Add_Status_Column {
    public function up() {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'products';
        
        // Проверяем существование колонки
        $column_exists = $wpdb->get_results(
            $wpdb->prepare(
                "SHOW COLUMNS FROM {$table_name} LIKE %s",
                'status'
            )
        );
        
        if (empty($column_exists)) {
            $wpdb->query("ALTER TABLE $table_name ADD COLUMN status varchar(50) DEFAULT 'active'");
        }
    }
    
    public function down() {
        global $wpdb;
        $table_name = $wpdb->prefix . 'products';
        
        $column_exists = $wpdb->get_results(
            $wpdb->prepare(
                "SHOW COLUMNS FROM {$table_name} LIKE %s",
                'status'
            )
        );
        
        if (!empty($column_exists)) {
            $wpdb->query("ALTER TABLE $table_name DROP COLUMN status");
        }
    }
}

Пример 3: Безопасное создание таблицы через Entity_Migrator

<?php
class Migration_004_Safe_Create_Table {
    public function up() {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'custom_data';
        $charset_collate = $wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE IF NOT EXISTS $table_name (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            post_id bigint(20) NOT NULL,
            custom_value varchar(255),
            PRIMARY KEY (id),
            KEY idx_post_id (post_id)
        ) $charset_collate;";
        
        $result = Entity_Migrator::safe_create_table($table_name, $sql);
        
        if (!$result['success']) {
            throw new Exception('Не удалось создать таблицу');
        }
        
        // Безопасное добавление колонки
        if (!Entity_Migrator::column_exists($table_name, 'status')) {
            Entity_Migrator::safe_add_column(
                $table_name,
                'status',
                "varchar(50) DEFAULT 'active'"
            );
        }
    }
    
    public function down() {
        global $wpdb;
        $table_name = $wpdb->prefix . 'custom_data';
        if (Entity_Migrator::table_exists($table_name)) {
            $wpdb->query("DROP TABLE IF EXISTS $table_name");
        }
    }
}

Пример 4: Массовый импорт постов

<?php
class Migration_005_Import_Posts {
    public function up() {
        // Получаем посты для импорта
        $posts = Entity_Selector::get_posts_for_migration(array(
            'post_type' => 'product',
            'post_status' => 'publish',
            'numberposts' => 10,
        ));
        
        foreach ($posts as $post_data) {
            unset($post_data['ID']); // Убираем ID для безопасного импорта
            
            $result = Entity_Migrator::migrate_post($post_data, array(
                'update_if_exists' => true,
                'update_meta' => true,
                'update_terms' => true,
            ));
            
            if (!$result['success']) {
                error_log('Ошибка импорта поста: ' . $result['error']);
            }
        }
    }
    
    public function down() {
        // Откат миграции
        // Удаление импортированных постов
    }
}

🔌 API и хуки

Хуки для других плагинов

// Запустить все миграции
do_action('migrations_plugin_run');

// Откатить все миграции
do_action('migrations_plugin_rollback');

Фильтры

// Изменить путь к папке с миграциями
add_filter('migrations_plugin_dir', function($dir) {
    return get_template_directory() . '/migrations/';
});

Программное выполнение

$runner = new Migration_Runner();

// Запустить все миграции
$results = $runner->run();

// Запустить конкретную миграцию
$results = $runner->run('001_example_migration');

// Откатить все миграции
$results = $runner->rollback();

// Откатить конкретную миграцию
$results = $runner->rollback('001_example_migration');

🔒 Безопасность

Плагин соответствует стандартам безопасности WordPress:

  • Защита от SQL Injection — все запросы используют $wpdb->prepare()
  • Защита от XSS — все выходные данные экранируются
  • Защита от CSRF — проверка nonce для всех действий
  • Защита от Local File Inclusion — валидация путей к файлам
  • Проверка прав доступаcurrent_user_can() для всех административных функций
  • Валидация входных данных — санитизация всех пользовательских данных

Подробный отчет о безопасности см. в SECURITY.md

📋 Требования

  • WordPress: 5.0 или выше
  • PHP: 7.2 или выше
  • MySQL: 5.6 или выше
  • Права доступа: Администратор для управления миграциями

📁 Структура проекта

migrations-plugin/
├── migrations/                    # Папка с миграциями
│   ├── 001_example_migration.php
│   └── ...
├── includes/                      # Основные классы
│   ├── class-migrations.php       # Главный класс плагина
│   ├── class-migration-runner.php # Выполнение миграций
│   ├── class-entity-migrator.php # Перенос сущностей
│   ├── class-entity-selector.php # Выбор элементов
│   ├── class-export-loader.php   # Загрузка экспортов
│   └── class-backup.php          # Резервное копирование
├── admin/                        # Админ-панель
│   └── class-migrations-admin.php # Интерфейс управления
├── exports/                      # Экспорты данных
├── backups/                      # Резервные копии
├── migrations-plugin.php         # Главный файл плагина
├── README.md                     # Документация
├── MIGRATIONS_GUIDE.md           # Руководство по миграциям
├── ENTITY_MIGRATION_GUIDE.md     # Руководство по переносу сущностей
├── ADMIN_UI_GUIDE.md             # Руководство по админ-панели
└── SECURITY.md                   # Отчет о безопасности

🗄️ Структура базы данных

Плагин создает таблицу wp_migrations_log для хранения информации о выполненных миграциях:

Колонка Тип Описание
id bigint(20) ID записи
migration_name varchar(255) Имя миграции
migration_file varchar(255) Имя файла миграции
executed_at datetime Дата и время выполнения
execution_time decimal(10,4) Время выполнения в секундах
status varchar(20) Статус (completed/failed)
error_message text Сообщение об ошибке (если есть)

🎓 Именование миграций

Правила именования

  • Файл: 001_descriptive_name.php
  • Класс: Migration_001_Descriptive_Name

Имя класса формируется автоматически:

  • Префикс Migration_
  • Номер из имени файла
  • Каждое слово с заглавной буквы, разделено подчеркиванием

Примеры

  • Файл: 001_create_users_table.php → Класс: Migration_001_Create_Users_Table
  • Файл: 002_add_status_column.php → Класс: Migration_002_Add_Status_Column
  • Файл: 003_migrate_old_data.php → Класс: Migration_003_Migrate_Old_Data

⚙️ Настройка

Изменение пути к миграциям

add_filter('migrations_plugin_dir', function($dir) {
    return get_template_directory() . '/custom-migrations/';
});

Автоматический запуск при обновлении

Миграции автоматически выполняются:

  • При активации плагина
  • При обновлении версии плагина (изменение MIGRATIONS_PLUGIN_VERSION)

🐛 Отладка

Включение логирования

// В wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);

Просмотр логов миграций

  1. Перейдите в ИнструментыМиграции
  2. Просмотрите список выполненных миграций
  3. Нажмите на миграцию для просмотра деталей

📝 Changelog

1.0.0

  • Первый релиз
  • Автоматическое выполнение миграций
  • Ручной запуск и откат через админ-панель
  • Безопасный перенос сущностей WordPress
  • Логирование выполненных миграций
  • Полная документация

🤝 Поддержка

Для вопросов и предложений создавайте issue в репозитории проекта.

📄 Лицензия

GPL v2 or later

Copyright (c) 2024

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

👤 Автор

VP


Важно: Перед выполнением миграций на продакшн-сервере всегда делайте резервную копию базы данных!

About

No description, website, or topics provided.

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors