Загрузка скрипта с зависимостью, выгрузка зависимости другого скрипта

9

Во-первых, я знаю, что мой вопрос происходит в контексте моей работы с плагином WooCommerce, который обычно делает его не по теме. Тем не менее, я думаю , что мой вопрос относится к wp_enqueue_script, так что, надеюсь, он все еще находится в теме.

Таким образом, WooCommerce регистрирует скрипт на admin_enqueue_scriptsкрючке. Этот скрипт требует кучу зависимостей:

wp_register_script( 'wc-admin-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes' . $suffix . '.js', array( 'jquery', 'jquery-ui-datepicker', 'jquery-ui-sortable', 'accounting', 'round', 'ajax-chosen', 'chosen', 'plupload-all' ), WC_VERSION );

(он ставится специально на страницу post.php и post-new.php для типа сообщения продукта чуть позже в коде)

В пользовательском плагине, который я пишу для работы с WooCommerce, я также загружаю скрипт на тот же хук.

wp_enqueue_script( 'My_Plugin_Metabox', My_Plugin_Class()->plugin_url() . '/assets/js/mnm-write-panel.js', array( 'jquery', 'wc-admin-meta-boxes'), My_Plugin_Class()->version, true );

Если я поставлю в очередь сценарий моего плагина и необъяснимым образом установлю для этого $in_footerпараметра параметр true, сценарий jQuery UI Datepicker не будет загружен (вообще отсутствует в исходном коде), и консоль отобразит соответствующие ошибки сценария.

Если я загружаю свой скрипт в шапку, это не проблема. Если я загружаю свой скрипт без wc-admin-meta-boxesзависимости, то это также решает проблему

Так что мне интересно, почему загрузка моего скрипта в нижний колонтитул влияет на загрузку основного скрипта datepicker? (Я не использую datepicker в моем сценарии вообще.) Или почему отсутствие сценария Woo в качестве зависимости также повлияет на сценарий datepicker? Мне кажется, что скрипт datepicker должен быть загружен независимо от того, что является зависимостью от скрипта metabox Woo, но этого не происходит.

Согласно комментарию Кайзера, я создал следующий плагин MU (откорректированный из комментариев, потому что $GLOBALS['wp_scripts']это объект:

/* Plugin Name: Dump jQUI Dp */ 

add_action( 'shutdown', 'so_dump_query_ui_dependencies' );
function so_dump_query_ui_dependencies() {  
    echo 'Does jQuery UI DatePicker script exist per default in&hellip;?<br>';  
    $s = 'jquery-ui-datepicker';    
    printf( 'The registered Dependencies Array: %s', isset( $GLOBALS['wp_scripts']->registered[ $s ] ) ? 'yep ' : 'nope ' );    
    printf( 'The Dependencies loaded in the footer: %s', isset( $GLOBALS['wp_scripts']->in_footer[ $s ] ) ? 'yep ' : 'nope ' );     
    printf( 'The Dependencies printed to the DOM: %s', isset( $GLOBALS['wp_scripts']->done[ $s ] ) ? 'yep ' : 'nope ' );    
    echo 'All nope? Well, then&hellip;'; 
}

Если активен только WooCommerce 2.2.8, результат будет выглядеть так:

Массив зарегистрированных зависимостей: yep
Зависимости, загруженные в нижний колонтитул: nope
Зависимости, напечатанные в DOM: nope

С WooCommerce 2.2.8 плюс мой новый плагин "dummy" результат выглядит одинаково (загружен ли мой скрипт в нижний колонтитул или нет):

Массив зарегистрированных зависимостей: yep
Зависимости, загруженные в нижний колонтитул: nope
Зависимости, напечатанные в DOM: nope

Пустышка Плагин

Также, согласно комментариям, есть фиктивный плагин, который, мы надеемся, воспроизведет проблему для других. Я разделся мой существующий плагин всего пути вниз только загрузить скрипт на продукт типа поста администратора страниц. Я все еще вижу загрузку datepicker, когда значение $in_footerfalse и не загружается, когда значение $in_footertrue.

<?php
/*
Plugin Name: WooCommerce Dummy Plugin
Plugin URI: http://wordpress.stackexchange.com/q/168688/6477
Author: helgatheviking
Description: Enqueue a script, miraculously dequeue datepicker
*/


/**
 * The Main My_Dummy_Plugin class
 **/
if ( ! class_exists( 'My_Dummy_Plugin' ) ) :

class My_Dummy_Plugin {

    /**
     * @var My_Dummy_Plugin - the single instance of the class
     */
    protected static $_instance = null;

    /**
     * variables
     */
    public $version = '1.0.0';

    /**
     * Main My_Dummy_Plugin instance.
     *
     * Ensures only one instance of My_Dummy_Plugin is loaded or can be loaded
     *
     * @static
     * @return My_Dummy_Plugin - Main instance
     */
    public static function instance() {
        if ( is_null( self::$_instance ) ) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }


    /**
     * Cloning is forbidden.
     */
    public function __clone() {
        _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?' ) );
    }


    /**
     * Unserializing instances of this class is forbidden.
     */
    public function __wakeup() {
        _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?' ) );
    }


    /**
     * My_Dummy_Plugin Constructor
     *
     * @access  public
     * @return  My_Dummy_Plugin
     */
    public function __construct() {

        add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );

    }


    /*-----------------------------------------------------------------------------------*/
    /* Helper Functions */
    /*-----------------------------------------------------------------------------------*/

    /**
     * Get the plugin url.
     *
     * @return string
     */
    public function plugin_url() {
        return untrailingslashit( plugins_url( '/', __FILE__ ) );
    }


    /**
     * Get the plugin path.
     *
     * @return string
     */
    public function plugin_path() {
        return untrailingslashit( plugin_dir_path( __FILE__ ) );
    }

    /*-----------------------------------------------------------------------------------*/
    /* Load scripts */
    /*-----------------------------------------------------------------------------------*/

    public function admin_scripts() {

        // Get admin screen id
        $screen = get_current_screen();

        // Product post type page only
        if ( in_array( $screen->id, array( 'product' ) ) ) {

            wp_enqueue_script( 'My_Dummy_Plugin_Metabox', $this->plugin_url() . '/assets/js/metabox.js', array( 'jquery', 'wc-admin-meta-boxes'), $this->version, true );

        }

    }

} //end class: do not remove or there will be no more guacamole for you

endif; // end class_exists check


/**
 * Returns the main instance of My_Dummy_Plugin
 *
 * @return WooCommerce
 */
function My_Dummy_Plugin() {
    return My_Dummy_Plugin::instance();
}

// Launch the whole plugin
My_Dummy_Plugin();
helgatheviking
источник
1
Просто любопытно. Вы пытались установить приоритет ваших действий в очереди ваших сценариев выше или ниже, чем в WooCommerce при очереди в нижнем колонтитуле? Я сталкивался с экземплярами с плагинами, использующими идентичные зависимости, и он отменял регистрацию каждого экземпляра, и по какой-то причине это исправило это. (Я не много думал об этом). Никогда не было разницы между очередями в верхнем и нижнем колонтитуле.
BODA82
Интересно, что случилось со всеми другими комментариями? Во всяком случае, @ BODA82, нет, я не пробовал это. Но добавление приоритета действительно сохраняет загрузку datepicker правильно, даже когда $in_footerэто верно для моего собственного сценария.
Helgatheviking
1
Для меня это похоже на ошибку в WP - я не следовал логике, но если вы посмотрите на функцию do_itemsв "wp-includes / class.wp-dependencies.php", в строках 122-125 код просто сбрасывается элемент в списке to_do, do_itemуспешно или нет Если вы измените эти строки на, if ( $this->do_item( $handle, $group ) ) { $this->done[] = $handle; unset( $this->to_do[$key] ); }то ошибка исчезнет ...
Bonger
2
Это ошибка WP - см. Trac # 25247 . Я предложил патч (gitlost c'est moi).
Бонгер
@bonger Спасибо за точный ответ. Если вы хотите переместить свой комментарий к ответу, я приму его. Видимо, зависимости адские.
helgatheviking

Ответы:

2

В настоящее время вы можете принудительно загрузить библиотеки, используя wp_enqueue_script (), например так:

wp_enqueue_script('jquery');
wp_enqueue_script('jquery-ui');

Я знаю, что он должен загружаться автоматически, но это работает таким образом.

Лео Казейро
источник