Make WordPress Core

Ticket #21170: 21170.13.diff

File 21170.13.diff, 31.2 KB (added by adamsilverstein, 8 years ago)
  • Gruntfile.js

    diff --git Gruntfile.js Gruntfile.js
    index 2c213492a8..2c68babb99 100644
    module.exports = function(grunt) { 
    354354                                        '!wp-includes/js/json2.js',
    355355                                        '!wp-includes/js/tw-sack.js',
    356356                                        '!wp-includes/js/twemoji.js',
    357                                         '!**/*.min.js'
     357                                        '!**/*.min.js',
     358                                        '!wp-includes/js/wp-hooks.js'
    358359                                ],
    359360                                // Remove once other JSHint errors are resolved
    360361                                options: {
  • new file src/wp-includes/js/wp-hooks.js

    diff --git src/wp-includes/js/wp-hooks.js src/wp-includes/js/wp-hooks.js
    new file mode 100644
    index 0000000000..572719c6f4
    - +  
     1this["wp"] = this["wp"] || {}; this["wp"]["hooks"] =
     2/******/ (function(modules) { // webpackBootstrap
     3/******/        // The module cache
     4/******/        var installedModules = {};
     5/******/
     6/******/        // The require function
     7/******/        function __webpack_require__(moduleId) {
     8/******/
     9/******/                // Check if module is in cache
     10/******/                if(installedModules[moduleId]) {
     11/******/                        return installedModules[moduleId].exports;
     12/******/                }
     13/******/                // Create a new module (and put it into the cache)
     14/******/                var module = installedModules[moduleId] = {
     15/******/                        i: moduleId,
     16/******/                        l: false,
     17/******/                        exports: {}
     18/******/                };
     19/******/
     20/******/                // Execute the module function
     21/******/                modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
     22/******/
     23/******/                // Flag the module as loaded
     24/******/                module.l = true;
     25/******/
     26/******/                // Return the exports of the module
     27/******/                return module.exports;
     28/******/        }
     29/******/
     30/******/
     31/******/        // expose the modules object (__webpack_modules__)
     32/******/        __webpack_require__.m = modules;
     33/******/
     34/******/        // expose the module cache
     35/******/        __webpack_require__.c = installedModules;
     36/******/
     37/******/        // define getter function for harmony exports
     38/******/        __webpack_require__.d = function(exports, name, getter) {
     39/******/                if(!__webpack_require__.o(exports, name)) {
     40/******/                        Object.defineProperty(exports, name, {
     41/******/                                configurable: false,
     42/******/                                enumerable: true,
     43/******/                                get: getter
     44/******/                        });
     45/******/                }
     46/******/        };
     47/******/
     48/******/        // getDefaultExport function for compatibility with non-harmony modules
     49/******/        __webpack_require__.n = function(module) {
     50/******/                var getter = module && module.__esModule ?
     51/******/                        function getDefault() { return module['default']; } :
     52/******/                        function getModuleExports() { return module; };
     53/******/                __webpack_require__.d(getter, 'a', getter);
     54/******/                return getter;
     55/******/        };
     56/******/
     57/******/        // Object.prototype.hasOwnProperty.call
     58/******/        __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
     59/******/
     60/******/        // __webpack_public_path__
     61/******/        __webpack_require__.p = "";
     62/******/
     63/******/        // Load entry module and return exports
     64/******/        return __webpack_require__(__webpack_require__.s = 2);
     65/******/ })
     66/************************************************************************/
     67/******/ ([
     68/* 0 */
     69/***/ (function(module, exports, __webpack_require__) {
     70
     71"use strict";
     72
     73
     74Object.defineProperty(exports, "__esModule", {
     75        value: true
     76});
     77/**
     78 * Validate a hook name.
     79 *
     80 * @param  {string} hookName The hook name to validate.
     81 *
     82 * @return {bool}            Whether the hook name is valid.
     83 */
     84function validateHookName(hookName) {
     85
     86        if ('string' !== typeof hookName) {
     87                console.error('The hook name must be a string.');
     88                return false;
     89        }
     90
     91        if (/^__/.test(hookName)) {
     92                console.error('The hook name cannot begin with `__`.');
     93                return false;
     94        }
     95
     96        if (!/^[a-z][a-z0-9_.-]*$/.test(hookName)) {
     97                console.error('The hook name can only contain numbers, letters, dashes, periods and underscores.');
     98                return false;
     99        }
     100
     101        return true;
     102}
     103
     104exports.default = validateHookName;
     105
     106/***/ }),
     107/* 1 */
     108/***/ (function(module, exports, __webpack_require__) {
     109
     110"use strict";
     111
     112
     113Object.defineProperty(exports, "__esModule", {
     114        value: true
     115});
     116/**
     117 * Validate a namespace.
     118 *
     119 * @param  {string} namespace The namespace to validate.
     120 *
     121 * @return {bool}             Whether the namespace is valid.
     122 */
     123function validateNamespace(namespace) {
     124
     125        if ('string' !== typeof namespace) {
     126                console.error('The namespace must be a string.');
     127                return false;
     128        }
     129
     130        if (!/^.*\/.*$/.test(namespace)) {
     131                console.error('The namespace must take the form `my-plugin-slug/functionDescription');
     132                return false;
     133        }
     134
     135        return true;
     136}
     137
     138exports.default = validateNamespace;
     139
     140/***/ }),
     141/* 2 */
     142/***/ (function(module, exports, __webpack_require__) {
     143
     144"use strict";
     145
     146
     147Object.defineProperty(exports, "__esModule", {
     148  value: true
     149});
     150exports.didFilter = exports.didAction = exports.doingFilter = exports.doingAction = exports.currentFilter = exports.currentAction = exports.applyFilters = exports.doAction = exports.removeAllFilters = exports.removeAllActions = exports.hasFilter = exports.hasAction = exports.removeFilter = exports.removeAction = exports.addFilter = exports.addAction = undefined;
     151
     152var _hooks = __webpack_require__(3);
     153
     154var _hooks2 = _interopRequireDefault(_hooks);
     155
     156var _createAddHook = __webpack_require__(4);
     157
     158var _createAddHook2 = _interopRequireDefault(_createAddHook);
     159
     160var _createRemoveHook = __webpack_require__(5);
     161
     162var _createRemoveHook2 = _interopRequireDefault(_createRemoveHook);
     163
     164var _createHasHook = __webpack_require__(6);
     165
     166var _createHasHook2 = _interopRequireDefault(_createHasHook);
     167
     168var _createRunHook = __webpack_require__(7);
     169
     170var _createRunHook2 = _interopRequireDefault(_createRunHook);
     171
     172var _createCurrentHook = __webpack_require__(8);
     173
     174var _createCurrentHook2 = _interopRequireDefault(_createCurrentHook);
     175
     176var _createDoingHook = __webpack_require__(9);
     177
     178var _createDoingHook2 = _interopRequireDefault(_createDoingHook);
     179
     180var _createDidHook = __webpack_require__(10);
     181
     182var _createDidHook2 = _interopRequireDefault(_createDidHook);
     183
     184function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
     185
     186// Add action/filter functions.
     187var addAction = exports.addAction = (0, _createAddHook2.default)(_hooks2.default.actions);
     188var addFilter = exports.addFilter = (0, _createAddHook2.default)(_hooks2.default.filters);
     189
     190// Remove action/filter functions.
     191var removeAction = exports.removeAction = (0, _createRemoveHook2.default)(_hooks2.default.actions);
     192var removeFilter = exports.removeFilter = (0, _createRemoveHook2.default)(_hooks2.default.filters);
     193
     194// Has action/filter functions.
     195var hasAction = exports.hasAction = (0, _createHasHook2.default)(_hooks2.default.actions);
     196var hasFilter = exports.hasFilter = (0, _createHasHook2.default)(_hooks2.default.filters);
     197
     198// Remove all actions/filters functions.
     199var removeAllActions = exports.removeAllActions = (0, _createRemoveHook2.default)(_hooks2.default.actions, true);
     200var removeAllFilters = exports.removeAllFilters = (0, _createRemoveHook2.default)(_hooks2.default.filters, true);
     201
     202// Do action/apply filters functions.
     203var doAction = exports.doAction = (0, _createRunHook2.default)(_hooks2.default.actions);
     204var applyFilters = exports.applyFilters = (0, _createRunHook2.default)(_hooks2.default.filters, true);
     205
     206// Current action/filter functions.
     207var currentAction = exports.currentAction = (0, _createCurrentHook2.default)(_hooks2.default.actions);
     208var currentFilter = exports.currentFilter = (0, _createCurrentHook2.default)(_hooks2.default.filters);
     209
     210// Doing action/filter: true while a hook is being run.
     211var doingAction = exports.doingAction = (0, _createDoingHook2.default)(_hooks2.default.actions);
     212var doingFilter = exports.doingFilter = (0, _createDoingHook2.default)(_hooks2.default.filters);
     213
     214// Did action/filter functions.
     215var didAction = exports.didAction = (0, _createDidHook2.default)(_hooks2.default.actions);
     216var didFilter = exports.didFilter = (0, _createDidHook2.default)(_hooks2.default.filters);
     217
     218/***/ }),
     219/* 3 */
     220/***/ (function(module, exports, __webpack_require__) {
     221
     222"use strict";
     223
     224
     225Object.defineProperty(exports, "__esModule", {
     226  value: true
     227});
     228/**
     229 * Contains the registered hooks, keyed by hook type. Each hook type is an
     230 * array of objects with priority and callback of each registered hook.
     231 */
     232var HOOKS = {
     233  actions: {},
     234  filters: {}
     235};
     236
     237exports.default = HOOKS;
     238
     239/***/ }),
     240/* 4 */
     241/***/ (function(module, exports, __webpack_require__) {
     242
     243"use strict";
     244
     245
     246Object.defineProperty(exports, "__esModule", {
     247        value: true
     248});
     249
     250var _validateNamespace = __webpack_require__(1);
     251
     252var _validateNamespace2 = _interopRequireDefault(_validateNamespace);
     253
     254var _validateHookName = __webpack_require__(0);
     255
     256var _validateHookName2 = _interopRequireDefault(_validateHookName);
     257
     258function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
     259
     260/**
     261 * Returns a function which, when invoked, will add a hook.
     262 *
     263 * @param  {Object}   hooks Stored hooks, keyed by hook name.
     264 *
     265 * @return {Function}       Function that adds a new hook.
     266 */
     267function createAddHook(hooks) {
     268        /**
     269  * Adds the hook to the appropriate hooks container.
     270  *
     271  * @param {string}   hookName  Name of hook to add
     272  * @param {string}   namespace The unique namespace identifying the callback in the form `my-plugin-slug/functionDescription`.
     273  * @param {Function} callback  Function to call when the hook is run
     274  * @param {?number}  priority  Priority of this hook (default=10)
     275  */
     276        return function addHook(hookName, namespace, callback) {
     277                var priority = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 10;
     278
     279
     280                if (!(0, _validateHookName2.default)(hookName)) {
     281                        return;
     282                }
     283
     284                if (!(0, _validateNamespace2.default)(namespace)) {
     285                        return;
     286                }
     287
     288                if ('function' !== typeof callback) {
     289                        console.error('The hook callback must be a function.');
     290                        return;
     291                }
     292
     293                // Validate numeric priority
     294                if ('number' !== typeof priority) {
     295                        console.error('If specified, the hook priority must be a number.');
     296                        return;
     297                }
     298
     299                var handler = { callback: callback, priority: priority, namespace: namespace };
     300
     301                if (hooks.hasOwnProperty(hookName)) {
     302                        // Find the correct insert index of the new hook.
     303                        var handlers = hooks[hookName].handlers;
     304                        var i = 0;
     305                        while (i < handlers.length) {
     306                                if (handlers[i].priority > priority) {
     307                                        break;
     308                                }
     309                                i++;
     310                        }
     311                        // Insert (or append) the new hook.
     312                        handlers.splice(i, 0, handler);
     313                        // We may also be currently executing this hook.  If the callback
     314                        // we're adding would come after the current callback, there's no
     315                        // problem; otherwise we need to increase the execution index of
     316                        // any other runs by 1 to account for the added element.
     317                        (hooks.__current || []).forEach(function (hookInfo) {
     318                                if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
     319                                        hookInfo.currentIndex++;
     320                                }
     321                        });
     322                } else {
     323                        // This is the first hook of its type.
     324                        hooks[hookName] = {
     325                                handlers: [handler],
     326                                runs: 0
     327                        };
     328                }
     329        };
     330}
     331
     332exports.default = createAddHook;
     333
     334/***/ }),
     335/* 5 */
     336/***/ (function(module, exports, __webpack_require__) {
     337
     338"use strict";
     339
     340
     341Object.defineProperty(exports, "__esModule", {
     342        value: true
     343});
     344
     345var _validateNamespace = __webpack_require__(1);
     346
     347var _validateNamespace2 = _interopRequireDefault(_validateNamespace);
     348
     349var _validateHookName = __webpack_require__(0);
     350
     351var _validateHookName2 = _interopRequireDefault(_validateHookName);
     352
     353function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
     354
     355/**
     356 * Returns a function which, when invoked, will remove a specified hook or all
     357 * hooks by the given name.
     358 *
     359 * @param  {Object}   hooks      Stored hooks, keyed by hook name.
     360 * @param  {bool}     removeAll  Whether to remove all callbacks for a hookName, without regard to namespace. Used to create `removeAll*` functions.
     361 *
     362 * @return {Function}            Function that removes hooks.
     363 */
     364function createRemoveHook(hooks, removeAll) {
     365        /**
     366  * Removes the specified callback (or all callbacks) from the hook with a
     367  * given hookName and namespace.
     368  *
     369  * @param {string}    hookName  The name of the hook to modify.
     370  * @param {string}    namespace The unique namespace identifying the callback in the form `my-plugin-slug/functionDescription`.
     371  *
     372  * @return {number}             The number of callbacks removed.
     373  */
     374        return function removeHook(hookName, namespace) {
     375
     376                if (!(0, _validateHookName2.default)(hookName)) {
     377                        return;
     378                }
     379                if (!removeAll && !(0, _validateNamespace2.default)(namespace)) {
     380                        return;
     381                }
     382
     383                // Bail if no hooks exist by this name
     384                if (!hooks.hasOwnProperty(hookName)) {
     385                        return 0;
     386                }
     387
     388                var handlersRemoved = 0;
     389
     390                if (removeAll) {
     391                        handlersRemoved = hooks[hookName].handlers.length;
     392                        hooks[hookName] = {
     393                                runs: hooks[hookName].runs,
     394                                handlers: []
     395                        };
     396                } else {
     397                        // Try to find the specified callback to remove.
     398                        var handlers = hooks[hookName].handlers;
     399
     400                        var _loop = function _loop(i) {
     401                                if (handlers[i].namespace === namespace) {
     402                                        handlers.splice(i, 1);
     403                                        handlersRemoved++;
     404                                        // This callback may also be part of a hook that is
     405                                        // currently executing.  If the callback we're removing
     406                                        // comes after the current callback, there's no problem;
     407                                        // otherwise we need to decrease the execution index of any
     408                                        // other runs by 1 to account for the removed element.
     409                                        (hooks.__current || []).forEach(function (hookInfo) {
     410                                                if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
     411                                                        hookInfo.currentIndex--;
     412                                                }
     413                                        });
     414                                }
     415                        };
     416
     417                        for (var i = handlers.length - 1; i >= 0; i--) {
     418                                _loop(i);
     419                        }
     420                }
     421
     422                return handlersRemoved;
     423        };
     424}
     425
     426exports.default = createRemoveHook;
     427
     428/***/ }),
     429/* 6 */
     430/***/ (function(module, exports, __webpack_require__) {
     431
     432"use strict";
     433
     434
     435Object.defineProperty(exports, "__esModule", {
     436        value: true
     437});
     438/**
     439 * Returns a function which, when invoked, will return whether any handlers are
     440 * attached to a particular hook.
     441 *
     442 * @param  {Object}   hooks Stored hooks, keyed by hook name.
     443 *
     444 * @return {Function}       Function that returns whether any handlers are
     445 *                          attached to a particular hook.
     446 */
     447function createHasHook(hooks) {
     448        /**
     449  * Returns how many handlers are attached for the given hook.
     450  *
     451  * @param  {string}  hookName The name of the hook to check for.
     452  *
     453  * @return {number}           The number of handlers that are attached to
     454  *                            the given hook.
     455  */
     456        return function hasHook(hookName) {
     457                return hooks.hasOwnProperty(hookName) ? hooks[hookName].handlers.length : 0;
     458        };
     459}
     460
     461exports.default = createHasHook;
     462
     463/***/ }),
     464/* 7 */
     465/***/ (function(module, exports, __webpack_require__) {
     466
     467"use strict";
     468
     469
     470Object.defineProperty(exports, "__esModule", {
     471        value: true
     472});
     473
     474var _validateHookName = __webpack_require__(0);
     475
     476var _validateHookName2 = _interopRequireDefault(_validateHookName);
     477
     478function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
     479
     480/**
     481 * Returns a function which, when invoked, will execute all callbacks
     482 * registered to a hook of the specified type, optionally returning the final
     483 * value of the call chain.
     484 *
     485 * @param  {Object}   hooks          Stored hooks, keyed by hook name.
     486 * @param  {?bool}    returnFirstArg Whether each hook callback is expected to
     487 *                                   return its first argument.
     488 *
     489 * @return {Function}                Function that runs hook callbacks.
     490 */
     491function createRunHook(hooks, returnFirstArg) {
     492        /**
     493  * Runs all callbacks for the specified hook.
     494  *
     495  * @param  {string} hookName The name of the hook to run.
     496  * @param  {...*}   args     Arguments to pass to the hook callbacks.
     497  *
     498  * @return {*}               Return value of runner, if applicable.
     499  */
     500        return function runHooks(hookName) {
     501
     502                if (!(0, _validateHookName2.default)(hookName)) {
     503                        return;
     504                }
     505
     506                if (!hooks.hasOwnProperty(hookName)) {
     507                        hooks[hookName] = {
     508                                runs: 0,
     509                                handlers: []
     510                        };
     511                }
     512
     513                var handlers = hooks[hookName].handlers;
     514
     515                for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
     516                        args[_key - 1] = arguments[_key];
     517                }
     518
     519                if (!handlers.length) {
     520                        return returnFirstArg ? args[0] : undefined;
     521                }
     522
     523                var hookInfo = {
     524                        name: hookName,
     525                        currentIndex: 0
     526                };
     527
     528                hooks.__current = hooks.__current || [];
     529                hooks.__current.push(hookInfo);
     530                hooks[hookName].runs++;
     531
     532                var maybeReturnValue = args[0];
     533
     534                while (hookInfo.currentIndex < handlers.length) {
     535                        var handler = handlers[hookInfo.currentIndex];
     536                        maybeReturnValue = handler.callback.apply(null, args);
     537                        if (returnFirstArg) {
     538                                args[0] = maybeReturnValue;
     539                        }
     540                        hookInfo.currentIndex++;
     541                }
     542
     543                hooks.__current.pop();
     544
     545                if (returnFirstArg) {
     546                        return maybeReturnValue;
     547                }
     548        };
     549}
     550
     551exports.default = createRunHook;
     552
     553/***/ }),
     554/* 8 */
     555/***/ (function(module, exports, __webpack_require__) {
     556
     557"use strict";
     558
     559
     560Object.defineProperty(exports, "__esModule", {
     561        value: true
     562});
     563/**
     564 * Returns a function which, when invoked, will return the name of the
     565 * currently running hook, or `null` if no hook of the given type is currently
     566 * running.
     567 *
     568 * @param  {Object}   hooks          Stored hooks, keyed by hook name.
     569 *
     570 * @return {Function}                Function that returns the current hook.
     571 */
     572function createCurrentHook(hooks, returnFirstArg) {
     573        /**
     574  * Returns the name of the currently running hook, or `null` if no hook of
     575  * the given type is currently running.
     576  *
     577  * @return {?string}             The name of the currently running hook, or
     578  *                               `null` if no hook is currently running.
     579  */
     580        return function currentHook() {
     581                if (!hooks.__current || !hooks.__current.length) {
     582                        return null;
     583                }
     584
     585                return hooks.__current[hooks.__current.length - 1].name;
     586        };
     587}
     588
     589exports.default = createCurrentHook;
     590
     591/***/ }),
     592/* 9 */
     593/***/ (function(module, exports, __webpack_require__) {
     594
     595"use strict";
     596
     597
     598Object.defineProperty(exports, "__esModule", {
     599        value: true
     600});
     601/**
     602 * Returns a function which, when invoked, will return whether a hook is
     603 * currently being executed.
     604 *
     605 * @param  {Object}   hooks Stored hooks, keyed by hook name.
     606 *
     607 * @return {Function}       Function that returns whether a hook is currently
     608 *                          being executed.
     609 */
     610function createDoingHook(hooks) {
     611        /**
     612  * Returns whether a hook is currently being executed.
     613  *
     614  * @param  {?string} hookName The name of the hook to check for.  If
     615  *                            omitted, will check for any hook being executed.
     616  *
     617  * @return {bool}             Whether the hook is being executed.
     618  */
     619        return function doingHook(hookName) {
     620                // If the hookName was not passed, check for any current hook.
     621                if ('undefined' === typeof hookName) {
     622                        return 'undefined' !== typeof hooks.__current[0];
     623                }
     624
     625                // Return the __current hook.
     626                return hooks.__current[0] ? hookName === hooks.__current[0].name : false;
     627        };
     628}
     629
     630exports.default = createDoingHook;
     631
     632/***/ }),
     633/* 10 */
     634/***/ (function(module, exports, __webpack_require__) {
     635
     636"use strict";
     637
     638
     639Object.defineProperty(exports, "__esModule", {
     640        value: true
     641});
     642
     643var _validateHookName = __webpack_require__(0);
     644
     645var _validateHookName2 = _interopRequireDefault(_validateHookName);
     646
     647function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
     648
     649/**
     650 * Returns a function which, when invoked, will return the number of times a
     651 * hook has been called.
     652 *
     653 * @param  {Object}   hooks Stored hooks, keyed by hook name.
     654 *
     655 * @return {Function}       Function that returns a hook's call count.
     656 */
     657function createDidHook(hooks) {
     658        /**
     659  * Returns the number of times an action has been fired.
     660  *
     661  * @param  {string} hookName The hook name to check.
     662  *
     663  * @return {number}          The number of times the hook has run.
     664  */
     665        return function didHook(hookName) {
     666
     667                if (!(0, _validateHookName2.default)(hookName)) {
     668                        return;
     669                }
     670
     671                return hooks.hasOwnProperty(hookName) && hooks[hookName].runs ? hooks[hookName].runs : 0;
     672        };
     673}
     674
     675exports.default = createDidHook;
     676
     677/***/ })
     678/******/ ]);
  • src/wp-includes/plugin.php

    diff --git src/wp-includes/plugin.php src/wp-includes/plugin.php
    index 86f1c3b319..86f9db8964 100644
    function doing_filter( $filter = null ) { 
    363363}
    364364
    365365/**
    366  * Retrieve the name of an action currently being processed.
     366 * Retrieve whether action currently being processed.
    367367 *
    368368 * @since 3.9.0
    369369 *
  • src/wp-includes/script-loader.php

    diff --git src/wp-includes/script-loader.php src/wp-includes/script-loader.php
    index 5761dfe3df..37e3350343 100644
    function wp_default_scripts( &$scripts ) { 
    8585
    8686        $scripts->add( 'wp-a11y', "/wp-includes/js/wp-a11y$suffix.js", array( 'jquery' ), false, 1 );
    8787
     88        $scripts->add( 'wp-hooks', "/wp-includes/js/wp-hooks$suffix.js", array(), false, 1 );
     89
    8890        $scripts->add( 'sack', "/wp-includes/js/tw-sack$suffix.js", array(), '1.6.1', 1 );
    8991
    9092        $scripts->add( 'quicktags', "/wp-includes/js/quicktags$suffix.js", array(), false, 1 );
  • tests/qunit/index.html

    diff --git tests/qunit/index.html tests/qunit/index.html
    index 2ca82b3cdd..c3dc94d46c 100644
     
    7777                <script src="../../src/wp-includes/js/customize-base.js"></script>
    7878                <script src="../../src/wp-includes/js/customize-models.js"></script>
    7979                <script src="../../src/wp-includes/js/shortcode.js"></script>
     80                <script src="../../src/wp-includes/js/wp-hooks.js"></script>
    8081                <script src="../../src/wp-admin/js/customize-controls.js"></script>
    8182                <script src="../../src/wp-includes/js/api-request.js"></script>
    8283                <script src="../../src/wp-includes/js/wp-api.js"></script>
     
    125126                <script src="wp-admin/js/customize-header.js"></script>
    126127                <script src="wp-includes/js/shortcode.js"></script>
    127128                <script src="wp-includes/js/api-request.js"></script>
     129                <script src="wp-includes/js/wp-hooks.js"></script>
    128130                <script src="wp-includes/js/wp-api.js"></script>
    129131                <script src="wp-admin/js/customize-controls.js"></script>
    130132                <script src="wp-admin/js/customize-controls-utils.js"></script>
  • new file tests/qunit/wp-includes/js/wp-hooks.js

    diff --git tests/qunit/wp-includes/js/wp-hooks.js tests/qunit/wp-includes/js/wp-hooks.js
    new file mode 100644
    index 0000000000..92b855901e
    - +  
     1/* global wp */
     2( function( QUnit ) {
     3        QUnit.module( 'wp-hooks' );
     4
     5        function filter_a( str ) {
     6                return str + 'a';
     7        }
     8
     9        function filter_b( str ) {
     10                return str + 'b';
     11        }
     12
     13        function filter_c( str ) {
     14                return str + 'c';
     15        }
     16
     17        function action_a() {
     18                window.actionValue += 'a';
     19        }
     20
     21        function action_b() {
     22                window.actionValue += 'b';
     23        }
     24
     25        function action_c() {
     26                window.actionValue += 'c';
     27        }
     28
     29        function filter_check( x ) {
     30                ok( wp.hooks.doingFilter( 'runtest_filter' ), 'The runtest_filter is running.' );
     31                return x;
     32        }
     33
     34        window.actionValue = '';
     35
     36        QUnit.test( 'add and remove a filter', function() {
     37                expect( 1 );
     38                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback', filter_a );
     39                wp.hooks.removeFilter( 'test_filter', 'my_plugin/my_callback'  );
     40                equal( wp.hooks.applyFilters( 'test_filter', 'test' ), 'test' );
     41        } );
     42        QUnit.test( 'add a filter and run it', function() {
     43                expect( 1 );
     44                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_a', filter_a );
     45                equal( wp.hooks.applyFilters( 'test_filter', 'test' ), 'testa' );
     46                wp.hooks.removeAllFilters( 'test_filter' );
     47        } );
     48
     49        QUnit.test( 'add 2 filters in a row and run them', function() {
     50                expect( 1 );
     51                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_a', filter_a );
     52                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_b', filter_b );
     53                equal( wp.hooks.applyFilters( 'test_filter', 'test' ), 'testab' );
     54                wp.hooks.removeAllFilters( 'test_filter' );
     55        } );
     56
     57        QUnit.test( 'add 3 filters with different priorities and run them', function() {
     58                expect( 1 );
     59                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_a', filter_a );
     60                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_b', filter_b, 2 );
     61                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_c', filter_c, 8 );
     62                equal( wp.hooks.applyFilters( 'test_filter', 'test' ), 'testbca' );
     63                wp.hooks.removeAllFilters( 'test_filter' );
     64        } );
     65
     66        QUnit.test( 'add and remove an action', function() {
     67                expect( 1 );
     68                window.actionValue = '';
     69                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', action_a );
     70                wp.hooks.removeAction( 'test_action', 'my_plugin/my_callback' );
     71                wp.hooks.doAction( 'test_action' );
     72                equal( window.actionValue, '' );
     73        } );
     74
     75        QUnit.test( 'add an action and run it', function() {
     76                expect( 1 );
     77                window.actionValue = '';
     78                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', action_a );
     79                wp.hooks.doAction( 'test_action' );
     80                equal( window.actionValue, 'a' );
     81                wp.hooks.removeAllActions( 'test_action' );
     82        } );
     83
     84        QUnit.test( 'add 2 actions in a row and then run them', function() {
     85                expect( 1 );
     86                window.actionValue = '';
     87                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', action_a );
     88                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', action_b );
     89                wp.hooks.doAction( 'test_action' );
     90                equal( window.actionValue, 'ab' );
     91                wp.hooks.removeAllActions( 'test_action' );
     92        } );
     93
     94        QUnit.test( 'add 3 actions with different priorities and run them', function() {
     95                expect( 1 );
     96                window.actionValue = '';
     97                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', action_a );
     98                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', action_b, 2 );
     99                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', action_c, 8 );
     100                wp.hooks.doAction( 'test_action' );
     101                equal( window.actionValue, 'bca' );
     102                wp.hooks.removeAllActions( 'test_action' );
     103        } );
     104
     105        QUnit.test( 'pass in two arguments to an action', function() {
     106                var arg1 = 10,
     107                        arg2 = 20;
     108
     109                expect( 4 );
     110
     111                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', function( a, b ) {
     112                        equal( arg1, a );
     113                        equal( arg2, b );
     114                } );
     115                wp.hooks.doAction( 'test_action', arg1, arg2 );
     116                wp.hooks.removeAllActions( 'test_action' );
     117
     118                equal( arg1, 10 );
     119                equal( arg2, 20 );
     120        } );
     121
     122        QUnit.test( 'fire action multiple times', function() {
     123                var func;
     124                expect( 2 );
     125
     126                func = function() {
     127                        ok( true );
     128                };
     129
     130                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback', func );
     131                wp.hooks.doAction( 'test_action' );
     132                wp.hooks.doAction( 'test_action' );
     133                wp.hooks.removeAllActions( 'test_action' );
     134        } );
     135
     136        QUnit.test( 'remove specific action callback', function() {
     137                window.actionValue = '';
     138                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback_action_a', action_a );
     139                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback_action_b', action_b, 2 );
     140                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback_action_c', action_c, 8 );
     141
     142                wp.hooks.removeAction( 'test_action', 'my_plugin/my_callback_action_b' );
     143                wp.hooks.doAction( 'test_action' );
     144                equal( window.actionValue, 'ca' );
     145                wp.hooks.removeAllActions( 'test_action' );
     146        } );
     147
     148        QUnit.test( 'remove all action callbacks', function() {
     149                window.actionValue = '';
     150                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback_action_a', action_a );
     151                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback_action_b', action_b, 2 );
     152                wp.hooks.addAction( 'test_action', 'my_plugin/my_callback_action_c', action_c, 8 );
     153
     154                wp.hooks.removeAllActions( 'test_action' );
     155                wp.hooks.doAction( 'test_action' );
     156                equal( window.actionValue, '' );
     157        } );
     158
     159        QUnit.test( 'remove specific filter callback', function() {
     160                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_a', filter_a );
     161                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_b', filter_b, 2 );
     162                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_c', filter_c, 8 );
     163
     164                wp.hooks.removeFilter( 'test_filter', 'my_plugin/my_callback_filter_b' );
     165                equal( wp.hooks.applyFilters( 'test_filter', 'test' ), 'testca' );
     166                wp.hooks.removeAllFilters( 'test_filter' );
     167        } );
     168
     169        QUnit.test( 'remove all filter callbacks', function() {
     170                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_a', filter_a );
     171                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_b', filter_b, 2 );
     172                wp.hooks.addFilter( 'test_filter', 'my_plugin/my_callback_filter_c', filter_c, 8 );
     173
     174                wp.hooks.removeAllFilters( 'test_filter' );
     175                equal( wp.hooks.applyFilters( 'test_filter', 'test' ), 'test' );
     176        } );
     177
     178        // Test doingAction, didAction, hasAction.
     179        QUnit.test( 'Test doingAction, didAction and hasAction.', function() {
     180
     181                // Reset state for testing.
     182                wp.hooks.removeAllActions( 'test_action' );
     183                wp.hooks.addAction( 'another_action', 'my_plugin/my_callback', function(){} );
     184                wp.hooks.doAction( 'another_action' );
     185
     186                // Verify no action is running yet.
     187                ok( ! wp.hooks.doingAction( 'newtest_action' ), 'The newtest_action is not running.' );
     188                equal( wp.hooks.didAction( 'newtest_action' ), 0, 'The newtest_action has not run.' );
     189                ok( ! wp.hooks.hasAction( 'newtest_action' ), 'The newtest_action is not registered.' );
     190
     191                wp.hooks.addAction( 'newtest_action', 'my_plugin/my_callback', action_a );
     192
     193                // Verify action added, not running yet.
     194                ok( ! wp.hooks.doingAction( 'newtest_action' ), 'The newtest_action is not running.' );
     195                equal( wp.hooks.didAction( 'newtest_action' ), 0, 'The newtest_action has not run.' );
     196                ok( wp.hooks.hasAction( 'newtest_action' ), 'The newtest_action is registered.' );
     197
     198                wp.hooks.doAction( 'newtest_action' );
     199
     200                // Verify action added and running.
     201                equal( wp.hooks.didAction( 'newtest_action' ), 1, 'The newtest_action has run once.' );
     202                ok( wp.hooks.hasAction( 'newtest_action' ), 'The newtest_action is registered.' );
     203
     204                wp.hooks.doAction( 'newtest_action' );
     205                equal( wp.hooks.didAction( 'newtest_action' ), 2, 'The newtest_action has run twice.' );
     206
     207                wp.hooks.removeAllActions( 'newtest_action' );
     208
     209                // Verify state is reset appropriately.
     210                equal( wp.hooks.didAction( 'newtest_action' ), 2, 'The newtest_action has run twice.' );
     211                ok( ! wp.hooks.hasAction( 'newtest_action' ), 'The newtest_action is not registered.' );
     212
     213                wp.hooks.doAction( 'another_action' );
     214                ok( ! wp.hooks.doingAction( 'newtest_action' ), 'The newtest_action is running.' );
     215
     216                // Verify hasAction returns false when no matching action.
     217                ok( ! wp.hooks.hasAction( 'notanewtest_action' ), 'The notanewtest_action is registered.' );
     218
     219        } );
     220
     221        QUnit.test( 'Verify doingFilter, didFilter and hasFilter.', function() {
     222                expect( 5 );
     223                wp.hooks.addFilter( 'runtest_filter', 'my_plugin/my_callback', filter_check );
     224                equal( wp.hooks.applyFilters( 'runtest_filter', 'test' ), 'test' );
     225
     226                // Verify filter added and running.
     227                equal( wp.hooks.didFilter( 'runtest_filter' ), 1, 'The runtest_filter has run once.' );
     228                ok( wp.hooks.hasFilter( 'runtest_filter' ), 'The runtest_filter is registered.' );
     229                ok( ! wp.hooks.hasFilter( 'notatest_filter' ), 'The notatest_filter is not registered.' );
     230
     231                wp.hooks.removeAllFilters( 'runtest_filter' );
     232        } );
     233/*
     234*/
     235} )( window.QUnit );