Поддержка Плагины Не работает динамическое добавление Cron events

  • Решено PavelVino

    (@pavelvino)


    Здравствуйте.
    Пишу плагин Вордпресс, который добавляет пользовательские папки в uploads/ , также он должен чистить выбранную папку по расписанию. Написал кой-какой код. Привожу обработчик POST запроса. Всё работает, кроме главного — wp_schedule_event() .
    Cron работает. записи опубликованные задним числом — публикуются. На странице плагина без пробем получаю список интервалов и задач (только моих там нет). Думаю дело в области видимости, но пробовал регистрируемую функцию очистки подключать в класс плагина — всё равно не работает.

    <?php
    
    require_once '../../../../wp-config.php' ;
    require_once '../../../../wp-load.php' ;
    $host = get_site_url();
    
    include 'int_to_words.php';
    
    if ( isset( $_POST ) && 
        array_key_exists( 'new_task_folder', $_POST) &&
        isset( $_POST['new_task_folder'] ) ) {
    
        if (
            isset( $_POST['new_start'] ) &&
            isset( $_POST['new_period'] )  &&
            !empty( $_POST['new_task_folder']) &&
            !empty( $_POST['new_start'] ) &&
            !empty( $_POST['new_period'] ) &&
            $_POST['new_period'] !== '0'
        ) {
            $new_task_folder = $_POST['new_task_folder'];
            $new_start = $_POST['new_start'];
            $new_start = strtotime( $new_start ) + 10;
            $new_period = $_POST['new_period'];
            $new_period = trim( $new_period );
            $new_period = intval( $new_period );
            $text_period = int_to_words( $new_period ) . '_days'; // Эта функция возвращает например для 125 - one_hundred_twenty_five
            $current_schedules = wp_get_schedules();
            $success = '';
            $errors = '';
            $new_schedule = 'cf_clean_' . $new_task_folder;
            $tasks_list = get_option( 'custom_folders_tasks_list' );
            $tasks_list[] = [ 'task_folder' => $new_task_folder, 'start' => $new_start, 'period' => $new_period, 'log' => [
    
                'last_run'    =>  'never',
    
                'status'      =>  'never',
    
                'files'       =>  0,
    
                'message'     =>  ''
    
            ] ];
            
            if ( !array_key_exists( $text_period, $current_schedules ) ) {
                add_filter( 'cron_schedules', 'cron_add_cf_interval' );
                function cron_add_cf_interval( $schedules ) {
                    $schedules[$text_period] = array(
                        "interval" => 60 * $new_period,
                        "display" => "Every " . strval( $new_period ) . " days"
                    );
                    return $schedules;
                }
            }
            add_action( 'admin_head', 'cf_cron_activation' );
            function cf_cron_activation() {
                if( ! wp_next_scheduled( $new_schedule ) ) {
    /*Проблема ->*/ $event = wp_schedule_event( $new_start, $text_period, $new_schedule, ['folder' => $new_task_folder]); // Здесь проблема - возвращает FALSE
                   }
            }
            add_action( $new_schedule, 'cf_clean_folder' );
            if( $event ) {
                update_option( 'custom_folders_tasks_list', $tasks_list );
                $success = 'Task successfully added!';
            } else {
                $errors = 'Error: Failed to add task.';
            }
        } else {
    
            $errors = 'Error: Check the correctness of the entered data.';
        }
    
        header("Location: " . $host ."/wp-admin/admin.php?page=custom-folders%2Fadmin%2Fcustom-folders-admin-cron-add-display.php&cfsuccess=" . $success  . "&cferrors=" . $errors );
        exit;
    } elseif ( isset( $_POST['task_folder'] ) ) {
    
        $task_folder = $_POST['task_folder'];
        $schedule = 'cf_clean_' . $task_folder;
        $tasks_list = get_option( 'custom_folders_tasks_list' );
        $success = '';
        $errors = '';
    
        foreach ( $tasks_list as $key => $task ) {
    
            if( $task_folder == $task['task_folder'] ) {
                if ( ! wp_next_scheduled( $shedule ) ) {
                    $errors = 'Error: The task was not deleted because it was not found.';
                } else {
                    $timestamp = wp_next_scheduled( $schedule );
                    $unschedule = wp_unschedule_event( $timestamp, $schedule, ['folder' => $task_folder] );
                    unset( $tasks_list[$key] );
                    update_option( 'custom_folders_tasks_list', $tasks_list );
                    $success = 'Task deleted successfully!';
                }
            }
        }
    
        header("Location: " . $host ."/wp-admin/admin.php?page=custom-folders%2Fadmin%2Fcustom-folders-admin-cron-add-display.php&cfsuccess=" . $success  . "&cferrors=" . $errors );
        exit;
    } else {
        exit;
    }
    
    function cf_clean_folder($args){
    
        $uploads_path = "../../../uploads/";
        $start = date( "c" );
        $folder_name = $args["folder"];
        $folder_path = $uploads_path . $folder_name . "/";
    
        if( is_dir( $folder_path ) ) {
            $fc = cf_cron_count_files($folder_path);
            if( $fc > 0 ){
                cf_cron_folders_clean($folder_path);
                add_action( "save_post", "cf_cron_folders_clear" );
                $c = cf_cron_count_files($folder_path);
                if( $c > 0 ){
                    $log = ["status" => "error", "last_run" => $start, "files" => $c, "message" => "Failed to completely clear folder (was: $fc, left: $c)."];
                } else {
                    $log = ["status" => "ok", "last_run" => $start, "files" => $c, "message" => "The folder has been successfully cleaned! Deleted: $fc files."];
                }
            } else {
                $log = ["status" => "ok", "last_run" => $start, "files" => $fc, "message" => "No files found in folder."];
            }
        } else {
            $log = ["status" => "error", "last_run" => $start, "files" => 0, "message" => "Folder not found."];
        }
    
        $tasks_list = get_option( 'custom_folders_tasks_list' );
    
        foreach($tasks_list as $key => $task){
            if ( !empty( $task ) && $task != '' && array_key_exists( 'task_folder', $task ) && $task['task_folder'] === $folder_name ) {
                $tasks_list[$key]['log'] = $log;
                update_option( "custom_folders_tasks_list", $tasks_list );
            }
        }
    }
    
        function cf_cron_folders_clean($folder_path){
            global $wpdb;
            foreach ( glob( $folder_path . "*" ) as $file ) {
                $file_db = cf_cron_create_db_link($file);
                $wpdb->delete( "wp_posts", array("guid" => $file_db) );
                unlink( $file );
            }
        }
    
        function cf_cron_create_db_link($file){
            $host = get_site_url();
            $file = str_replace($uploads_path, "", $file);
            $new_file = $host . "/wp-content/uploads/" . $file;
            return $new_file;
        }
        
        function cf_cron_count_files($folder_path){
            return count( glob( $folder_path . "*" ) );
        } 
        
        
    ?>
    • Тема изменена 5 месяцев назад пользователем PavelVino.
Просмотр 7 ответов — с 1 по 7 (всего 7)
  • Модератор Юрий

    (@yube)

    Пишу плагин Вордпресс

    require_once ‘../../../../wp-config.php’ ;
    require_once ‘../../../../wp-load.php’ ;

    Извините, но так плагины не пишут. Плагин работает в среде wordpress, а потому не требует отдельного подключения ни конфига, ни загрузчика, потому что движок это всё уже подгрузил. Плагин, как правило, представляет собой набор обработчиков хуков API wordpress.

    Если Вы пишете автономный скрипт, пусть даже с частичным подключения движка, add_action/add_filter в нем будут актуальны исключительно во время исполнения этого скрипта, остальные запуски, в т.ч. и wp-cron, ничего о них знать не будут.

    Спасибо. Буду переписывать всё в классы.

    Модератор Юрий

    (@yube)

    Классы тут вообще никаким боком. Обработчик хука может быть вообще анонимной функцией.

    Важно, чтобы плагин был plug in, а не наоборот 🙂

    Понятно. Я извиняюсь, я не очень опытен в данном вопросе, думал wp-cron хранит список задач в своей опции в БД, и достаточно только зарегистрировать задачу.

    Сам плагин загружается в среду WordPress, а это отдельный скрипт-обработчик.

    Модератор Юрий

    (@yube)

    думал wp-cron хранит список задач в своей опции в БД,

    Хранит. Но не задачи, а имена actions (хуков), которые нужно дёрнуть в заданный момент (насколько псевдохрон вообще может что-то сделать вовремя). Если обработчик есть, т.е. в этом процессе выполнено add_action для этого хука, то он выполнится. Поэтому и важно, чтобы плагин был plug in, то есть, чтобы он, точнее, та часть кода, где находится add_action, срабатывал (выполнялся) во время выполнения wp-cron.php.

    Модератор Юрий

    (@yube)

    а это отдельный скрипт-обработчик.

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

    На всякий случай еще раз: в хрон.задачи регистриуется имя хука, на котором висит обработчик. Многие упускают эту «двухэтажность».

Просмотр 7 ответов — с 1 по 7 (всего 7)