summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/install-testing.yml6
-rw-r--r--.github/workflows/local-docker-environment.yml6
-rw-r--r--.github/workflows/phpunit-tests.yml10
-rw-r--r--.github/workflows/reusable-test-local-docker-environment-v1.yml2
-rw-r--r--.github/workflows/upgrade-testing.yml12
-rw-r--r--.version-support-mysql.json2
-rw-r--r--Gruntfile.js1
-rw-r--r--docker-compose.yml4
-rw-r--r--package.json2
-rw-r--r--src/js/_enqueues/admin/user-profile.js14
-rw-r--r--src/js/_enqueues/vendor/README.md2
-rw-r--r--src/js/_enqueues/vendor/swfobject.js4
-rw-r--r--src/js/_enqueues/vendor/swfupload/handlers.js54
-rw-r--r--src/js/_enqueues/vendor/swfupload/handlers.min.js1
-rw-r--r--src/js/_enqueues/vendor/swfupload/license.txt32
-rw-r--r--src/js/_enqueues/vendor/swfupload/swfupload.js140
-rw-r--r--src/js/media/views/uploader/status.js6
-rw-r--r--src/wp-admin/async-upload.php19
-rw-r--r--src/wp-admin/css/common.css4
-rw-r--r--src/wp-admin/css/list-tables.css8
-rw-r--r--src/wp-admin/includes/ajax-actions.php8
-rw-r--r--src/wp-admin/includes/class-language-pack-upgrader.php2
-rw-r--r--src/wp-admin/includes/class-wp-automatic-updater.php2
-rw-r--r--src/wp-admin/includes/class-wp-community-events.php8
-rw-r--r--src/wp-admin/includes/class-wp-debug-data.php23
-rw-r--r--src/wp-admin/includes/class-wp-filesystem-ftpext.php8
-rw-r--r--src/wp-admin/includes/class-wp-filesystem-ftpsockets.php4
-rw-r--r--src/wp-admin/includes/class-wp-list-table.php4
-rw-r--r--src/wp-admin/includes/file.php2
-rw-r--r--src/wp-admin/includes/media.php2
-rw-r--r--src/wp-admin/includes/misc.php4
-rw-r--r--src/wp-admin/includes/post.php2
-rw-r--r--src/wp-admin/includes/taxonomy.php2
-rw-r--r--src/wp-admin/includes/update-core.php1
-rw-r--r--src/wp-admin/options-discussion.php2
-rw-r--r--src/wp-admin/user-edit.php30
-rw-r--r--src/wp-content/themes/twentynineteen/sass/navigation/_menu-main-navigation.scss6
-rw-r--r--src/wp-content/themes/twentynineteen/style-rtl.css6
-rw-r--r--src/wp-content/themes/twentynineteen/style.css6
-rw-r--r--src/wp-content/themes/twentytwenty/assets/js/index.js5
-rw-r--r--src/wp-includes/author-template.php2
-rw-r--r--src/wp-includes/block-template.php2
-rw-r--r--src/wp-includes/capabilities.php59
-rw-r--r--src/wp-includes/category-template.php26
-rw-r--r--src/wp-includes/class-wp-block-pattern-categories-registry.php2
-rw-r--r--src/wp-includes/class-wp-block-patterns-registry.php2
-rw-r--r--src/wp-includes/class-wp-block-styles-registry.php2
-rw-r--r--src/wp-includes/class-wp-comment-query.php4
-rw-r--r--src/wp-includes/class-wp-customize-widgets.php8
-rw-r--r--src/wp-includes/class-wp-image-editor-imagick.php2
-rw-r--r--src/wp-includes/class-wp-oembed.php14
-rw-r--r--src/wp-includes/comment-template.php5
-rw-r--r--src/wp-includes/comment.php6
-rw-r--r--src/wp-includes/embed.php16
-rw-r--r--src/wp-includes/link-template.php31
-rw-r--r--src/wp-includes/media-template.php4
-rw-r--r--src/wp-includes/media.php21
-rw-r--r--src/wp-includes/meta.php188
-rw-r--r--src/wp-includes/ms-site.php8
-rw-r--r--src/wp-includes/pluggable.php20
-rw-r--r--src/wp-includes/post.php19
-rw-r--r--src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php12
-rw-r--r--src/wp-includes/script-loader.php10
-rw-r--r--src/wp-includes/taxonomy.php10
-rw-r--r--src/wp-includes/theme.php2
-rw-r--r--src/wp-includes/user.php13
-rw-r--r--tests/phpunit/includes/abstract-testcase.php55
-rw-r--r--tests/phpunit/includes/build-visual-html-tree.php304
-rw-r--r--tests/phpunit/includes/factory/class-wp-unittest-factory-for-attachment.php5
-rw-r--r--tests/phpunit/includes/object-cache.php8
-rw-r--r--tests/phpunit/tests/auth.php5
-rw-r--r--tests/phpunit/tests/build-visual-html-tree.php144
-rw-r--r--tests/phpunit/tests/comment/commentForm.php34
-rw-r--r--tests/phpunit/tests/customize/widgets.php38
-rw-r--r--tests/phpunit/tests/dependencies/scripts.php435
-rw-r--r--tests/phpunit/tests/media.php1
-rw-r--r--tests/phpunit/tests/rest-api/rest-settings-controller.php32
-rw-r--r--tests/phpunit/tests/user/getTheAuthorPosts.php4
-rw-r--r--tools/local-env/scripts/docker.js33
-rw-r--r--tools/local-env/scripts/install.js35
-rw-r--r--tools/local-env/scripts/start.js61
-rw-r--r--tools/local-env/scripts/utils.js10
82 files changed, 1408 insertions, 740 deletions
diff --git a/.github/workflows/install-testing.yml b/.github/workflows/install-testing.yml
index 775ea83c75..6d6caf246a 100644
--- a/.github/workflows/install-testing.yml
+++ b/.github/workflows/install-testing.yml
@@ -92,11 +92,13 @@ jobs:
db-version: '8.4'
# Only test the latest innovation release.
- db-version: '9.0'
+ - db-version: '9.1'
+ - db-version: '9.2'
# MySQL 9.0+ will not work on PHP 7.2 & 7.3. See https://core.trac.wordpress.org/ticket/61218.
- php: '7.2'
- db-version: '9.1'
+ db-version: '9.3'
- php: '7.3'
- db-version: '9.1'
+ db-version: '9.3'
services:
database:
diff --git a/.github/workflows/local-docker-environment.yml b/.github/workflows/local-docker-environment.yml
index 7e4be73c33..d8312015f6 100644
--- a/.github/workflows/local-docker-environment.yml
+++ b/.github/workflows/local-docker-environment.yml
@@ -97,11 +97,13 @@ jobs:
- db-version: '5.5'
# Only test the latest innovation release.
- db-version: '9.0'
+ - db-version: '9.1'
+ - db-version: '9.2'
# MySQL 9.0+ will not work on PHP 7.2 & 7.3. See https://core.trac.wordpress.org/ticket/61218.
- php: '7.2'
- db-version: '9.1'
+ db-version: '9.3'
- php: '7.3'
- db-version: '9.1'
+ db-version: '9.3'
with:
os: ${{ matrix.os }}
diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml
index 2feb89a063..83054d8b86 100644
--- a/.github/workflows/phpunit-tests.yml
+++ b/.github/workflows/phpunit-tests.yml
@@ -187,7 +187,7 @@ jobs:
os: [ ubuntu-24.04 ]
php: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ]
db-type: [ 'mysql', 'mariadb' ]
- db-version: [ '9.1', '11.6' ]
+ db-version: [ '9.3', '11.7' ]
multisite: [ false, true ]
memcached: [ false ]
db-innovation: [ true ]
@@ -195,14 +195,14 @@ jobs:
exclude:
# MySQL 9.0+ will not work on PHP <= 7.3 because mysql_native_password was removed. See https://core.trac.wordpress.org/ticket/61218.
- php: '7.2'
- db-version: '9.1'
+ db-version: '9.3'
- php: '7.3'
- db-version: '9.1'
+ db-version: '9.3'
# Exclude version combinations that don't exist.
- db-type: 'mariadb'
- db-version: '9.1'
+ db-version: '9.3'
- db-type: 'mysql'
- db-version: '11.6'
+ db-version: '11.7'
with:
os: ${{ matrix.os }}
php: ${{ matrix.php }}
diff --git a/.github/workflows/reusable-test-local-docker-environment-v1.yml b/.github/workflows/reusable-test-local-docker-environment-v1.yml
index 83ed4d1ac7..c4bbfae729 100644
--- a/.github/workflows/reusable-test-local-docker-environment-v1.yml
+++ b/.github/workflows/reusable-test-local-docker-environment-v1.yml
@@ -155,7 +155,7 @@ jobs:
run: npm run env:restart
- name: Test a CLI command
- run: npm run env:cli wp option get siteurl
+ run: npm run env:cli option get siteurl
- name: Test logs command
run: npm run env:logs
diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml
index 8f3320f216..39846ce6b0 100644
--- a/.github/workflows/upgrade-testing.yml
+++ b/.github/workflows/upgrade-testing.yml
@@ -65,7 +65,7 @@ jobs:
os: [ 'ubuntu-24.04' ]
php: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ]
db-type: [ 'mysql' ]
- db-version: [ '5.7', '8.0', '8.4', '9.1' ]
+ db-version: [ '5.7', '8.0', '8.4', '9.3' ]
wp: [ '6.6', '6.7' ]
multisite: [ false, true ]
@@ -77,9 +77,9 @@ jobs:
db-version: '8.4'
# MySQL 9.0+ will not work on PHP 7.2 & 7.3. See https://core.trac.wordpress.org/ticket/61218.
- php: '7.2'
- db-version: '9.1'
+ db-version: '9.3'
- php: '7.3'
- db-version: '9.1'
+ db-version: '9.3'
with:
os: ${{ matrix.os }}
php: ${{ matrix.php }}
@@ -243,7 +243,7 @@ jobs:
os: [ 'ubuntu-24.04' ]
php: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ]
db-type: [ 'mysql' ]
- db-version: [ '5.7', '8.0', '8.4', '9.1' ]
+ db-version: [ '5.7', '8.0', '8.4', '9.3' ]
wp: [ '4.1' ]
multisite: [ false, true ]
@@ -255,9 +255,9 @@ jobs:
db-version: '8.4'
# MySQL 9.0+ will not work on PHP 7.2 & 7.3. See https://core.trac.wordpress.org/ticket/61218.
- php: '7.2'
- db-version: '9.1'
+ db-version: '9.3'
- php: '7.3'
- db-version: '9.1'
+ db-version: '9.3'
with:
os: ${{ matrix.os }}
php: ${{ matrix.php }}
diff --git a/.version-support-mysql.json b/.version-support-mysql.json
index bc3d17dce6..e92216e416 100644
--- a/.version-support-mysql.json
+++ b/.version-support-mysql.json
@@ -1,5 +1,7 @@
{
"6-9": [
+ "9.3",
+ "9.2",
"9.1",
"9.0",
"8.4",
diff --git a/Gruntfile.js b/Gruntfile.js
index 83a31a9cd3..a577b0711d 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -838,7 +838,6 @@ module.exports = function(grunt) {
'!**/*.min.js',
'!wp-admin/js/custom-header.js', // Why? We should minify this.
'!wp-admin/js/farbtastic.js',
- '!wp-includes/js/swfobject.js',
]
},
'jquery-ui': {
diff --git a/docker-compose.yml b/docker-compose.yml
index 48f3abc607..863cbd2ea9 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -106,10 +106,14 @@ services:
PHP_FPM_UID: ${PHP_FPM_UID-1000}
PHP_FPM_GID: ${PHP_FPM_GID-1000}
HOST_PATH: ${PWD-}/${LOCAL_DIR-src}
+ WP_CONFIG_PATH: /var/www/wp-config.php
volumes:
- ./:/var/www
+ # Keeps the service alive.
+ command: 'sleep infinity'
+
# The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly.
init: true
diff --git a/package.json b/package.json
index aeef7640f4..77c2b2d68c 100644
--- a/package.json
+++ b/package.json
@@ -184,7 +184,7 @@
"env:clean": "node ./tools/local-env/scripts/docker.js down -v --remove-orphans",
"env:reset": "node ./tools/local-env/scripts/docker.js down --rmi all -v --remove-orphans",
"env:install": "node ./tools/local-env/scripts/install.js",
- "env:cli": "node ./tools/local-env/scripts/docker.js run --rm cli",
+ "env:cli": "node ./tools/local-env/scripts/docker.js exec cli wp --allow-root",
"env:logs": "node ./tools/local-env/scripts/docker.js logs",
"env:pull": "node ./tools/local-env/scripts/docker.js pull",
"test:performance": "wp-scripts test-playwright --config tests/performance/playwright.config.js",
diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js
index 2aebe62a91..ce680ef4c4 100644
--- a/src/js/_enqueues/admin/user-profile.js
+++ b/src/js/_enqueues/admin/user-profile.js
@@ -56,8 +56,8 @@
// Once zxcvbn loads, passwords strength is known.
$( '#pw-weak-text-label' ).text( __( 'Confirm use of weak password' ) );
- // Focus the password field.
- if ( 'mailserver_pass' !== $pass1.prop('id' ) ) {
+ // Focus the password field if not the install screen.
+ if ( 'mailserver_pass' !== $pass1.prop('id' ) && ! $('#weblog_title').length ) {
$( $pass1 ).trigger( 'focus' );
}
}
@@ -101,6 +101,8 @@
return;
}
$toggleButton = $pass1Row.find('.wp-hide-pw');
+
+ // Toggle between showing and hiding the password.
$toggleButton.show().on( 'click', function () {
if ( 'password' === $pass1.attr( 'type' ) ) {
$pass1.attr( 'type', 'text' );
@@ -110,6 +112,14 @@
resetToggle( true );
}
});
+
+ // Ensure the password input type is set to password when the form is submitted.
+ $pass1Row.closest( 'form' ).on( 'submit', function() {
+ if ( $pass1.attr( 'type' ) === 'text' ) {
+ $pass1.attr( 'type', 'password' );
+ resetToggle( true );
+ }
+ } );
}
/**
diff --git a/src/js/_enqueues/vendor/README.md b/src/js/_enqueues/vendor/README.md
index 4764f0b808..fef43e3ec2 100644
--- a/src/js/_enqueues/vendor/README.md
+++ b/src/js/_enqueues/vendor/README.md
@@ -10,7 +10,6 @@ In this directory you'll find vendor JavaScript packages that cannot be installe
- jcrop: https://github.com/tapmodo/Jcrop
- mediaelement: https://github.com/mediaelement/mediaelement
- plupload: https://github.com/moxiecode/plupload
-- swfupload: https://github.com/WordPress/secure-swfupload
- thickbox: https://codylindley.com/thickbox/
- tinymce: https://www.tiny.cloud/get-tiny/self-hosted/
- Download "TinyMCE Dev Package". This package is needed because it includes
@@ -70,6 +69,5 @@ In this directory you'll find vendor JavaScript packages that cannot be installe
- jquery/jquery.serializeobject: https://github.com/cowboy/jquery-misc/blob/master/jquery.ba-serializeobject.js
- jquery/jquery.table-hotkeys: WP version can be downloaded at https://code.google.com/archive/p/js-hotkeys/downloads?page=2. A newer version is available at https://github.com/jeresig/jquery.hotkeys.
- jquery/jquery.ui.touch-punch.js https://github.com/furf/jquery-ui-touch-punch/blob/master/jquery.ui.touch-punch.js
-- swfobject: https://github.com/swfobject/swfobject
- tw-sack: https://github.com/abritinthebay/simpleajaxcodekit
- zxcvbn: https://github.com/dropbox/zxcvbn cannot automatically be installed as the frequency lists need to be manually ROT13 transformed.
diff --git a/src/js/_enqueues/vendor/swfobject.js b/src/js/_enqueues/vendor/swfobject.js
index 87e61553b3..e69de29bb2 100644
--- a/src/js/_enqueues/vendor/swfobject.js
+++ b/src/js/_enqueues/vendor/swfobject.js
@@ -1,4 +0,0 @@
-/* SWFObject v2.2 <http://code.google.com/p/swfobject/>
- is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
-*/
-var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+encodeURI(O.location).toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}(); \ No newline at end of file
diff --git a/src/js/_enqueues/vendor/swfupload/handlers.js b/src/js/_enqueues/vendor/swfupload/handlers.js
index 2de11ab6d9..e69de29bb2 100644
--- a/src/js/_enqueues/vendor/swfupload/handlers.js
+++ b/src/js/_enqueues/vendor/swfupload/handlers.js
@@ -1,54 +0,0 @@
-var topWin = window.dialogArguments || opener || parent || top;
-
-function fileDialogStart() {}
-function fileQueued() {}
-function uploadStart() {}
-function uploadProgress() {}
-function prepareMediaItem() {}
-function prepareMediaItemInit() {}
-function itemAjaxError() {}
-function deleteSuccess() {}
-function deleteError() {}
-function updateMediaForm() {}
-function uploadSuccess() {}
-function uploadComplete() {}
-function wpQueueError() {}
-function wpFileError() {}
-function fileQueueError() {}
-function fileDialogComplete() {}
-function uploadError() {}
-function cancelUpload() {}
-
-function switchUploader() {
- jQuery( '#' + swfu.customSettings.swfupload_element_id ).hide();
- jQuery( '#' + swfu.customSettings.degraded_element_id ).show();
- jQuery( '.upload-html-bypass' ).hide();
-}
-
-function swfuploadPreLoad() {
- switchUploader();
-}
-
-function swfuploadLoadFailed() {
- switchUploader();
-}
-
-jQuery(document).ready(function($){
- $( 'input[type="radio"]', '#media-items' ).on( 'click', function(){
- var tr = $(this).closest('tr');
-
- if ( $(tr).hasClass('align') )
- setUserSetting('align', $(this).val());
- else if ( $(tr).hasClass('image-size') )
- setUserSetting('imgsize', $(this).val());
- });
-
- $( 'button.button', '#media-items' ).on( 'click', function(){
- var c = this.className || '';
- c = c.match(/url([^ '"]+)/);
- if ( c && c[1] ) {
- setUserSetting('urlbutton', c[1]);
- $(this).siblings('.urlfield').val( $(this).attr('title') );
- }
- });
-});
diff --git a/src/js/_enqueues/vendor/swfupload/handlers.min.js b/src/js/_enqueues/vendor/swfupload/handlers.min.js
index 09bbaf9c3d..e69de29bb2 100644
--- a/src/js/_enqueues/vendor/swfupload/handlers.min.js
+++ b/src/js/_enqueues/vendor/swfupload/handlers.min.js
@@ -1 +0,0 @@
-function fileDialogStart(){}function fileQueued(){}function uploadStart(){}function uploadProgress(){}function prepareMediaItem(){}function prepareMediaItemInit(){}function itemAjaxError(){}function deleteSuccess(){}function deleteError(){}function updateMediaForm(){}function uploadSuccess(){}function uploadComplete(){}function wpQueueError(){}function wpFileError(){}function fileQueueError(){}function fileDialogComplete(){}function uploadError(){}function cancelUpload(){}function switchUploader(){jQuery("#"+swfu.customSettings.swfupload_element_id).hide(),jQuery("#"+swfu.customSettings.degraded_element_id).show(),jQuery(".upload-html-bypass").hide()}function swfuploadPreLoad(){switchUploader()}function swfuploadLoadFailed(){switchUploader()}var topWin=window.dialogArguments||opener||parent||top;jQuery(document).ready(function(a){a('input[type="radio"]',"#media-items").on("click",function(){var b=a(this).closest("tr");a(b).hasClass("align")?setUserSetting("align",a(this).val()):a(b).hasClass("image-size")&&setUserSetting("imgsize",a(this).val())}),a("button.button","#media-items").on("click",function(){var b=this.className||"";b=b.match(/url([^ '"]+)/),b&&b[1]&&(setUserSetting("urlbutton",b[1]),a(this).siblings(".urlfield").val(a(this).attr("title")))})}); \ No newline at end of file
diff --git a/src/js/_enqueues/vendor/swfupload/license.txt b/src/js/_enqueues/vendor/swfupload/license.txt
index 8252ca9e24..e69de29bb2 100644
--- a/src/js/_enqueues/vendor/swfupload/license.txt
+++ b/src/js/_enqueues/vendor/swfupload/license.txt
@@ -1,32 +0,0 @@
-/**
- * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
- *
- * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/
- *
- * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
- * http://www.opensource.org/licenses/mit-license.php
- *
- * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
- * http://www.opensource.org/licenses/mit-license.php
- *
- */
-
-The MIT License
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE. \ No newline at end of file
diff --git a/src/js/_enqueues/vendor/swfupload/swfupload.js b/src/js/_enqueues/vendor/swfupload/swfupload.js
index 14d58dcaf5..e69de29bb2 100644
--- a/src/js/_enqueues/vendor/swfupload/swfupload.js
+++ b/src/js/_enqueues/vendor/swfupload/swfupload.js
@@ -1,140 +0,0 @@
-/**
- * SWFUpload fallback
- *
- * @since 4.9.0
- */
-
-var SWFUpload;
-
-( function () {
- function noop() {}
-
- if (SWFUpload == undefined) {
- SWFUpload = function (settings) {
- this.initSWFUpload(settings);
- };
- }
-
- SWFUpload.prototype.initSWFUpload = function ( settings ) {
- function fallback() {
- var $ = window.jQuery;
- var $placeholder = settings.button_placeholder_id ? $( '#' + settings.button_placeholder_id ) : $( settings.button_placeholder );
-
- if ( ! $placeholder.length ) {
- return;
- }
-
- var $form = $placeholder.closest( 'form' );
-
- if ( ! $form.length ) {
- $form = $( '<form enctype="multipart/form-data" method="post">' );
- $form.attr( 'action', settings.upload_url );
- $form.insertAfter( $placeholder ).append( $placeholder );
- }
-
- $placeholder.replaceWith(
- $( '<div>' )
- .append(
- $( '<input type="file" multiple />' ).attr({
- name: settings.file_post_name || 'async-upload',
- accepts: settings.file_types || '*.*'
- })
- ).append(
- $( '<input type="submit" name="html-upload" class="button" value="Upload" />' )
- )
- );
- }
-
- try {
- // Try the built-in fallback.
- if ( typeof settings.swfupload_load_failed_handler === 'function' && settings.custom_settings ) {
-
- window.swfu = {
- customSettings: settings.custom_settings
- };
-
- settings.swfupload_load_failed_handler();
- } else {
- fallback();
- }
- } catch ( ex ) {
- fallback();
- }
- };
-
- SWFUpload.instances = {};
- SWFUpload.movieCount = 0;
- SWFUpload.version = "0";
- SWFUpload.QUEUE_ERROR = {};
- SWFUpload.UPLOAD_ERROR = {};
- SWFUpload.FILE_STATUS = {};
- SWFUpload.BUTTON_ACTION = {};
- SWFUpload.CURSOR = {};
- SWFUpload.WINDOW_MODE = {};
-
- SWFUpload.completeURL = noop;
- SWFUpload.prototype.initSettings = noop;
- SWFUpload.prototype.loadFlash = noop;
- SWFUpload.prototype.getFlashHTML = noop;
- SWFUpload.prototype.getFlashVars = noop;
- SWFUpload.prototype.getMovieElement = noop;
- SWFUpload.prototype.buildParamString = noop;
- SWFUpload.prototype.destroy = noop;
- SWFUpload.prototype.displayDebugInfo = noop;
- SWFUpload.prototype.addSetting = noop;
- SWFUpload.prototype.getSetting = noop;
- SWFUpload.prototype.callFlash = noop;
- SWFUpload.prototype.selectFile = noop;
- SWFUpload.prototype.selectFiles = noop;
- SWFUpload.prototype.startUpload = noop;
- SWFUpload.prototype.cancelUpload = noop;
- SWFUpload.prototype.stopUpload = noop;
- SWFUpload.prototype.getStats = noop;
- SWFUpload.prototype.setStats = noop;
- SWFUpload.prototype.getFile = noop;
- SWFUpload.prototype.addFileParam = noop;
- SWFUpload.prototype.removeFileParam = noop;
- SWFUpload.prototype.setUploadURL = noop;
- SWFUpload.prototype.setPostParams = noop;
- SWFUpload.prototype.addPostParam = noop;
- SWFUpload.prototype.removePostParam = noop;
- SWFUpload.prototype.setFileTypes = noop;
- SWFUpload.prototype.setFileSizeLimit = noop;
- SWFUpload.prototype.setFileUploadLimit = noop;
- SWFUpload.prototype.setFileQueueLimit = noop;
- SWFUpload.prototype.setFilePostName = noop;
- SWFUpload.prototype.setUseQueryString = noop;
- SWFUpload.prototype.setRequeueOnError = noop;
- SWFUpload.prototype.setHTTPSuccess = noop;
- SWFUpload.prototype.setAssumeSuccessTimeout = noop;
- SWFUpload.prototype.setDebugEnabled = noop;
- SWFUpload.prototype.setButtonImageURL = noop;
- SWFUpload.prototype.setButtonDimensions = noop;
- SWFUpload.prototype.setButtonText = noop;
- SWFUpload.prototype.setButtonTextPadding = noop;
- SWFUpload.prototype.setButtonTextStyle = noop;
- SWFUpload.prototype.setButtonDisabled = noop;
- SWFUpload.prototype.setButtonAction = noop;
- SWFUpload.prototype.setButtonCursor = noop;
- SWFUpload.prototype.queueEvent = noop;
- SWFUpload.prototype.executeNextEvent = noop;
- SWFUpload.prototype.unescapeFilePostParams = noop;
- SWFUpload.prototype.testExternalInterface = noop;
- SWFUpload.prototype.flashReady = noop;
- SWFUpload.prototype.cleanUp = noop;
- SWFUpload.prototype.fileDialogStart = noop;
- SWFUpload.prototype.fileQueued = noop;
- SWFUpload.prototype.fileQueueError = noop;
- SWFUpload.prototype.fileDialogComplete = noop;
- SWFUpload.prototype.uploadStart = noop;
- SWFUpload.prototype.returnUploadStart = noop;
- SWFUpload.prototype.uploadProgress = noop;
- SWFUpload.prototype.uploadError = noop;
- SWFUpload.prototype.uploadSuccess = noop;
- SWFUpload.prototype.uploadComplete = noop;
- SWFUpload.prototype.debug = noop;
- SWFUpload.prototype.debugMessage = noop;
- SWFUpload.Console = {
- writeLine: noop
- };
-}() );
diff --git a/src/js/media/views/uploader/status.js b/src/js/media/views/uploader/status.js
index 86c538b833..f629e0a343 100644
--- a/src/js/media/views/uploader/status.js
+++ b/src/js/media/views/uploader/status.js
@@ -124,8 +124,11 @@ UploaderStatus = View.extend(/** @lends wp.media.view.UploaderStatus.prototype *
this.views.add( '.upload-errors', statusError, { at: 0 } );
_.delay( function() {
buttonClose.trigger( 'focus' );
- wp.a11y.speak( error.get( 'message' ), 'assertive' );
}, 1000 );
+
+ _.delay( function() {
+ wp.a11y.speak( error.get( 'message' ) );
+ }, 1500 );
},
dismiss: function() {
@@ -135,6 +138,7 @@ UploaderStatus = View.extend(/** @lends wp.media.view.UploaderStatus.prototype *
_.invoke( errors, 'remove' );
}
wp.Uploader.errors.reset();
+ wp.a11y.speak( wp.i18n.__( 'Error dismissed.' ) );
// Move focus to the modal after the dismiss button gets removed from the DOM.
if ( this.controller.modal ) {
this.controller.modal.focusManager.focus();
diff --git a/src/wp-admin/async-upload.php b/src/wp-admin/async-upload.php
index 2ac2f20e76..135568507c 100644
--- a/src/wp-admin/async-upload.php
+++ b/src/wp-admin/async-upload.php
@@ -112,12 +112,14 @@ if ( isset( $_REQUEST['post_id'] ) ) {
$id = media_handle_upload( 'async-upload', $post_id );
if ( is_wp_error( $id ) ) {
- $button_unique_id = uniqid( 'dismiss-' );
- $message = sprintf(
+ $button_unique_id = uniqid( 'dismiss-' );
+ $error_description_id = uniqid( 'error-description-' );
+ $message = sprintf(
'%s <strong>%s</strong><br />%s',
sprintf(
- '<button type="button" id="%s" class="dismiss button-link">%s</button>',
+ '<button type="button" id="%1$s" class="dismiss button-link" aria-describedby="%2$s">%3$s</button>',
esc_attr( $button_unique_id ),
+ esc_attr( $error_description_id ),
__( 'Dismiss' )
),
sprintf(
@@ -127,14 +129,23 @@ if ( is_wp_error( $id ) ) {
),
esc_html( $id->get_error_message() )
);
+
wp_admin_notice(
$message,
array(
+ 'id' => $error_description_id,
'additional_classes' => array( 'error-div', 'error' ),
'paragraph_wrap' => false,
)
);
- echo "<script>jQuery( 'button#{$button_unique_id}' ).on( 'click', function() {jQuery(this).parents('div.media-item').slideUp(200, function(){jQuery(this).remove();})});</script>\n";
+
+ $speak_message = sprintf(
+ /* translators: %s: Name of the file that failed to upload. */
+ __( '%s has failed to upload.' ),
+ esc_js( $_FILES['async-upload']['name'] )
+ );
+
+ echo "<script>_.delay(function() {wp.a11y.speak('" . esc_js( $speak_message ) . "');}, 1500);jQuery( 'button#{$button_unique_id}' ).on( 'click', function() {jQuery(this).parents('div.media-item').slideUp(200, function(){jQuery(this).remove();wp.a11y.speak( wp.i18n.__( 'Error dismissed.' ) );jQuery( '#plupload-browse-button' ).trigger( 'focus' );})});</script>\n";
exit;
}
diff --git a/src/wp-admin/css/common.css b/src/wp-admin/css/common.css
index c008d784ce..f8764e2b2d 100644
--- a/src/wp-admin/css/common.css
+++ b/src/wp-admin/css/common.css
@@ -3912,6 +3912,10 @@ img {
top: 7px;
}
+ .screen-reader-shortcut[href="#wp-toolbar"] {
+ display: none;
+ }
+
body {
min-width: 240px;
overflow-x: hidden;
diff --git a/src/wp-admin/css/list-tables.css b/src/wp-admin/css/list-tables.css
index da4bb599be..bc38d64b38 100644
--- a/src/wp-admin/css/list-tables.css
+++ b/src/wp-admin/css/list-tables.css
@@ -2064,7 +2064,6 @@ div.action-links,
}
.row-actions {
- margin-left: -8px;
margin-right: -8px;
padding-top: 4px;
}
@@ -2077,10 +2076,15 @@ div.action-links,
color: transparent;
}
+ .row-actions span {
+ font-size: 0;
+ }
+
.row-actions span a,
.row-actions span .button-link {
display: inline-block;
- padding: 4px 8px;
+ padding: 4px 16px 4px 0;
+ font-size: 13px;
line-height: 1.5;
}
diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php
index 83b682634b..53635479e0 100644
--- a/src/wp-admin/includes/ajax-actions.php
+++ b/src/wp-admin/includes/ajax-actions.php
@@ -5354,7 +5354,7 @@ function wp_ajax_health_check_dotorg_communication() {
_doing_it_wrong(
'wp_ajax_health_check_dotorg_communication',
sprintf(
- // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
+ /* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
'wp_ajax_health_check_dotorg_communication',
'WP_REST_Site_Health_Controller::test_dotorg_communication'
@@ -5387,7 +5387,7 @@ function wp_ajax_health_check_background_updates() {
_doing_it_wrong(
'wp_ajax_health_check_background_updates',
sprintf(
- // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
+ /* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
'wp_ajax_health_check_background_updates',
'WP_REST_Site_Health_Controller::test_background_updates'
@@ -5420,7 +5420,7 @@ function wp_ajax_health_check_loopback_requests() {
_doing_it_wrong(
'wp_ajax_health_check_loopback_requests',
sprintf(
- // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
+ /* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
'wp_ajax_health_check_loopback_requests',
'WP_REST_Site_Health_Controller::test_loopback_requests'
@@ -5470,7 +5470,7 @@ function wp_ajax_health_check_get_sizes() {
_doing_it_wrong(
'wp_ajax_health_check_get_sizes',
sprintf(
- // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
+ /* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
'wp_ajax_health_check_get_sizes',
'WP_REST_Site_Health_Controller::get_directory_sizes'
diff --git a/src/wp-admin/includes/class-language-pack-upgrader.php b/src/wp-admin/includes/class-language-pack-upgrader.php
index 6f7cf742bd..89b9f9ac87 100644
--- a/src/wp-admin/includes/class-language-pack-upgrader.php
+++ b/src/wp-admin/includes/class-language-pack-upgrader.php
@@ -383,7 +383,7 @@ class Language_Pack_Upgrader extends WP_Upgrader {
case 'theme':
$theme = wp_get_theme( $update->slug );
if ( $theme->exists() ) {
- return $theme->Get( 'Name' );
+ return $theme->get( 'Name' );
}
break;
case 'plugin':
diff --git a/src/wp-admin/includes/class-wp-automatic-updater.php b/src/wp-admin/includes/class-wp-automatic-updater.php
index 4dccd94ccd..2facbeb1d5 100644
--- a/src/wp-admin/includes/class-wp-automatic-updater.php
+++ b/src/wp-admin/includes/class-wp-automatic-updater.php
@@ -411,7 +411,7 @@ class WP_Automatic_Updater {
case 'theme':
$upgrader_item = $item->theme;
$theme = wp_get_theme( $upgrader_item );
- $item_name = $theme->Get( 'Name' );
+ $item_name = $theme->get( 'Name' );
// Add the current version so that it can be reported in the notification email.
$item->current_version = $theme->get( 'Version' );
if ( empty( $item->current_version ) ) {
diff --git a/src/wp-admin/includes/class-wp-community-events.php b/src/wp-admin/includes/class-wp-community-events.php
index 008611af21..b5a65e298d 100644
--- a/src/wp-admin/includes/class-wp-community-events.php
+++ b/src/wp-admin/includes/class-wp-community-events.php
@@ -375,17 +375,13 @@ class WP_Community_Events {
* of the user who triggered the cache refresh, rather than their own.
*
* @since 4.8.0
- * @deprecated 5.6.0 No longer used in core.
+ * @deprecated 5.5.2 No longer used in core.
*
* @param array $response_body The response which contains the events.
* @return array The response with dates and times formatted.
*/
protected function format_event_data_time( $response_body ) {
- _deprecated_function(
- __METHOD__,
- '5.5.2',
- 'This is no longer used by core, and only kept for backward compatibility.'
- );
+ _deprecated_function( __METHOD__, '5.5.2' );
if ( isset( $response_body['events'] ) ) {
foreach ( $response_body['events'] as $key => $event ) {
diff --git a/src/wp-admin/includes/class-wp-debug-data.php b/src/wp-admin/includes/class-wp-debug-data.php
index cbb57a4b8c..cd04297684 100644
--- a/src/wp-admin/includes/class-wp-debug-data.php
+++ b/src/wp-admin/includes/class-wp-debug-data.php
@@ -682,6 +682,25 @@ class WP_Debug_Data {
);
}
+ // Get the image format transforms.
+ $mappings = wp_get_image_editor_output_format( '', '' );
+ $formatted_mappings = array();
+
+ if ( ! empty( $mappings ) ) {
+ foreach ( $mappings as $format => $mime_type ) {
+ $formatted_mappings[] = sprintf( '%s &rarr; %s', $format, $mime_type );
+ }
+ $mappings_display = implode( ', ', $formatted_mappings );
+ } else {
+ $mappings_display = __( 'No format transforms defined' );
+ }
+
+ $fields['image_format_transforms'] = array(
+ 'label' => __( 'Image format transforms' ),
+ 'value' => $mappings_display,
+ 'debug' => ( empty( $mappings ) ) ? 'No format transforms defined' : $mappings_display,
+ );
+
// Get GD information, if available.
if ( function_exists( 'gd_info' ) ) {
$gd = gd_info();
@@ -1860,10 +1879,14 @@ class WP_Debug_Data {
* Intended to supplement the array returned by `WP_Debug_Data::debug_data()`.
*
* @since 5.2.0
+ * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::get_directory_sizes()
+ * @see WP_REST_Site_Health_Controller::get_directory_sizes()
*
* @return array The sizes of the directories, also the database size and total installation size.
*/
public static function get_sizes() {
+ _deprecated_function( __METHOD__, '5.6.0', 'WP_REST_Site_Health_Controller::get_directory_sizes()' );
+
$size_db = self::get_database_size();
$upload_dir = wp_get_upload_dir();
diff --git a/src/wp-admin/includes/class-wp-filesystem-ftpext.php b/src/wp-admin/includes/class-wp-filesystem-ftpext.php
index 454998822e..7c721734c3 100644
--- a/src/wp-admin/includes/class-wp-filesystem-ftpext.php
+++ b/src/wp-admin/includes/class-wp-filesystem-ftpext.php
@@ -601,9 +601,11 @@ class WP_Filesystem_FTPext extends WP_Filesystem_Base {
}
/**
- * @param string $line
- * @return array {
- * Array of file information.
+ * Parses an individual entry from the FTP LIST command output.
+ *
+ * @param string $line A line from the directory listing.
+ * @return array|string {
+ * Array of file information. Empty string if the line could not be parsed.
*
* @type string $name Name of the file or directory.
* @type string $perms *nix representation of permissions.
diff --git a/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php b/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php
index 9a37d88c11..986fccf2cf 100644
--- a/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php
+++ b/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php
@@ -77,7 +77,7 @@ class WP_Filesystem_ftpsockets extends WP_Filesystem_Base {
return false;
}
- $this->ftp->setTimeout( FS_CONNECT_TIMEOUT );
+ $this->ftp->SetTimeout( FS_CONNECT_TIMEOUT );
if ( ! $this->ftp->SetServer( $this->options['hostname'], $this->options['port'] ) ) {
$this->errors->add(
@@ -120,7 +120,7 @@ class WP_Filesystem_ftpsockets extends WP_Filesystem_Base {
$this->ftp->SetType( FTP_BINARY );
$this->ftp->Passive( true );
- $this->ftp->setTimeout( FS_TIMEOUT );
+ $this->ftp->SetTimeout( FS_TIMEOUT );
return true;
}
diff --git a/src/wp-admin/includes/class-wp-list-table.php b/src/wp-admin/includes/class-wp-list-table.php
index 5a7fa0db8e..cdf31db597 100644
--- a/src/wp-admin/includes/class-wp-list-table.php
+++ b/src/wp-admin/includes/class-wp-list-table.php
@@ -72,10 +72,10 @@ class WP_List_Table {
protected $modes = array();
/**
- * Stores the value returned by ->get_column_info().
+ * Stores the value returned by ::get_column_info().
*
* @since 4.1.0
- * @var array
+ * @var array|null
*/
protected $_column_headers;
diff --git a/src/wp-admin/includes/file.php b/src/wp-admin/includes/file.php
index 40059273ba..0658662126 100644
--- a/src/wp-admin/includes/file.php
+++ b/src/wp-admin/includes/file.php
@@ -2622,7 +2622,7 @@ function request_filesystem_credentials( $form_post, $type = '', $error = false,
<?php
if ( isset( $types['ssh'] ) ) {
$hidden_class = '';
- if ( 'ssh' !== $connection_type || empty( $connection_type ) ) {
+ if ( 'ssh' !== $connection_type ) {
$hidden_class = ' class="hidden"';
}
?>
diff --git a/src/wp-admin/includes/media.php b/src/wp-admin/includes/media.php
index 5c0b5d0b38..7d9fd638fb 100644
--- a/src/wp-admin/includes/media.php
+++ b/src/wp-admin/includes/media.php
@@ -3337,7 +3337,7 @@ function attachment_submitbox_metadata() {
$uploaded_by_link = get_edit_user_link( $author->ID );
}
?>
- <div class="misc-pub-section misc-pub-uploadedby">
+ <div class="misc-pub-section misc-pub-uploadedby word-wrap-break-word">
<?php if ( $uploaded_by_link ) { ?>
<?php _e( 'Uploaded by:' ); ?> <a href="<?php echo $uploaded_by_link; ?>"><strong><?php echo $uploaded_by_name; ?></strong></a>
<?php } else { ?>
diff --git a/src/wp-admin/includes/misc.php b/src/wp-admin/includes/misc.php
index 979d237448..ff073b0fd3 100644
--- a/src/wp-admin/includes/misc.php
+++ b/src/wp-admin/includes/misc.php
@@ -988,7 +988,7 @@ function saveDomDocument( $doc, $filename ) { // phpcs:ignore WordPress.NamingCo
}
/**
- * Displays the default admin color scheme picker (Used in user-edit.php).
+ * Displays the default administration color scheme picker (Used in user-edit.php).
*
* @since 3.0.0
*
@@ -1025,7 +1025,7 @@ function admin_color_scheme_picker( $user_id ) {
<legend class="screen-reader-text"><span>
<?php
/* translators: Hidden accessibility text. */
- _e( 'Admin Color Scheme' );
+ _e( 'Administration Color Scheme' );
?>
</span></legend>
<?php
diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php
index 40fac43d6e..ebdd61df34 100644
--- a/src/wp-admin/includes/post.php
+++ b/src/wp-admin/includes/post.php
@@ -2186,7 +2186,7 @@ function wp_autosave( $post_data ) {
*
* @param int $post_id Optional. Post ID.
*/
-function redirect_post( $post_id = '' ) {
+function redirect_post( $post_id = 0 ) {
if ( isset( $_POST['save'] ) || isset( $_POST['publish'] ) ) {
$status = get_post_status( $post_id );
diff --git a/src/wp-admin/includes/taxonomy.php b/src/wp-admin/includes/taxonomy.php
index 7765084fa7..359cfafe2f 100644
--- a/src/wp-admin/includes/taxonomy.php
+++ b/src/wp-admin/includes/taxonomy.php
@@ -75,7 +75,7 @@ function wp_create_category( $cat_name, $category_parent = 0 ) {
* @param int $post_id Optional. The post ID. Default empty.
* @return int[] Array of IDs of categories assigned to the given post.
*/
-function wp_create_categories( $categories, $post_id = '' ) {
+function wp_create_categories( $categories, $post_id = 0 ) {
$cat_ids = array();
foreach ( $categories as $category ) {
$id = category_exists( $category );
diff --git a/src/wp-admin/includes/update-core.php b/src/wp-admin/includes/update-core.php
index f1731f9c8f..2d925afa63 100644
--- a/src/wp-admin/includes/update-core.php
+++ b/src/wp-admin/includes/update-core.php
@@ -1023,6 +1023,7 @@ $_new_bundled_files = array(
* @global string[] $_old_requests_files
* @global string[] $_new_bundled_files
* @global wpdb $wpdb WordPress database abstraction object.
+ * @global string $wp_version The WordPress version string.
*
* @param string $from New release unzipped path.
* @param string $to Path to old WordPress installation.
diff --git a/src/wp-admin/options-discussion.php b/src/wp-admin/options-discussion.php
index 6bb8ce2f54..e0e12dc21f 100644
--- a/src/wp-admin/options-discussion.php
+++ b/src/wp-admin/options-discussion.php
@@ -309,6 +309,8 @@ $avatar_defaults = array(
'monsterid' => __( 'MonsterID (Generated)' ),
'retro' => __( 'Retro (Generated)' ),
'robohash' => __( 'RoboHash (Generated)' ),
+ 'initials' => __( 'Initials (Generated)' ),
+ 'color' => __( 'Color (Generated)' ),
);
/**
* Filters the default avatars.
diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php
index c476a294ad..6810425c77 100644
--- a/src/wp-admin/user-edit.php
+++ b/src/wp-admin/user-edit.php
@@ -333,11 +333,11 @@ switch ( $action ) {
<?php if ( count( $_wp_admin_css_colors ) > 1 && has_action( 'admin_color_scheme_picker' ) ) : ?>
<tr class="user-admin-color-wrap">
- <th scope="row"><?php _e( 'Admin Color Scheme' ); ?></th>
+ <th scope="row"><?php _e( 'Administration Color Scheme' ); ?></th>
<td>
<?php
/**
- * Fires in the 'Admin Color Scheme' section of the user editing screen.
+ * Fires in the 'Administration Color Scheme' section of the user editing screen.
*
* The section is only enabled if a callback is hooked to the action,
* and if there is more than one defined color scheme for the admin.
@@ -486,17 +486,35 @@ switch ( $action ) {
<tr class="user-first-name-wrap">
<th><label for="first_name"><?php _e( 'First Name' ); ?></label></th>
- <td><input type="text" name="first_name" id="first_name" value="<?php echo esc_attr( $profile_user->first_name ); ?>" class="regular-text" /></td>
+ <td>
+ <?php if ( IS_PROFILE_PAGE ) : ?>
+ <input type="text" name="first_name" id="first_name" value="<?php echo esc_attr( $profile_user->first_name ); ?>" autocomplete="given-name" class="regular-text" />
+ <?php else : ?>
+ <input type="text" name="first_name" id="first_name" value="<?php echo esc_attr( $profile_user->first_name ); ?>" class="regular-text" />
+ <?php endif; ?>
+ </td>
</tr>
<tr class="user-last-name-wrap">
<th><label for="last_name"><?php _e( 'Last Name' ); ?></label></th>
- <td><input type="text" name="last_name" id="last_name" value="<?php echo esc_attr( $profile_user->last_name ); ?>" class="regular-text" /></td>
+ <td>
+ <?php if ( IS_PROFILE_PAGE ) : ?>
+ <input type="text" name="last_name" id="last_name" value="<?php echo esc_attr( $profile_user->last_name ); ?>" autocomplete="family-name" class="regular-text" />
+ <?php else : ?>
+ <input type="text" name="last_name" id="last_name" value="<?php echo esc_attr( $profile_user->last_name ); ?>" class="regular-text" />
+ <?php endif; ?>
+ </td>
</tr>
<tr class="user-nickname-wrap">
<th><label for="nickname"><?php _e( 'Nickname' ); ?> <span class="description"><?php _e( '(required)' ); ?></span></label></th>
- <td><input type="text" name="nickname" id="nickname" value="<?php echo esc_attr( $profile_user->nickname ); ?>" class="regular-text" /></td>
+ <td>
+ <?php if ( IS_PROFILE_PAGE ) : ?>
+ <input type="text" name="nickname" id="nickname" value="<?php echo esc_attr( $profile_user->nickname ); ?>" autocomplete="nickname" class="regular-text" />
+ <?php else : ?>
+ <input type="text" name="nickname" id="nickname" value="<?php echo esc_attr( $profile_user->nickname ); ?>" class="regular-text" />
+ <?php endif; ?>
+ </td>
</tr>
<tr class="user-display-name-wrap">
@@ -546,7 +564,7 @@ switch ( $action ) {
<th><label for="email"><?php _e( 'Email' ); ?> <span class="description"><?php _e( '(required)' ); ?></span></label></th>
<td>
<?php if ( $profile_user->ID === $current_user->ID ) : ?>
- <input type="email" name="email" id="email" aria-describedby="email-description" value="<?php echo esc_attr( $profile_user->user_email ); ?>" class="regular-text ltr" />
+ <input type="email" name="email" id="email" aria-describedby="email-description" value="<?php echo esc_attr( $profile_user->user_email ); ?>" autocomplete="email" class="regular-text ltr" />
<p class="description" id="email-description">
<?php _e( 'If you change this, an email will be sent at your new address to confirm it. <strong>The new address will not become active until confirmed.</strong>' ); ?>
</p>
diff --git a/src/wp-content/themes/twentynineteen/sass/navigation/_menu-main-navigation.scss b/src/wp-content/themes/twentynineteen/sass/navigation/_menu-main-navigation.scss
index d1e30256f3..6d6d744ed8 100644
--- a/src/wp-content/themes/twentynineteen/sass/navigation/_menu-main-navigation.scss
+++ b/src/wp-content/themes/twentynineteen/sass/navigation/_menu-main-navigation.scss
@@ -433,9 +433,13 @@
white-space: inherit;
}
+ &:not(:has(.sub-menu.expanded-true)) {
+ overflow-y: scroll;
+ }
+
&.expanded-true {
- display: table;
+ display: block;
margin-top: 0;
opacity: 1;
padding-left: 0;
diff --git a/src/wp-content/themes/twentynineteen/style-rtl.css b/src/wp-content/themes/twentynineteen/style-rtl.css
index da1b3636c0..9f1700c012 100644
--- a/src/wp-content/themes/twentynineteen/style-rtl.css
+++ b/src/wp-content/themes/twentynineteen/style-rtl.css
@@ -3271,8 +3271,12 @@ body.page .main-navigation {
white-space: inherit;
}
+.main-navigation .main-menu .menu-item-has-children.off-canvas .sub-menu:not(:has(.sub-menu.expanded-true)) {
+ overflow-y: scroll;
+}
+
.main-navigation .main-menu .menu-item-has-children.off-canvas .sub-menu.expanded-true {
- display: table;
+ display: block;
margin-top: 0;
opacity: 1;
padding-right: 0;
diff --git a/src/wp-content/themes/twentynineteen/style.css b/src/wp-content/themes/twentynineteen/style.css
index 2124cf584f..634a947b3a 100644
--- a/src/wp-content/themes/twentynineteen/style.css
+++ b/src/wp-content/themes/twentynineteen/style.css
@@ -3271,8 +3271,12 @@ body.page .main-navigation {
white-space: inherit;
}
+.main-navigation .main-menu .menu-item-has-children.off-canvas .sub-menu:not(:has(.sub-menu.expanded-true)) {
+ overflow-y: scroll;
+}
+
.main-navigation .main-menu .menu-item-has-children.off-canvas .sub-menu.expanded-true {
- display: table;
+ display: block;
margin-top: 0;
opacity: 1;
padding-left: 0;
diff --git a/src/wp-content/themes/twentytwenty/assets/js/index.js b/src/wp-content/themes/twentytwenty/assets/js/index.js
index 258658a97e..35efcd6b60 100644
--- a/src/wp-content/themes/twentytwenty/assets/js/index.js
+++ b/src/wp-content/themes/twentytwenty/assets/js/index.js
@@ -257,7 +257,10 @@ twentytwenty.coverModals = {
clickedEl = false;
}
- _win.scrollTo( 0, Math.abs( _win.twentytwenty.scrolled + getAdminBarHeight() ) );
+ _win.scrollTo({
+ top: Math.abs( _win.twentytwenty.scrolled + getAdminBarHeight() ),
+ behavior: 'instant'
+ });
_win.twentytwenty.scrolled = 0;
}, 500 );
diff --git a/src/wp-includes/author-template.php b/src/wp-includes/author-template.php
index 184d7d0f38..a48a6d3e6e 100644
--- a/src/wp-includes/author-template.php
+++ b/src/wp-includes/author-template.php
@@ -286,7 +286,7 @@ function get_the_author_posts() {
if ( ! $post ) {
return 0;
}
- return count_user_posts( $post->post_author, $post->post_type );
+ return (int) count_user_posts( $post->post_author, $post->post_type );
}
/**
diff --git a/src/wp-includes/block-template.php b/src/wp-includes/block-template.php
index affae1c09a..eecbe2d61d 100644
--- a/src/wp-includes/block-template.php
+++ b/src/wp-includes/block-template.php
@@ -253,7 +253,7 @@ function get_the_block_template_html() {
if ( is_user_logged_in() ) {
return '<h1>' . esc_html__( 'No matching template found' ) . '</h1>';
}
- return;
+ return '';
}
$content = $wp_embed->run_shortcode( $_wp_current_template_content );
diff --git a/src/wp-includes/capabilities.php b/src/wp-includes/capabilities.php
index d6c340c95e..48586e093c 100644
--- a/src/wp-includes/capabilities.php
+++ b/src/wp-includes/capabilities.php
@@ -470,7 +470,7 @@ function map_meta_cap( $cap, $user_id, ...$args ) {
if ( $meta_key ) {
$allowed = ! is_protected_meta( $meta_key, $object_type );
- if ( ! empty( $object_subtype ) && has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
+ if ( has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
/**
* Filters whether the user is allowed to edit a specific meta key of a specific object type and subtype.
@@ -512,36 +512,33 @@ function map_meta_cap( $cap, $user_id, ...$args ) {
$allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
}
- if ( ! empty( $object_subtype ) ) {
-
- /**
- * Filters whether the user is allowed to edit meta for specific object types/subtypes.
- *
- * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
- *
- * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
- * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered.
- * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
- *
- * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
- * @since 4.7.0 Renamed from `auth_post_{$post_type}_meta_{$meta_key}` to
- * `auth_{$object_type}_{$object_subtype}_meta_{$meta_key}`.
- * @deprecated 4.9.8 Use {@see 'auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}'} instead.
- *
- * @param bool $allowed Whether the user can add the object meta. Default false.
- * @param string $meta_key The meta key.
- * @param int $object_id Object ID.
- * @param int $user_id User ID.
- * @param string $cap Capability name.
- * @param string[] $caps Array of the user's capabilities.
- */
- $allowed = apply_filters_deprecated(
- "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}",
- array( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ),
- '4.9.8',
- "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}"
- );
- }
+ /**
+ * Filters whether the user is allowed to edit meta for specific object types/subtypes.
+ *
+ * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
+ *
+ * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
+ * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered.
+ * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
+ *
+ * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
+ * @since 4.7.0 Renamed from `auth_post_{$post_type}_meta_{$meta_key}` to
+ * `auth_{$object_type}_{$object_subtype}_meta_{$meta_key}`.
+ * @deprecated 4.9.8 Use {@see 'auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}'} instead.
+ *
+ * @param bool $allowed Whether the user can add the object meta. Default false.
+ * @param string $meta_key The meta key.
+ * @param int $object_id Object ID.
+ * @param int $user_id User ID.
+ * @param string $cap Capability name.
+ * @param string[] $caps Array of the user's capabilities.
+ */
+ $allowed = apply_filters_deprecated(
+ "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}",
+ array( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ),
+ '4.9.8',
+ "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}"
+ );
if ( ! $allowed ) {
$caps[] = $cap;
diff --git a/src/wp-includes/category-template.php b/src/wp-includes/category-template.php
index 0525ae792a..b2c88c9c25 100644
--- a/src/wp-includes/category-template.php
+++ b/src/wp-includes/category-template.php
@@ -71,7 +71,7 @@ function get_category_parents( $category_id, $link = false, $separator = '/', $n
*
* @since 0.71
*
- * @param int $post_id Optional. The post ID. Defaults to current post ID.
+ * @param int|false $post_id Optional. The post ID. Defaults to current post ID.
* @return WP_Term[] Array of WP_Term objects, one for each category assigned to the post.
*/
function get_the_category( $post_id = false ) {
@@ -131,11 +131,11 @@ function get_the_category_by_ID( $cat_id ) { // phpcs:ignore WordPress.NamingCon
*
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
*
- * @param string $separator Optional. Separator between the categories. By default, the links are placed
- * in an unordered list. An empty string will result in the default behavior.
- * @param string $parents Optional. How to display the parents. Accepts 'multiple', 'single', or empty.
- * Default empty string.
- * @param int $post_id Optional. ID of the post to retrieve categories for. Defaults to the current post.
+ * @param string $separator Optional. Separator between the categories. By default, the links are placed
+ * in an unordered list. An empty string will result in the default behavior.
+ * @param string $parents Optional. How to display the parents. Accepts 'multiple', 'single', or empty.
+ * Default empty string.
+ * @param int|false $post_id Optional. ID of the post to retrieve categories for. Defaults to the current post.
* @return string Category list for a post.
*/
function get_the_category_list( $separator = '', $parents = '', $post_id = false ) {
@@ -251,7 +251,7 @@ function get_the_category_list( $separator = '', $parents = '', $post_id = false
*
* @param int|string|int[]|string[] $category Category ID, name, slug, or array of such
* to check against.
- * @param int|WP_Post $post Optional. Post to check. Defaults to the current post.
+ * @param int|null|WP_Post $post Optional. Post to check. Defaults to the current post.
* @return bool True if the current post is in any of the given categories.
*/
function in_category( $category, $post = null ) {
@@ -267,11 +267,11 @@ function in_category( $category, $post = null ) {
*
* @since 0.71
*
- * @param string $separator Optional. Separator between the categories. By default, the links are placed
- * in an unordered list. An empty string will result in the default behavior.
- * @param string $parents Optional. How to display the parents. Accepts 'multiple', 'single', or empty.
- * Default empty string.
- * @param int $post_id Optional. ID of the post to retrieve categories for. Defaults to the current post.
+ * @param string $separator Optional. Separator between the categories. By default, the links are placed
+ * in an unordered list. An empty string will result in the default behavior.
+ * @param string $parents Optional. How to display the parents. Accepts 'multiple', 'single', or empty.
+ * Default empty string.
+ * @param int|false $post_id Optional. ID of the post to retrieve categories for. Defaults to the current post.
*/
function the_category( $separator = '', $parents = '', $post_id = false ) {
echo get_the_category_list( $separator, $parents, $post_id );
@@ -793,7 +793,7 @@ function wp_tag_cloud( $args = '' ) {
* @return int Scaled count.
*/
function default_topic_count_scale( $count ) {
- return round( log10( $count + 1 ) * 100 );
+ return (int) round( log10( $count + 1 ) * 100 );
}
/**
diff --git a/src/wp-includes/class-wp-block-pattern-categories-registry.php b/src/wp-includes/class-wp-block-pattern-categories-registry.php
index 3d37a5940a..2d5fbcf2fe 100644
--- a/src/wp-includes/class-wp-block-pattern-categories-registry.php
+++ b/src/wp-includes/class-wp-block-pattern-categories-registry.php
@@ -107,7 +107,7 @@ final class WP_Block_Pattern_Categories_Registry {
* @since 5.5.0
*
* @param string $category_name Pattern category name including namespace.
- * @return array Registered pattern properties.
+ * @return array|null Registered pattern properties, or `null` if the pattern category is not registered.
*/
public function get_registered( $category_name ) {
if ( ! $this->is_registered( $category_name ) ) {
diff --git a/src/wp-includes/class-wp-block-patterns-registry.php b/src/wp-includes/class-wp-block-patterns-registry.php
index 3b5f053bfd..2afa8a853f 100644
--- a/src/wp-includes/class-wp-block-patterns-registry.php
+++ b/src/wp-includes/class-wp-block-patterns-registry.php
@@ -188,7 +188,7 @@ final class WP_Block_Patterns_Registry {
* @since 5.5.0
*
* @param string $pattern_name Block pattern name including namespace.
- * @return array Registered pattern properties.
+ * @return array|null Registered pattern properties or `null` if the pattern is not registered.
*/
public function get_registered( $pattern_name ) {
if ( ! $this->is_registered( $pattern_name ) ) {
diff --git a/src/wp-includes/class-wp-block-styles-registry.php b/src/wp-includes/class-wp-block-styles-registry.php
index 9a990173b4..8fb5e2eb23 100644
--- a/src/wp-includes/class-wp-block-styles-registry.php
+++ b/src/wp-includes/class-wp-block-styles-registry.php
@@ -140,7 +140,7 @@ final class WP_Block_Styles_Registry {
*
* @param string $block_name Block type name including namespace.
* @param string $block_style_name Block style name.
- * @return array Registered block style properties.
+ * @return array|null Registered block style properties or `null` if the block style is not registered.
*/
public function get_registered( $block_name, $block_style_name ) {
if ( ! $this->is_registered( $block_name, $block_style_name ) ) {
diff --git a/src/wp-includes/class-wp-comment-query.php b/src/wp-includes/class-wp-comment-query.php
index 6a72c0d209..03d3479b6c 100644
--- a/src/wp-includes/class-wp-comment-query.php
+++ b/src/wp-includes/class-wp-comment-query.php
@@ -579,9 +579,7 @@ class WP_Comment_Query {
}
}
- if ( ! empty( $status_clauses ) ) {
- $approved_clauses[] = '( ' . implode( ' OR ', $status_clauses ) . ' )';
- }
+ $approved_clauses[] = '( ' . implode( ' OR ', $status_clauses ) . ' )';
}
// User IDs or emails whose unapproved comments are included, regardless of $status.
diff --git a/src/wp-includes/class-wp-customize-widgets.php b/src/wp-includes/class-wp-customize-widgets.php
index 3db46ad088..b24a9c8b47 100644
--- a/src/wp-includes/class-wp-customize-widgets.php
+++ b/src/wp-includes/class-wp-customize-widgets.php
@@ -921,10 +921,12 @@ final class WP_Customize_Widgets {
</button>
<h3>
<span class="customize-action">
- <?php
+ <?php
+ $panel = $this->manager->get_panel( 'widgets' );
+ $panel_title = isset( $panel->title ) ? $panel->title : __( 'Widgets' );
/* translators: &#9656; is the unicode right-pointing triangle. %s: Section title in the Customizer. */
- printf( __( 'Customizing &#9656; %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) );
- ?>
+ printf( __( 'Customizing &#9656; %s' ), esc_html( $panel_title ) );
+ ?>
</span>
<?php _e( 'Add a Widget' ); ?>
</h3>
diff --git a/src/wp-includes/class-wp-image-editor-imagick.php b/src/wp-includes/class-wp-image-editor-imagick.php
index 2e7c7039d5..f57e6f281f 100644
--- a/src/wp-includes/class-wp-image-editor-imagick.php
+++ b/src/wp-includes/class-wp-image-editor-imagick.php
@@ -305,7 +305,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
* image operations within the time of the HTTP request.
*
* @since 6.2.0
- * @since 6.3.0 This method was deprecated.
+ * @deprecated 6.3.0 No longer used in core.
*
* @return int|null The new limit on success, null on failure.
*/
diff --git a/src/wp-includes/class-wp-oembed.php b/src/wp-includes/class-wp-oembed.php
index 2d59c2217d..43f95ed150 100644
--- a/src/wp-includes/class-wp-oembed.php
+++ b/src/wp-includes/class-wp-oembed.php
@@ -739,9 +739,9 @@ class WP_oEmbed {
*
* @since 2.9.0
*
- * @param string $return The returned oEmbed HTML.
- * @param object $data A data object result from an oEmbed provider.
- * @param string $url The URL of the content to be embedded.
+ * @param string|false $return The returned oEmbed HTML, or false on failure.
+ * @param object $data A data object result from an oEmbed provider.
+ * @param string $url The URL of the content to be embedded.
*/
return apply_filters( 'oembed_dataparse', $return, $data, $url );
}
@@ -752,10 +752,10 @@ class WP_oEmbed {
* @since 2.9.0 as strip_scribd_newlines()
* @since 3.0.0
*
- * @param string $html Existing HTML.
- * @param object $data Data object from WP_oEmbed::data2html()
- * @param string $url The original URL passed to oEmbed.
- * @return string Possibly modified $html
+ * @param string|false $html Existing HTML.
+ * @param object $data Data object from WP_oEmbed::data2html()
+ * @param string $url The original URL passed to oEmbed.
+ * @return string|false Possibly modified $html.
*/
public function _strip_newlines( $html, $data, $url ) {
if ( ! str_contains( $html, "\n" ) ) {
diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php
index cd41d4b200..f023c03cd0 100644
--- a/src/wp-includes/comment-template.php
+++ b/src/wp-includes/comment-template.php
@@ -2446,6 +2446,7 @@ function wp_list_comments( $args = array(), $comments = null ) {
* @since 4.6.0 Introduced the 'action' argument.
* @since 4.9.6 Introduced the 'cookies' default comment field.
* @since 5.5.0 Introduced the 'class_container' argument.
+ * @since 6.8.2 Introduced the 'novalidate' argument.
*
* @param array $args {
* Optional. Default arguments and form fields to override.
@@ -2467,6 +2468,7 @@ function wp_list_comments( $args = array(), $comments = null ) {
* Default 'Your email address will not be published.'.
* @type string $comment_notes_after HTML element for a message displayed after the textarea field.
* @type string $action The comment form element action attribute. Default '/wp-comments-post.php'.
+ * @type bool $novalidate Whether the novalidate attribute is added to the comment form. Default false.
* @type string $id_form The comment form element id attribute. Default 'commentform'.
* @type string $id_submit The comment submit element id attribute. Default 'submit'.
* @type string $class_container The comment form container class attribute. Default 'comment-respond'.
@@ -2646,6 +2648,7 @@ function comment_form( $args = array(), $post = null ) {
),
'comment_notes_after' => '',
'action' => site_url( '/wp-comments-post.php' ),
+ 'novalidate' => false,
'id_form' => 'commentform',
'id_submit' => 'submit',
'class_container' => 'comment-respond',
@@ -2729,7 +2732,7 @@ function comment_form( $args = array(), $post = null ) {
esc_url( $args['action'] ),
esc_attr( $args['id_form'] ),
esc_attr( $args['class_form'] ),
- ( $html5 ? ' novalidate' : '' )
+ ( $args['novalidate'] ? ' novalidate' : '' )
);
/**
diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php
index d0a7743c0e..3909683bce 100644
--- a/src/wp-includes/comment.php
+++ b/src/wp-includes/comment.php
@@ -446,6 +446,8 @@ function get_comment_count( $post_id = 0 ) {
/**
* Adds meta data field to a comment.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 2.9.0
*
* @link https://developer.wordpress.org/reference/functions/add_comment_meta/
@@ -474,6 +476,8 @@ function add_comment_meta( $comment_id, $meta_key, $meta_value, $unique = false
* value, will keep from removing duplicate metadata with the same key. It also
* allows removing all metadata matching key, if needed.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 2.9.0
*
* @link https://developer.wordpress.org/reference/functions/delete_comment_meta/
@@ -540,6 +544,8 @@ function wp_lazyload_comment_meta( array $comment_ids ) {
*
* If the meta field for the comment does not exist, it will be added.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 2.9.0
*
* @link https://developer.wordpress.org/reference/functions/update_comment_meta/
diff --git a/src/wp-includes/embed.php b/src/wp-includes/embed.php
index b5b30acead..a3c23be931 100644
--- a/src/wp-includes/embed.php
+++ b/src/wp-includes/embed.php
@@ -843,10 +843,10 @@ function _oembed_create_xml( $data, $node = null ) {
*
* @since 5.2.0
*
- * @param string $result The oEmbed HTML result.
- * @param object $data A data object result from an oEmbed provider.
- * @param string $url The URL of the content to be embedded.
- * @return string The filtered oEmbed result.
+ * @param string|false $result The oEmbed HTML result.
+ * @param object $data A data object result from an oEmbed provider.
+ * @param string $url The URL of the content to be embedded.
+ * @return string|false The filtered oEmbed result.
*/
function wp_filter_oembed_iframe_title_attribute( $result, $data, $url ) {
if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) {
@@ -910,10 +910,10 @@ function wp_filter_oembed_iframe_title_attribute( $result, $data, $url ) {
*
* @since 4.4.0
*
- * @param string $result The oEmbed HTML result.
- * @param object $data A data object result from an oEmbed provider.
- * @param string $url The URL of the content to be embedded.
- * @return string The filtered and sanitized oEmbed result.
+ * @param string|false $result The oEmbed HTML result.
+ * @param object $data A data object result from an oEmbed provider.
+ * @param string $url The URL of the content to be embedded.
+ * @return string|false The filtered and sanitized oEmbed result.
*/
function wp_filter_oembed_result( $result, $data, $url ) {
if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) {
diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php
index 3e02c17853..cf41630c4a 100644
--- a/src/wp-includes/link-template.php
+++ b/src/wp-includes/link-template.php
@@ -4298,6 +4298,8 @@ function the_shortlink( $text = '', $title = '', $before = '', $after = '' ) {
* - 'monsterid' (a monster)
* - 'wavatar' (a cartoon face)
* - 'identicon' (the "quilt", a geometric pattern)
+ * - 'initials' (initials based avatar with background color)
+ * - 'color' (generated background color)
* - 'mystery', 'mm', or 'mysteryman' (The Oyster Man)
* - 'blank' (transparent GIF)
* - 'gravatar_default' (the Gravatar logo)
@@ -4366,6 +4368,8 @@ function is_avatar_comment_type( $comment_type ) {
* - 'monsterid' (a monster)
* - 'wavatar' (a cartoon face)
* - 'identicon' (the "quilt", a geometric pattern)
+ * - 'initials' (initials based avatar with background color)
+ * - 'color' (generated background color)
* - 'mystery', 'mm', or 'mysteryman' (The Oyster Man)
* - 'blank' (transparent GIF)
* - 'gravatar_default' (the Gravatar logo)
@@ -4545,6 +4549,33 @@ function get_avatar_data( $id_or_email, $args = null ) {
'r' => $args['rating'],
);
+ // Handle additional parameters for the 'initials' avatar type
+ if ( 'initials' === $args['default'] ) {
+ $name = '';
+
+ if ( $user ) {
+ $name = ! empty( $user->display_name ) ? $user->display_name :
+ ( ! empty( $user->first_name ) && ! empty( $user->last_name ) ?
+ $user->first_name . ' ' . $user->last_name : $user->user_login );
+ } elseif ( is_object( $id_or_email ) && isset( $id_or_email->comment_author ) ) {
+ $name = $id_or_email->comment_author;
+ } elseif ( is_string( $id_or_email ) && false !== strpos( $id_or_email, '@' ) ) {
+ $name = str_replace( array( '.', '_', '-' ), ' ', substr( $id_or_email, 0, strpos( $id_or_email, '@' ) ) );
+ }
+
+ if ( ! empty( $name ) ) {
+ if ( preg_match( '/\p{Han}|\p{Hiragana}|\p{Katakana}|\p{Hangul}/u', $name ) || false === strpos( $name, ' ' ) ) {
+ $initials = mb_substr( $name, 0, min( 2, mb_strlen( $name, 'UTF-8' ) ), 'UTF-8' );
+ } else {
+ $first = mb_substr( $name, 0, 1, 'UTF-8' );
+ $last = mb_substr( $name, strrpos( $name, ' ' ) + 1, 1, 'UTF-8' );
+ $initials = $first . $last;
+ }
+
+ $url_args['initials'] = $initials;
+ }
+ }
+
/*
* Gravatars are always served over HTTPS.
*
diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php
index 86fe200f8d..4e7592bd74 100644
--- a/src/wp-includes/media-template.php
+++ b/src/wp-includes/media-template.php
@@ -443,7 +443,7 @@ function wp_print_media_templates() {
?>
</h2>
<div class="uploaded"><strong><?php _e( 'Uploaded on:' ); ?></strong> {{ data.dateFormatted }}</div>
- <div class="uploaded-by">
+ <div class="uploaded-by word-wrap-break-word">
<strong><?php _e( 'Uploaded by:' ); ?></strong>
<# if ( data.authorLink ) { #>
<a href="{{ data.authorLink }}">{{ data.authorName }}</a>
@@ -605,7 +605,7 @@ function wp_print_media_templates() {
<div class="centered">
<# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
<img src="{{ data.image.src }}" class="thumbnail" draggable="false" alt="" />
- <# } else if ( data.sizes ) {
+ <# } else if ( data.sizes ) {
if ( data.sizes.medium ) { #>
<img src="{{ data.sizes.medium.url }}" class="thumbnail" draggable="false" alt="" />
<# } else { #>
diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php
index da46ef90a7..5d95b0a188 100644
--- a/src/wp-includes/media.php
+++ b/src/wp-includes/media.php
@@ -2992,9 +2992,6 @@ function wp_underscore_playlist_templates() {
function wp_playlist_scripts( $type ) {
wp_enqueue_style( 'wp-mediaelement' );
wp_enqueue_script( 'wp-playlist' );
- ?>
-<!--[if lt IE 9]><script>document.createElement('<?php echo esc_js( $type ); ?>');</script><![endif]-->
- <?php
add_action( 'wp_footer', 'wp_underscore_playlist_templates', 0 );
add_action( 'admin_footer', 'wp_underscore_playlist_templates', 0 );
}
@@ -3502,14 +3499,7 @@ function wp_audio_shortcode( $attr, $content = '' ) {
}
}
- $html = '';
-
- if ( 'mediaelement' === $library && 1 === $instance ) {
- $html .= "<!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->\n";
- }
-
- $html .= sprintf( '<audio %s controls="controls">', implode( ' ', $attr_strings ) );
-
+ $html = sprintf( '<audio %s controls="controls">', implode( ' ', $attr_strings ) );
$fileurl = '';
$source = '<source type="%s" src="%s" />';
@@ -3787,14 +3777,7 @@ function wp_video_shortcode( $attr, $content = '' ) {
}
}
- $html = '';
-
- if ( 'mediaelement' === $library && 1 === $instance ) {
- $html .= "<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->\n";
- }
-
- $html .= sprintf( '<video %s controls="controls">', implode( ' ', $attr_strings ) );
-
+ $html = sprintf( '<video %s controls="controls">', implode( ' ', $attr_strings ) );
$fileurl = '';
$source = '<source type="%s" src="%s" />';
diff --git a/src/wp-includes/meta.php b/src/wp-includes/meta.php
index 6982e618c3..d60bf5e875 100644
--- a/src/wp-includes/meta.php
+++ b/src/wp-includes/meta.php
@@ -15,12 +15,14 @@ require ABSPATH . WPINC . '/class-wp-metadata-lazyloader.php';
/**
* Adds metadata for the specified object.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 2.9.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Metadata key.
* @param mixed $meta_value Metadata value. Arrays and objects are stored as serialized data and
@@ -65,11 +67,12 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique =
* Short-circuits adding metadata of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible hook names include:
*
+ * - `add_blog_metadata`
* - `add_post_metadata`
* - `add_comment_metadata`
* - `add_term_metadata`
@@ -77,11 +80,12 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique =
*
* @since 3.1.0
*
- * @param null|bool $check Whether to allow adding metadata for the given type.
- * @param int $object_id ID of the object metadata is for.
- * @param string $meta_key Metadata key.
- * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
- * @param bool $unique Whether the specified meta key should be unique for the object.
+ * @param null|int|false $check Whether to allow adding metadata for the given type. Return false or a meta ID
+ * to short-circuit the function. Return null to continue with the default behavior.
+ * @param int $object_id ID of the object metadata is for.
+ * @param string $meta_key Metadata key.
+ * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
+ * @param bool $unique Whether the specified meta key should be unique for the object.
*/
$check = apply_filters( "add_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $unique );
if ( null !== $check ) {
@@ -105,10 +109,11 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique =
* Fires immediately before meta of a specific type is added.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible hook names include:
*
+ * - `add_blog_meta`
* - `add_post_meta`
* - `add_comment_meta`
* - `add_term_meta`
@@ -143,10 +148,11 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique =
* Fires immediately after meta of a specific type is added.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible hook names include:
*
+ * - `added_blog_meta`
* - `added_post_meta`
* - `added_comment_meta`
* - `added_term_meta`
@@ -168,12 +174,14 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique =
* Updates metadata for the specified object. If no value already exists for the specified object
* ID and metadata key, the metadata will be added.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 2.9.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Metadata key.
* @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
@@ -218,11 +226,12 @@ function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_
* Short-circuits updating metadata of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible hook names include:
*
+ * - `update_blog_metadata`
* - `update_post_metadata`
* - `update_comment_metadata`
* - `update_term_metadata`
@@ -277,10 +286,11 @@ function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_
* Fires immediately before updating metadata of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible hook names include:
*
+ * - `update_blog_meta`
* - `update_post_meta`
* - `update_comment_meta`
* - `update_term_meta`
@@ -323,10 +333,11 @@ function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_
* Fires immediately after updating metadata of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible hook names include:
*
+ * - `updated_blog_meta`
* - `updated_post_meta`
* - `updated_comment_meta`
* - `updated_term_meta`
@@ -363,12 +374,14 @@ function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_
/**
* Deletes metadata for the specified object.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 2.9.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Metadata key.
* @param mixed $meta_value Optional. Metadata value. Must be serializable if non-scalar.
@@ -411,11 +424,12 @@ function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $
* Short-circuits deleting metadata of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible hook names include:
*
+ * - `delete_blog_metadata`
* - `delete_post_metadata`
* - `delete_comment_metadata`
* - `delete_term_metadata`
@@ -466,10 +480,11 @@ function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $
* Fires immediately before deleting metadata of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible hook names include:
*
+ * - `delete_blog_meta`
* - `delete_post_meta`
* - `delete_comment_meta`
* - `delete_term_meta`
@@ -515,10 +530,11 @@ function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $
* Fires immediately after deleting metadata of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible hook names include:
*
+ * - `deleted_blog_meta`
* - `deleted_post_meta`
* - `deleted_comment_meta`
* - `deleted_term_meta`
@@ -563,8 +579,8 @@ function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $
* @see get_metadata_raw()
* @see get_metadata_default()
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for
* the specified object. Default empty string.
@@ -596,8 +612,8 @@ function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false )
*
* @since 5.5.0
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for
* the specified object. Default empty string.
@@ -623,11 +639,12 @@ function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal
* Short-circuits the return value of a meta field.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible filter names include:
*
+ * - `get_blog_metadata`
* - `get_post_metadata`
* - `get_comment_metadata`
* - `get_term_metadata`
@@ -641,8 +658,8 @@ function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Metadata key.
* @param bool $single Whether to return only the first value of the specified `$meta_key`.
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
*/
$check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single, $meta_type );
if ( null !== $check ) {
@@ -687,8 +704,8 @@ function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal
*
* @since 5.5.0
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Metadata key.
* @param bool $single Optional. If true, return only the first value of the specified `$meta_key`.
@@ -707,10 +724,11 @@ function get_metadata_default( $meta_type, $object_id, $meta_key, $single = fals
* Filters the default metadata value for a specified meta key and object.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible filter names include:
*
+ * - `default_blog_metadata`
* - `default_post_metadata`
* - `default_comment_metadata`
* - `default_term_metadata`
@@ -723,8 +741,8 @@ function get_metadata_default( $meta_type, $object_id, $meta_key, $single = fals
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Metadata key.
* @param bool $single Whether to return only the first value of the specified `$meta_key`.
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
*/
$value = apply_filters( "default_{$meta_type}_metadata", $value, $object_id, $meta_key, $single, $meta_type );
@@ -740,8 +758,8 @@ function get_metadata_default( $meta_type, $object_id, $meta_key, $single = fals
*
* @since 3.3.0
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Metadata key.
* @return bool Whether a meta field with the given key exists.
@@ -783,8 +801,8 @@ function metadata_exists( $meta_type, $object_id, $meta_key ) {
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $meta_id ID for a specific meta row.
* @return stdClass|false {
* Metadata object, or boolean `false` if the metadata doesn't exist.
@@ -793,6 +811,7 @@ function metadata_exists( $meta_type, $object_id, $meta_key ) {
* @type mixed $meta_value The unserialized meta value.
* @type string $meta_id Optional. The meta ID when the meta type is any value except 'user'.
* @type string $umeta_id Optional. The meta ID when the meta type is 'user'.
+ * @type string $blog_id Optional. The object ID when the meta type is 'blog'.
* @type string $post_id Optional. The object ID when the meta type is 'post'.
* @type string $comment_id Optional. The object ID when the meta type is 'comment'.
* @type string $term_id Optional. The object ID when the meta type is 'term'.
@@ -820,11 +839,12 @@ function get_metadata_by_mid( $meta_type, $meta_id ) {
* Short-circuits the return value when fetching a meta field by meta ID.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible hook names include:
*
+ * - `get_blog_metadata_by_mid`
* - `get_post_metadata_by_mid`
* - `get_comment_metadata_by_mid`
* - `get_term_metadata_by_mid`
@@ -862,8 +882,8 @@ function get_metadata_by_mid( $meta_type, $meta_id ) {
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $meta_id ID for a specific meta row.
* @param string $meta_value Metadata value. Must be serializable if non-scalar.
* @param string|false $meta_key Optional. You can provide a meta key to update it. Default false.
@@ -894,11 +914,12 @@ function update_metadata_by_mid( $meta_type, $meta_id, $meta_value, $meta_key =
* Short-circuits updating metadata of a specific type by meta ID.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible hook names include:
*
+ * - `update_blog_metadata_by_mid`
* - `update_post_metadata_by_mid`
* - `update_comment_metadata_by_mid`
* - `update_term_metadata_by_mid`
@@ -988,8 +1009,8 @@ function update_metadata_by_mid( $meta_type, $meta_id, $meta_value, $meta_key =
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $meta_id ID for a specific meta row.
* @return bool True on successful delete, false on failure.
*/
@@ -1019,11 +1040,12 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) {
* Short-circuits deleting metadata of a specific type by meta ID.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible hook names include:
*
+ * - `delete_blog_metadata_by_mid`
* - `delete_post_metadata_by_mid`
* - `delete_comment_metadata_by_mid`
* - `delete_term_metadata_by_mid`
@@ -1059,8 +1081,6 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) {
*
* - `delete_postmeta`
* - `delete_commentmeta`
- * - `delete_termmeta`
- * - `delete_usermeta`
*
* @since 3.4.0
*
@@ -1090,8 +1110,6 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) {
*
* - `deleted_postmeta`
* - `deleted_commentmeta`
- * - `deleted_termmeta`
- * - `deleted_usermeta`
*
* @since 3.4.0
*
@@ -1115,8 +1133,8 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) {
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string|int[] $object_ids Array or comma delimited list of object IDs to update cache for.
* @return array|false Metadata cache for the specified objects, or false on failure.
*/
@@ -1145,11 +1163,12 @@ function update_meta_cache( $meta_type, $object_ids ) {
* Short-circuits updating the metadata cache of a specific type.
*
* The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
* Returning a non-null value will effectively short-circuit the function.
*
* Possible hook names include:
*
+ * - `update_blog_metadata_cache`
* - `update_post_metadata_cache`
* - `update_comment_metadata_cache`
* - `update_term_metadata_cache`
@@ -1268,8 +1287,8 @@ function get_meta_sql( $meta_query, $type, $primary_table, $primary_id_column, $
*
* @global wpdb $wpdb WordPress database abstraction object.
*
- * @param string $type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @return string|false Metadata table name, or false if no metadata table exists
*/
function _get_meta_table( $type ) {
@@ -1290,8 +1309,8 @@ function _get_meta_table( $type ) {
* @since 3.1.3
*
* @param string $meta_key Metadata key.
- * @param string $meta_type Optional. Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table. Default empty string.
+ * @param string $meta_type Optional. Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table. Default empty string.
* @return bool Whether the meta key is considered protected.
*/
function is_protected_meta( $meta_key, $meta_type = '' ) {
@@ -1305,8 +1324,8 @@ function is_protected_meta( $meta_key, $meta_type = '' ) {
*
* @param bool $protected Whether the key is considered protected.
* @param string $meta_key Metadata key.
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
*/
return apply_filters( 'is_protected_meta', $protected, $meta_key, $meta_type );
}
@@ -1319,8 +1338,8 @@ function is_protected_meta( $meta_key, $meta_type = '' ) {
*
* @param string $meta_key Metadata key.
* @param mixed $meta_value Metadata value to sanitize.
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string $object_subtype Optional. The subtype of the object type. Default empty string.
* @return mixed Sanitized $meta_value.
*/
@@ -1331,15 +1350,15 @@ function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype =
* Filters the sanitization of a specific meta key of a specific meta type and subtype.
*
* The dynamic portions of the hook name, `$object_type`, `$meta_key`,
- * and `$object_subtype`, refer to the metadata object type (comment, post, term, or user),
+ * and `$object_subtype`, refer to the metadata object type (blog, comment, post, term, or user),
* the meta key value, and the object subtype respectively.
*
* @since 4.9.8
*
* @param mixed $meta_value Metadata value to sanitize.
* @param string $meta_key Metadata key.
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string $object_subtype Object subtype.
*/
return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $meta_value, $meta_key, $object_type, $object_subtype );
@@ -1349,15 +1368,15 @@ function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype =
* Filters the sanitization of a specific meta key of a specific meta type.
*
* The dynamic portions of the hook name, `$meta_type`, and `$meta_key`,
- * refer to the metadata object type (comment, post, term, or user) and the meta
+ * refer to the metadata object type (blog, comment, post, term, or user) and the meta
* key value, respectively.
*
* @since 3.3.0
*
* @param mixed $meta_value Metadata value to sanitize.
* @param string $meta_key Metadata key.
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
*/
return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}", $meta_value, $meta_key, $object_type );
}
@@ -1369,7 +1388,7 @@ function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype =
* an object subtype is omitted, the meta key will be registered for the entire object type, however it can be partly
* overridden in case a more specific meta key of the same name exists for the same object type and a subtype.
*
- * If an object type does not support any subtypes, such as users or comments, you should commonly call this function
+ * If an object type does not support any subtypes, such as blogs, users, or comments, you should commonly call this function
* without passing a subtype.
*
* @since 3.3.0
@@ -1382,8 +1401,8 @@ function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype =
* @since 6.4.0 The `$revisions_enabled` argument was added to the arguments array.
* @since 6.7.0 The `label` argument was added to the arguments array.
*
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string $meta_key Meta key to register.
* @param array $args {
* Data used to describe the meta key when registered.
@@ -1461,8 +1480,8 @@ function register_meta( $object_type, $meta_key, $args, $deprecated = null ) {
*
* @param array $args Array of meta registration arguments.
* @param array $defaults Array of default arguments.
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string $meta_key Meta key.
*/
$args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
@@ -1557,8 +1576,8 @@ function register_meta( $object_type, $meta_key, $args, $deprecated = null ) {
* @param string $meta_key Metadata key.
* @param bool $single If true, return only the first value of the specified `$meta_key`.
* This parameter has no effect if `$meta_key` is not specified.
- * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @return mixed An array of default values if `$single` is false.
* The default value of the meta field if `$single` is true.
*/
@@ -1612,8 +1631,8 @@ function filter_default_metadata( $value, $object_id, $meta_key, $single, $meta_
* @since 4.6.0
* @since 4.9.8 The `$object_subtype` parameter was added.
*
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string $meta_key Metadata key.
* @param string $object_subtype Optional. The subtype of the object type. Default empty string.
* @return bool True if the meta key is registered to the object type and, if provided,
@@ -1631,8 +1650,8 @@ function registered_meta_key_exists( $object_type, $meta_key, $object_subtype =
* @since 4.6.0
* @since 4.9.8 The `$object_subtype` parameter was added.
*
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string $meta_key Metadata key.
* @param string $object_subtype Optional. The subtype of the object type. Default empty string.
* @return bool True if successful. False if the meta key was not registered.
@@ -1681,8 +1700,8 @@ function unregister_meta_key( $object_type, $meta_key, $object_subtype = '' ) {
* @since 4.6.0
* @since 4.9.8 The `$object_subtype` parameter was added.
*
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param string $object_subtype Optional. The subtype of the object type. Default empty string.
* @return array[] List of registered metadata args, keyed by their meta keys.
*/
@@ -1704,8 +1723,8 @@ function get_registered_meta_keys( $object_type, $object_subtype = '' ) {
*
* @since 4.6.0
*
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object the metadata is for.
* @param string $meta_key Optional. Registered metadata key. If not specified, retrieve all registered
* metadata for the specified object.
@@ -1767,8 +1786,8 @@ function _wp_register_meta_args_allowed_list( $args, $default_args ) {
*
* @since 4.9.8
*
- * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
- * or any other object type with an associated meta table.
+ * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
+ * 'user', or any other object type with an associated meta table.
* @param int $object_id ID of the object to retrieve its subtype.
* @return string The object subtype or an empty string if unspecified subtype.
*/
@@ -1814,13 +1833,14 @@ function get_object_subtype( $object_type, $object_id ) {
}
/**
- * Filters the object subtype identifier for a non-standard object type.
+ * Filters the object subtype identifier.
*
* The dynamic portion of the hook name, `$object_type`, refers to the meta object type
- * (post, comment, term, user, or any other type with an associated meta table).
+ * (blog, post, comment, term, user, or any other type with an associated meta table).
*
* Possible hook names include:
*
+ * - `get_object_subtype_blog`
* - `get_object_subtype_post`
* - `get_object_subtype_comment`
* - `get_object_subtype_term`
@@ -1828,7 +1848,7 @@ function get_object_subtype( $object_type, $object_id ) {
*
* @since 4.9.8
*
- * @param string $object_subtype Empty string to override.
+ * @param string $object_subtype Object subtype or empty string to override.
* @param int $object_id ID of the object to get the subtype for.
*/
return apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id );
diff --git a/src/wp-includes/ms-site.php b/src/wp-includes/ms-site.php
index 2a2b1474c5..a8d9f8e2b6 100644
--- a/src/wp-includes/ms-site.php
+++ b/src/wp-includes/ms-site.php
@@ -1022,6 +1022,8 @@ function clean_blog_cache( $blog ) {
/**
* Adds metadata to a site.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 5.1.0
*
* @param int $site_id Site ID.
@@ -1048,6 +1050,8 @@ function add_site_meta( $site_id, $meta_key, $meta_value, $unique = false ) {
* value, will keep from removing duplicate metadata with the same key. It also
* allows removing all metadata matching key, if needed.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 5.1.0
*
* @param int $site_id Site ID.
@@ -1090,11 +1094,13 @@ function get_site_meta( $site_id, $key = '', $single = false ) {
/**
* Updates metadata for a site.
*
- * Use the $prev_value parameter to differentiate between meta fields with the
+ * Use the `$prev_value` parameter to differentiate between meta fields with the
* same key and site ID.
*
* If the meta field for the site does not exist, it will be added.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 5.1.0
*
* @param int $site_id Site ID.
diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php
index e7ce2edb41..1dbac5e1d7 100644
--- a/src/wp-includes/pluggable.php
+++ b/src/wp-includes/pluggable.php
@@ -446,10 +446,10 @@ if ( ! function_exists( 'wp_mail' ) ) :
$phpmailer->addAddress( $address, $recipient_name );
break;
case 'cc':
- $phpmailer->addCc( $address, $recipient_name );
+ $phpmailer->addCC( $address, $recipient_name );
break;
case 'bcc':
- $phpmailer->addBcc( $address, $recipient_name );
+ $phpmailer->addBCC( $address, $recipient_name );
break;
case 'reply_to':
$phpmailer->addReplyTo( $address, $recipient_name );
@@ -2676,9 +2676,11 @@ if ( ! function_exists( 'wp_hash_password' ) ) :
* - `PASSWORD_ARGON2ID`
* - `PASSWORD_DEFAULT`
*
+ * The values of the algorithm constants are strings in PHP 7.4+ and integers in PHP 7.3 and earlier.
+ *
* @since 6.8.0
*
- * @param string $algorithm The hashing algorithm. Default is the value of the `PASSWORD_BCRYPT` constant.
+ * @param string|int $algorithm The hashing algorithm. Default is the value of the `PASSWORD_BCRYPT` constant.
*/
$algorithm = apply_filters( 'wp_hash_password_algorithm', PASSWORD_BCRYPT );
@@ -2688,12 +2690,14 @@ if ( ! function_exists( 'wp_hash_password' ) ) :
* The default hashing algorithm is bcrypt, but this can be changed via the {@see 'wp_hash_password_algorithm'}
* filter. You must ensure that the options are appropriate for the algorithm in use.
*
+ * The values of the algorithm constants are strings in PHP 7.4+ and integers in PHP 7.3 and earlier.
+ *
* @since 6.8.0
*
- * @param array $options Array of options to pass to the password hashing functions.
- * By default this is an empty array which means the default
- * options will be used.
- * @param string $algorithm The hashing algorithm in use.
+ * @param array $options Array of options to pass to the password hashing functions.
+ * By default this is an empty array which means the default
+ * options will be used.
+ * @param string|int $algorithm The hashing algorithm in use.
*/
$options = apply_filters( 'wp_hash_password_options', array(), $algorithm );
@@ -3048,6 +3052,8 @@ if ( ! function_exists( 'get_avatar' ) ) :
* - 'monsterid' (a monster)
* - 'wavatar' (a cartoon face)
* - 'identicon' (the "quilt", a geometric pattern)
+ * - 'initials' (initials based avatar with background color)
+ * - 'color' (generated background color)
* - 'mystery', 'mm', or 'mysteryman' (The Oyster Man)
* - 'blank' (transparent GIF)
* - 'gravatar_default' (the Gravatar logo)
diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php
index 19fada6383..b312ac394b 100644
--- a/src/wp-includes/post.php
+++ b/src/wp-includes/post.php
@@ -2608,6 +2608,8 @@ function get_posts( $args = null ) {
*
* Post meta data is called "Custom Fields" on the Administration Screen.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 1.5.0
*
* @param int $post_id Post ID.
@@ -2640,6 +2642,8 @@ function add_post_meta( $post_id, $meta_key, $meta_value, $unique = false ) {
* value, will keep from removing duplicate metadata with the same key. It also
* allows removing all metadata matching the key, if needed.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 1.5.0
*
* @param int $post_id Post ID.
@@ -2695,6 +2699,8 @@ function get_post_meta( $post_id, $key = '', $single = false ) {
*
* Can be used in place of add_post_meta().
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 1.5.0
*
* @param int $post_id Post ID.
@@ -4868,6 +4874,15 @@ function wp_insert_post( $postarr, $wp_error = false, $fire_after_hooks = true )
}
}
+ /**
+ * Fires immediately before a new post is inserted in the database.
+ *
+ * @since 6.9.0
+ *
+ * @param array $data Array of unslashed post data.
+ */
+ do_action( 'pre_post_insert', $data );
+
if ( false === $wpdb->insert( $wpdb->posts, $data ) ) {
if ( $wp_error ) {
if ( 'attachment' === $post_type ) {
@@ -6862,7 +6877,9 @@ function wp_get_attachment_metadata( $attachment_id = 0, $unfiltered = false ) {
*
* @param int $attachment_id Attachment post ID.
* @param array $data Attachment meta data.
- * @return int|false False if $post is invalid.
+ * @return int|bool Whether the metadata was successfully updated.
+ * True on success, the Meta ID if the key didn't exist.
+ * False if $post is invalid, on failure, or if $data is the same as the existing metadata.
*/
function wp_update_attachment_metadata( $attachment_id, $data ) {
$attachment_id = (int) $attachment_id;
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php
index 004f5851a2..66cf8785e4 100644
--- a/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php
@@ -147,6 +147,18 @@ class WP_REST_Settings_Controller extends WP_REST_Controller {
$params = $request->get_params();
+ if ( empty( $params ) || ! empty( array_diff_key( $params, $options ) ) ) {
+ $message = empty( $params )
+ ? __( 'Request body cannot be empty.' )
+ : __( 'Invalid parameter(s) provided.' );
+
+ return new WP_Error(
+ 'rest_invalid_param',
+ $message,
+ array( 'status' => 400 )
+ );
+ }
+
foreach ( $options as $name => $args ) {
if ( ! array_key_exists( $name, $params ) ) {
continue;
diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php
index d439629882..cd2c06e4cc 100644
--- a/src/wp-includes/script-loader.php
+++ b/src/wp-includes/script-loader.php
@@ -396,7 +396,7 @@ function wp_default_packages_inline_scripts( $scripts ) {
"\n",
array(
'( function() {',
- ' var userId = ' . get_current_user_ID() . ';',
+ ' var userId = ' . get_current_user_id() . ';',
' var storageKey = "WP_DATA_USER_" + userId;',
' wp.data',
' .use( wp.data.plugins.persistence, { storageKey: storageKey } );',
@@ -997,8 +997,6 @@ function wp_default_scripts( $scripts ) {
// Not used in core, replaced by imgAreaSelect.
$scripts->add( 'jcrop', '/wp-includes/js/jcrop/jquery.Jcrop.min.js', array( 'jquery' ), '0.9.15' );
- $scripts->add( 'swfobject', '/wp-includes/js/swfobject.js', array(), '2.2-20120417' );
-
// Error messages for Plupload.
$uploader_l10n = array(
'queue_limit_exceeded' => __( 'You have attempted to queue too many files.' ),
@@ -1046,12 +1044,6 @@ function wp_default_scripts( $scripts ) {
$scripts->add( 'wp-plupload', "/wp-includes/js/plupload/wp-plupload$suffix.js", array( 'plupload', 'jquery', 'json2', 'media-models' ), false, 1 );
did_action( 'init' ) && $scripts->localize( 'wp-plupload', 'pluploadL10n', $uploader_l10n );
- // Keep 'swfupload' for back-compat.
- $scripts->add( 'swfupload', '/wp-includes/js/swfupload/swfupload.js', array(), '2201-20110113' );
- $scripts->add( 'swfupload-all', false, array( 'swfupload' ), '2201' );
- $scripts->add( 'swfupload-handlers', "/wp-includes/js/swfupload/handlers$suffix.js", array( 'swfupload-all', 'jquery' ), '2201-20110524' );
- did_action( 'init' ) && $scripts->localize( 'swfupload-handlers', 'swfuploadL10n', $uploader_l10n );
-
$scripts->add( 'comment-reply', "/wp-includes/js/comment-reply$suffix.js", array(), false, 1 );
did_action( 'init' ) && $scripts->add_data( 'comment-reply', 'strategy', 'async' );
diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php
index e89855264d..a6c47e43ec 100644
--- a/src/wp-includes/taxonomy.php
+++ b/src/wp-includes/taxonomy.php
@@ -1382,6 +1382,8 @@ function get_terms( $args = array(), $deprecated = '' ) {
/**
* Adds metadata to a term.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 4.4.0
*
* @param int $term_id Term ID.
@@ -1409,6 +1411,8 @@ function add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) {
/**
* Removes metadata matching criteria from a term.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 4.4.0
*
* @param int $term_id Term ID.
@@ -1455,6 +1459,8 @@ function get_term_meta( $term_id, $key = '', $single = false ) {
*
* If the meta field for the term does not exist, it will be added.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 4.4.0
*
* @param int $term_id Term ID.
@@ -4892,11 +4898,13 @@ function is_object_in_term( $object_id, $taxonomy, $terms = null ) {
if ( is_wp_error( $object_terms ) ) {
return $object_terms;
}
+
if ( empty( $object_terms ) ) {
return false;
}
+
if ( empty( $terms ) ) {
- return ( ! empty( $object_terms ) );
+ return true;
}
$terms = (array) $terms;
diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php
index b4a71d855a..0727086aee 100644
--- a/src/wp-includes/theme.php
+++ b/src/wp-includes/theme.php
@@ -4349,6 +4349,8 @@ function create_initial_theme_features() {
*
* @since 5.9.0
*
+ * @global string[] $wp_theme_directories
+ *
* @return bool Whether the active theme is a block-based theme or not.
*/
function wp_is_block_theme() {
diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php
index 6d53726327..4dacf58628 100644
--- a/src/wp-includes/user.php
+++ b/src/wp-includes/user.php
@@ -637,7 +637,7 @@ function count_user_posts( $userid, $post_type = 'post', $public_only = false )
* @since 4.1.0 Added `$post_type` argument.
* @since 4.3.1 Added `$public_only` argument.
*
- * @param int $count The user's post count.
+ * @param string $count The user's post count as a numeric string.
* @param int $userid User ID.
* @param string|array $post_type Single post type or array of post types to count the number of posts for.
* @param bool $public_only Whether to limit counted posts to public posts.
@@ -1202,6 +1202,8 @@ function is_user_member_of_blog( $user_id = 0, $blog_id = 0 ) {
/**
* Adds meta data to a user.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 3.0.0
*
* @param int $user_id User ID.
@@ -1228,6 +1230,8 @@ function add_user_meta( $user_id, $meta_key, $meta_value, $unique = false ) {
* value, will keep from removing duplicate metadata with the same key. It also
* allows removing all metadata matching key, if needed.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 3.0.0
*
* @link https://developer.wordpress.org/reference/functions/delete_user_meta/
@@ -1279,6 +1283,8 @@ function get_user_meta( $user_id, $key = '', $single = false ) {
*
* If the meta field for the user does not exist, it will be added.
*
+ * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
+ *
* @since 3.0.0
*
* @link https://developer.wordpress.org/reference/functions/update_user_meta/
@@ -2280,7 +2286,10 @@ function wp_insert_user( $userdata ) {
*/
$user_nicename = apply_filters( 'pre_user_nicename', $user_nicename );
- if ( mb_strlen( $user_nicename ) > 50 ) {
+ // Check if the sanitized nicename is empty.
+ if ( empty( $user_nicename ) ) {
+ return new WP_Error( 'empty_user_nicename', __( 'Cannot create a user with an empty nicename.' ) );
+ } elseif ( mb_strlen( $user_nicename ) > 50 ) {
return new WP_Error( 'user_nicename_too_long', __( 'Nicename may not be longer than 50 characters.' ) );
}
diff --git a/tests/phpunit/includes/abstract-testcase.php b/tests/phpunit/includes/abstract-testcase.php
index f665bdafb1..29ce8d8b53 100644
--- a/tests/phpunit/includes/abstract-testcase.php
+++ b/tests/phpunit/includes/abstract-testcase.php
@@ -1,5 +1,6 @@
<?php
+require_once __DIR__ . '/build-visual-html-tree.php';
require_once __DIR__ . '/factory.php';
require_once __DIR__ . '/trac.php';
@@ -13,7 +14,6 @@ require_once __DIR__ . '/trac.php';
* All WordPress unit tests should inherit from this class.
*/
abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase {
-
protected static $forced_tickets = array();
protected $expected_deprecated = array();
protected $caught_deprecated = array();
@@ -136,6 +136,21 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase {
$this->start_transaction();
$this->expectDeprecated();
add_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) );
+ add_filter( 'wp_hash_password_options', array( $this, 'wp_hash_password_options' ), 1, 2 );
+ }
+
+ /**
+ * Sets the bcrypt cost option for password hashing during tests.
+ *
+ * @param array $options The options for password hashing.
+ * @param string|int $algorithm The algorithm to use for hashing. This is a string in PHP 7.4+ and an integer in PHP 7.3 and earlier.
+ */
+ public function wp_hash_password_options( array $options, $algorithm ): array {
+ if ( PASSWORD_BCRYPT === $algorithm ) {
+ $options['cost'] = 5;
+ }
+
+ return $options;
}
/**
@@ -1181,6 +1196,44 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase {
}
/**
+ * Check HTML markup (including blocks) for semantic equivalence.
+ *
+ * Given two markup strings, assert that they translate to the same semantic HTML tree,
+ * normalizing tag names, attribute names, and attribute order. Furthermore, attributes
+ * and class names are sorted and deduplicated, and whitespace in style attributes
+ * is normalized. Finally, block delimiter comments are recognized and normalized,
+ * applying the same principles.
+ *
+ * @since 6.9.0
+ *
+ * @param string $expected The expected HTML.
+ * @param string $actual The actual HTML.
+ * @param string|null $fragment_context Optional. The fragment context, for example "<td>" expected HTML
+ * must occur within "<table><tr>" fragment context. Default "<body>".
+ * Only "<body>" or `null` are supported at this time.
+ * Set to `null` to parse a full HTML document.
+ * @param string|null $message Optional. The assertion error message.
+ */
+ public function assertEqualHTML( string $expected, string $actual, ?string $fragment_context = '<body>', $message = 'HTML markup was not equivalent.' ): void {
+ try {
+ $tree_expected = build_visual_html_tree( $expected, $fragment_context );
+ $tree_actual = build_visual_html_tree( $actual, $fragment_context );
+ } catch ( Exception $e ) {
+ // For PHP 8.4+, we can retry, using the built-in DOM\HTMLDocument parser.
+ if ( class_exists( 'DOM\HtmlDocument' ) ) {
+ $dom_expected = DOM\HtmlDocument::createFromString( $expected, LIBXML_NOERROR );
+ $tree_expected = build_visual_html_tree( $dom_expected->saveHtml(), $fragment_context );
+ $dom_actual = DOM\HtmlDocument::createFromString( $actual, LIBXML_NOERROR );
+ $tree_actual = build_visual_html_tree( $dom_actual->saveHtml(), $fragment_context );
+ } else {
+ throw $e;
+ }
+ }
+
+ $this->assertSame( $tree_expected, $tree_actual, $message );
+ }
+
+ /**
* Helper function to convert a single-level array containing text strings to a named data provider.
*
* The value of the data set will also be used as the name of the data set.
diff --git a/tests/phpunit/includes/build-visual-html-tree.php b/tests/phpunit/includes/build-visual-html-tree.php
new file mode 100644
index 0000000000..e0f6c3ac3d
--- /dev/null
+++ b/tests/phpunit/includes/build-visual-html-tree.php
@@ -0,0 +1,304 @@
+<?php
+
+/* phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped */
+
+/**
+ * Generates representation of the semantic HTML tree structure.
+ *
+ * This is inspired by the representation used by the HTML5lib tests. It's been extended here for
+ * blocks to render the semantic structure of blocks and their attributes.
+ * The order of attributes and class names is normalized both for HTML tags and blocks,
+ * as is the whitespace in HTML tags' style attribute.
+ *
+ * For example, consider the following block markup:
+ *
+ * <!-- wp:separator {"className":"is-style-default has-custom-classname","style":{"spacing":{"margin":{"top":"50px","bottom":"50px"}}},"backgroundColor":"accent-1"} -->
+ * <hr class="wp-block-separator is-style-default has-custom-classname" style="margin-top: 50px; margin-bottom: 50px" />
+ * <!-- /wp:separator -->
+ *
+ * This will be represented as:
+ *
+ * BLOCK["core/separator"]
+ * {
+ * "backgroundColor": "accent-1",
+ * "className": "has-custom-classname is-style-default",
+ * "style": {
+ * "spacing": {
+ * "margin": {
+ * "top": "50px",
+ * "bottom": "50px"
+ * }
+ * }
+ * }
+ * }
+ * <hr>
+ * class="has-custom-classname is-style-default wp-block-separator"
+ * style="margin-top:50px;margin-bottom:50px;"
+ *
+ *
+ * @see https://github.com/WordPress/wordpress-develop/blob/trunk/tests/phpunit/data/html5lib-tests/tree-construction/README.md
+ *
+ * @since 6.9.0
+ *
+ * @throws WP_HTML_Unsupported_Exception|Error If the markup could not be parsed.
+ *
+ * @param string $html Given test HTML.
+ * @param string|null $fragment_context Context element in which to parse HTML, such as BODY or SVG.
+ * @return string Tree structure of parsed HTML, if supported.
+ */
+function build_visual_html_tree( string $html, ?string $fragment_context ): string {
+ $processor = $fragment_context
+ ? WP_HTML_Processor::create_fragment( $html, $fragment_context )
+ : WP_HTML_Processor::create_full_parser( $html );
+ if ( null === $processor ) {
+ throw new Error( 'Could not create a parser.' );
+ }
+ $tree_indent = ' ';
+
+ $output = '';
+ $indent_level = 0;
+ $was_text = null;
+ $text_node = '';
+
+ $block_context = array();
+
+ while ( $processor->next_token() ) {
+ if ( null !== $processor->get_last_error() ) {
+ break;
+ }
+
+ $token_name = $processor->get_token_name();
+ $token_type = $processor->get_token_type();
+ $is_closer = $processor->is_tag_closer();
+
+ if ( $was_text && '#text' !== $token_name ) {
+ if ( '' !== $text_node ) {
+ $output .= "{$text_node}\"\n";
+ }
+ $was_text = false;
+ $text_node = '';
+ }
+
+ switch ( $token_type ) {
+ case '#doctype':
+ $doctype = $processor->get_doctype_info();
+ $output .= "<!DOCTYPE {$doctype->name}";
+ if ( null !== $doctype->public_identifier || null !== $doctype->system_identifier ) {
+ $output .= " \"{$doctype->public_identifier}\" \"{$doctype->system_identifier}\"";
+ }
+ $output .= ">\n";
+ break;
+
+ case '#tag':
+ $namespace = $processor->get_namespace();
+ $tag_name = 'html' === $namespace
+ ? strtolower( $processor->get_tag() )
+ : "{$namespace} {$processor->get_qualified_tag_name()}";
+
+ if ( $is_closer ) {
+ --$indent_level;
+
+ if ( 'html' === $namespace && 'TEMPLATE' === $token_name ) {
+ --$indent_level;
+ }
+
+ break;
+ }
+
+ $tag_indent = $indent_level;
+
+ if ( $processor->expects_closer() ) {
+ ++$indent_level;
+ }
+
+ $output .= str_repeat( $tree_indent, $tag_indent ) . "<{$tag_name}>\n";
+
+ $attribute_names = $processor->get_attribute_names_with_prefix( '' );
+ if ( $attribute_names ) {
+ $sorted_attributes = array();
+ foreach ( $attribute_names as $attribute_name ) {
+ $sorted_attributes[ $attribute_name ] = $processor->get_qualified_attribute_name( $attribute_name );
+ }
+
+ /*
+ * Sorts attributes to match html5lib sort order.
+ *
+ * - First comes normal HTML attributes.
+ * - Then come adjusted foreign attributes; these have spaces in their names.
+ * - Finally come non-adjusted foreign attributes; these have a colon in their names.
+ *
+ * Example:
+ *
+ * From: <math xlink:author definitionurl xlink:title xlink:show>
+ * Sorted: 'definitionURL', 'xlink show', 'xlink title', 'xlink:author'
+ */
+ uasort(
+ $sorted_attributes,
+ static function ( $a, $b ) {
+ $a_has_ns = str_contains( $a, ':' );
+ $b_has_ns = str_contains( $b, ':' );
+
+ // Attributes with `:` should follow all other attributes.
+ if ( $a_has_ns !== $b_has_ns ) {
+ return $a_has_ns ? 1 : -1;
+ }
+
+ $a_has_sp = str_contains( $a, ' ' );
+ $b_has_sp = str_contains( $b, ' ' );
+
+ // Attributes with a namespace ' ' should come after those without.
+ if ( $a_has_sp !== $b_has_sp ) {
+ return $a_has_sp ? 1 : -1;
+ }
+
+ return $a <=> $b;
+ }
+ );
+
+ foreach ( $sorted_attributes as $attribute_name => $display_name ) {
+ $val = $processor->get_attribute( $attribute_name );
+ /*
+ * Attributes with no value are `true` with the HTML API,
+ * we use the empty string value in the tree structure.
+ */
+ if ( true === $val ) {
+ $val = '';
+ } elseif ( 'class' === $attribute_name ) {
+ $class_names = iterator_to_array( $processor->class_list() );
+ sort( $class_names, SORT_STRING );
+ $val = implode( ' ', $class_names );
+ } elseif ( 'style' === $attribute_name ) {
+ $normalized_style = '';
+ foreach ( explode( ';', $val ) as $style ) {
+ if ( empty( trim( $style ) ) ) {
+ continue;
+ }
+ list( $style_key, $style_val ) = explode( ':', $style );
+
+ $style_key = trim( $style_key );
+ $style_val = trim( $style_val );
+
+ $normalized_style .= "{$style_key}:{$style_val};";
+ }
+ $val = $normalized_style;
+ }
+ $output .= str_repeat( $tree_indent, $tag_indent + 1 ) . "{$display_name}=\"{$val}\"\n";
+ }
+ }
+
+ // Self-contained tags contain their inner contents as modifiable text.
+ $modifiable_text = $processor->get_modifiable_text();
+ if ( '' !== $modifiable_text ) {
+ $output .= str_repeat( $tree_indent, $tag_indent + 1 ) . "\"{$modifiable_text}\"\n";
+ }
+
+ if ( 'html' === $namespace && 'TEMPLATE' === $token_name ) {
+ $output .= str_repeat( $tree_indent, $indent_level ) . "content\n";
+ ++$indent_level;
+ }
+
+ break;
+
+ case '#cdata-section':
+ case '#text':
+ $text_content = $processor->get_modifiable_text();
+ if ( '' === trim( $text_content, " \f\t\r\n" ) ) {
+ break;
+ }
+ $was_text = true;
+ if ( '' === $text_node ) {
+ $text_node .= str_repeat( $tree_indent, $indent_level ) . '"';
+ }
+ $text_node .= $text_content;
+ break;
+
+ case '#funky-comment':
+ // Comments must be "<" then "!-- " then the data then " -->".
+ $output .= str_repeat( $tree_indent, $indent_level ) . "<!-- {$processor->get_modifiable_text()} -->\n";
+ break;
+
+ case '#comment':
+ // Comments must be "<" then "!--" then the data then "-->".
+ $comment = "<!--{$processor->get_full_comment_text()}-->";
+
+ // Maybe the comment is a block delimiter.
+ $parser = new WP_Block_Parser();
+ $parser->document = $comment;
+ $parser->offset = 0;
+ list( $delimiter_type, $block_name, $block_attrs, $start_offset, $token_length ) = $parser->next_token();
+
+ switch ( $delimiter_type ) {
+ case 'block-opener':
+ case 'void-block':
+ $output .= str_repeat( $tree_indent, $indent_level ) . "BLOCK[\"{$block_name}\"]\n";
+
+ if ( 'block-opener' === $delimiter_type ) {
+ $block_context[] = $block_name;
+ ++$indent_level;
+ }
+
+ // If they're no attributes, we're done here.
+ if ( empty( $block_attrs ) ) {
+ break;
+ }
+
+ // Normalize attribute order.
+ ksort( $block_attrs, SORT_STRING );
+
+ if ( isset( $block_attrs['className'] ) ) {
+ // Normalize class name order (and de-duplicate), as we need to be tolerant of different orders.
+ // (Style attributes don't need this treatment, as they are parsed into a nested array.)
+ $block_class_processor = new WP_HTML_Tag_Processor( '<div>' );
+ $block_class_processor->next_token();
+ $block_class_processor->set_attribute( 'class', $block_attrs['className'] );
+ $class_names = iterator_to_array( $block_class_processor->class_list() );
+ sort( $class_names, SORT_STRING );
+ $block_attrs['className'] = implode( ' ', $class_names );
+ }
+
+ $block_attrs = json_encode( $block_attrs, JSON_PRETTY_PRINT );
+ // Fix indentation by "halving" it (2 spaces instead of 4).
+ // Additionally, we need to indent each line by the current indentation level.
+ $block_attrs = preg_replace( '/^( +)\1/m', str_repeat( $tree_indent, $indent_level ) . '$1', $block_attrs );
+ // Finally, indent the first line, and the last line (with the closing curly brace).
+ $output .= str_repeat( $tree_indent, $indent_level ) . substr( $block_attrs, 0, -1 ) . str_repeat( $tree_indent, $indent_level ) . "}\n";
+ break;
+ case 'block-closer':
+ // Is this a closer for the currently open block?
+ if ( ! empty( $block_context ) && end( $block_context ) === $block_name ) {
+ // If it's a closer, we don't add it to the output.
+ // Instead, we decrease indentation and remove the block from block context stack.
+ --$indent_level;
+ array_pop( $block_context );
+ }
+ break;
+ default: // Not a block delimiter.
+ $output .= str_repeat( $tree_indent, $indent_level ) . $comment . "\n";
+ break;
+ }
+ break;
+ default:
+ // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
+ $serialized_token_type = var_export( $processor->get_token_type(), true );
+ throw new Error( "Unhandled token type for tree construction: {$serialized_token_type}" );
+ }
+ }
+
+ if ( null !== $processor->get_unsupported_exception() ) {
+ throw $processor->get_unsupported_exception();
+ }
+
+ if ( null !== $processor->get_last_error() ) {
+ throw new Error( "Parser error: {$processor->get_last_error()}" );
+ }
+
+ if ( $processor->paused_at_incomplete_token() ) {
+ throw new Error( 'Paused at incomplete token.' );
+ }
+
+ if ( '' !== $text_node ) {
+ $output .= "{$text_node}\"\n";
+ }
+
+ return $output;
+}
diff --git a/tests/phpunit/includes/factory/class-wp-unittest-factory-for-attachment.php b/tests/phpunit/includes/factory/class-wp-unittest-factory-for-attachment.php
index 262c6c4640..2c1872795f 100644
--- a/tests/phpunit/includes/factory/class-wp-unittest-factory-for-attachment.php
+++ b/tests/phpunit/includes/factory/class-wp-unittest-factory-for-attachment.php
@@ -50,12 +50,13 @@ class WP_UnitTest_Factory_For_Attachment extends WP_UnitTest_Factory_For_Post {
}
/**
- * Saves an attachment.
+ * Saves a file as an attachment.
*
* @since 4.4.0
* @since 6.2.0 Returns a WP_Error object on failure.
*
- * @param string $file The file name to create attachment object for.
+ * @param string $file Full path to the file to create an attachment object for.
+ * The name of the file will be used as the attachment name.
* @param int $parent_post_id ID of the post to attach the file to.
*
* @return int|WP_Error The attachment ID on success, WP_Error object on failure.
diff --git a/tests/phpunit/includes/object-cache.php b/tests/phpunit/includes/object-cache.php
index ef03546892..daffcabac5 100644
--- a/tests/phpunit/includes/object-cache.php
+++ b/tests/phpunit/includes/object-cache.php
@@ -160,8 +160,8 @@ function wp_cache_cas( $cas_token, $key, $value, $group = '', $expiration = 0 )
*
* @link https://www.php.net/manual/en/memcached.casbykey.php
*
- * @param string $server_key The key identifying the server to store the value on.
* @param float $cas_token Unique value associated with the existing item. Generated by memcached.
+ * @param string $server_key The key identifying the server to store the value on.
* @param string $key The key under which to store the value.
* @param mixed $value The value to store.
* @param string $group The group value appended to the $key.
@@ -1238,8 +1238,8 @@ class WP_Object_Cache {
*
* @link https://www.php.net/manual/en/memcached.casbykey.php
*
- * @param string $server_key The key identifying the server to store the value on.
* @param float $cas_token Unique value associated with the existing item. Generated by memcached.
+ * @param string $server_key The key identifying the server to store the value on.
* @param string $key The key under which to store the value.
* @param mixed $value The value to store.
* @param string $group The group value appended to the $key.
@@ -1929,12 +1929,12 @@ class WP_Object_Cache {
*
* @link https://www.php.net/manual/en/memcached.replace.php
*
- * @param string $server_key The key identifying the server to store the value on.
* @param string $key The key under which to store the value.
* @param mixed $value The value to store.
* @param string $group The group value appended to the $key.
- * @param bool $by_key True to store in internal cache by key; false to not store by key.
* @param int $expiration The expiration time, defaults to 0.
+ * @param string $server_key The key identifying the server to store the value on.
+ * @param bool $by_key True to store in internal cache by key; false to not store by key.
* @return bool True on success, false on failure.
*/
public function replace( $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) {
diff --git a/tests/phpunit/tests/auth.php b/tests/phpunit/tests/auth.php
index 405a8526d0..a490842ebd 100644
--- a/tests/phpunit/tests/auth.php
+++ b/tests/phpunit/tests/auth.php
@@ -2089,9 +2089,6 @@ class Tests_Auth extends WP_UnitTestCase {
}
private static function get_default_bcrypt_cost(): int {
- $hash = password_hash( 'password', PASSWORD_BCRYPT );
- $info = password_get_info( $hash );
-
- return $info['options']['cost'];
+ return 5;
}
}
diff --git a/tests/phpunit/tests/build-visual-html-tree.php b/tests/phpunit/tests/build-visual-html-tree.php
new file mode 100644
index 0000000000..42e35c5b74
--- /dev/null
+++ b/tests/phpunit/tests/build-visual-html-tree.php
@@ -0,0 +1,144 @@
+<?php
+
+/**
+ * Tests for build_visual_html_tree().
+ *
+ * @package WordPress
+ *
+ * @group testsuite
+ */
+class Tests_Build_Equivalent_HTML_Semantic_Tree extends WP_UnitTestCase {
+ public function data_build_equivalent_html_semantic_tree() {
+ $block_markup = <<<END
+ <!-- wp:separator {"className":"is-style-default has-custom-classname","style":{"spacing":{"margin":{"top":"50px","bottom":"50px"}}},"backgroundColor":"accent-1"} -->
+ <hr class="wp-block-separator is-style-default has-custom-classname" style="margin-top: 50px; margin-bottom: 50px" />
+ <!-- /wp:separator -->
+END;
+
+ $tree_structure = <<<END
+BLOCK["core/separator"]
+ {
+ "backgroundColor": "accent-1",
+ "className": "has-custom-classname is-style-default",
+ "style": {
+ "spacing": {
+ "margin": {
+ "top": "50px",
+ "bottom": "50px"
+ }
+ }
+ }
+ }
+ <hr>
+ class="has-custom-classname is-style-default wp-block-separator"
+ style="margin-top:50px;margin-bottom:50px;"
+
+END;
+
+ return array(
+ 'Block delimiter' => array( $block_markup, $tree_structure ),
+ );
+ }
+
+ /**
+ * @ticket 63527
+ *
+ * @covers ::build_visual_html_tree
+ *
+ * @dataProvider data_build_equivalent_html_semantic_tree
+ */
+ public function test_build_equivalent_html_semantic_tree( $markup, $expected ) {
+ $actual = build_visual_html_tree( $markup, '<body>' );
+ $this->assertSame( $expected, $actual );
+ }
+
+ public function data_build_equivalent_html_semantic_tree_with_equivalent_html() {
+ return array(
+ 'Different attribute order' => array(
+ '<img src="wp.png" alt="The WordPress logo">',
+ '<img alt="The WordPress logo" src="wp.png">',
+ ),
+ 'Different class name order' => array(
+ '<hr class="wp-block-separator is-style-default">',
+ '<hr class="is-style-default wp-block-separator">',
+ ),
+ 'Differences in style attribute whitespace and trailing semicolon' => array(
+ '<hr style="margin-top: 50px; margin-bottom: 50px;">',
+ '<hr style="margin-top:50px;margin-bottom: 50px">',
+ ),
+ 'Different block attribute order' => array(
+ '<!-- wp:separator {"className":"is-style-default","backgroundColor":"accent-1"} -->',
+ '<!-- wp:separator {"backgroundColor":"accent-1","className":"is-style-default"} -->',
+ ),
+ 'Different block class name order' => array(
+ '<!-- wp:separator {"className":"is-style-default has-custom-classname"} -->',
+ '<!-- wp:separator {"className":"has-custom-classname is-style-default"} -->',
+ ),
+ 'Different whitespace in block class name' => array(
+ '<!-- wp:separator {"className":"wp-block-separator is-style-default"} -->',
+ '<!-- wp:separator {"className":"wp-block-separator is-style-default "} -->',
+ ),
+ 'Duplicated block class names' => array(
+ '<!-- wp:separator {"className":"wp-block-separator is-style-default"} -->',
+ '<!-- wp:separator {"className":"wp-block-separator is-style-default wp-block-separator"} -->',
+ ),
+ 'Different Capitalization of tag' => array(
+ '<IMG src="wp.png" alt="The WordPress logo">',
+ '<img src="wp.png" alt="The WordPress logo">',
+ ),
+ );
+ }
+
+ /**
+ * @ticket 63527
+ *
+ * @covers ::build_visual_html_tree
+ *
+ * @dataProvider data_build_equivalent_html_semantic_tree_with_equivalent_html
+ */
+ public function test_build_equivalent_html_semantic_tree_with_equivalent_html( $expected, $actual ) {
+ $tree_expected = build_visual_html_tree( $expected, '<body>' );
+ $tree_actual = build_visual_html_tree( $actual, '<body>' );
+
+ $this->assertSame( $tree_expected, $tree_actual );
+ }
+
+ public function data_build_equivalent_html_semantic_tree_with_non_equivalent_html() {
+ return array(
+ 'Different attributes' => array(
+ '<img src="wp.png" alt="The WordPress logo">',
+ '<img alt="The WordPress logo" src="wp.png" title="WordPress">',
+ ),
+ 'Different class names' => array(
+ '<hr class="wp-block-separator is-style-default">',
+ '<hr class="is-style-default wp-block-hairline">',
+ ),
+ 'Different styles' => array(
+ '<hr style="margin-top: 50px; margin-bottom: 50px;">',
+ '<hr style="margin-top: 50px; margin-bottom: 100px">',
+ ),
+ 'Different comments' => array(
+ '<!-- abc -->',
+ '<!-- xyz -->',
+ ),
+ 'Semantically relevant whitespace' => array(
+ '<div style="color: rgb(50 139 31)">Test</div>',
+ '<div style="color:rgb(5013931)">Test</div>',
+ ),
+ );
+ }
+
+ /**
+ * @ticket 63527
+ *
+ * @covers ::build_visual_html_tree
+ *
+ * @dataProvider data_build_equivalent_html_semantic_tree_with_non_equivalent_html
+ */
+ public function test_build_equivalent_html_semantic_tree_with_non_equivalent_html( $expected, $actual ) {
+ $tree_expected = build_visual_html_tree( $expected, '<body>' );
+ $tree_actual = build_visual_html_tree( $actual, '<body>' );
+
+ $this->assertNotSame( $tree_expected, $tree_actual );
+ }
+}
diff --git a/tests/phpunit/tests/comment/commentForm.php b/tests/phpunit/tests/comment/commentForm.php
index 771cbc1b57..e3dab07e24 100644
--- a/tests/phpunit/tests/comment/commentForm.php
+++ b/tests/phpunit/tests/comment/commentForm.php
@@ -193,4 +193,38 @@ class Tests_Comment_CommentForm extends WP_UnitTestCase {
$post_hidden_field = "<input type='hidden' name='comment_post_ID' value='{$post_id}' id='comment_post_ID' />";
$this->assertStringContainsString( $post_hidden_field, $form );
}
+
+ /**
+ * Tests novalidate attribute on the comment form.
+ *
+ * @ticket 47595
+ */
+ public function test_comment_form_and_novalidate_attribute() {
+ $post_id = self::$post_id;
+
+ // By default, the novalidate is not emitted.
+ $form = get_echo( 'comment_form', array( array(), $post_id ) );
+ $p = new WP_HTML_Tag_Processor( $form );
+ $this->assertTrue( $p->next_tag( array( 'tag_name' => 'FORM' ) ), 'Expected FORM tag.' );
+ $this->assertNull( $p->get_attribute( 'novalidate' ), 'Expected FORM to not have novalidate attribute by default.' );
+
+ // Opt in to the novalidate attribute by passing an arg to comment_form().
+ $form = get_echo( 'comment_form', array( array( 'novalidate' => true ), $post_id ) );
+ $p = new WP_HTML_Tag_Processor( $form );
+ $this->assertTrue( $p->next_tag( array( 'tag_name' => 'FORM' ) ), 'Expected FORM tag.' );
+ $this->assertTrue( $p->get_attribute( 'novalidate' ), 'Expected FORM to have the novalidate attribute.' );
+
+ // Opt in to the novalidate attribute via the comment_form_defaults filter.
+ add_filter(
+ 'comment_form_defaults',
+ static function ( array $defaults ): array {
+ $defaults['novalidate'] = true;
+ return $defaults;
+ }
+ );
+ $form = get_echo( 'comment_form', array( array(), $post_id ) );
+ $p = new WP_HTML_Tag_Processor( $form );
+ $this->assertTrue( $p->next_tag( array( 'tag_name' => 'FORM' ) ), 'Expected FORM tag.' );
+ $this->assertTrue( $p->get_attribute( 'novalidate' ), 'Expected FORM to have novalidate attribute.' );
+ }
}
diff --git a/tests/phpunit/tests/customize/widgets.php b/tests/phpunit/tests/customize/widgets.php
index bf298e1fff..5b64f85ce3 100644
--- a/tests/phpunit/tests/customize/widgets.php
+++ b/tests/phpunit/tests/customize/widgets.php
@@ -872,4 +872,42 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
$this->manager->widgets->prepreview_added_widget_instance();
$this->manager->widgets->remove_prepreview_filters();
}
+
+ /**
+ * Test that output_widget_control_templates() works without sidebars.
+ * This test verifies that the fix for accessing panel title works correctly
+ * when no sidebars are registered or the widgets panel doesn't exist.
+ *
+ * @ticket 63151
+ *
+ * @covers WP_Customize_Widgets::output_widget_control_templates
+ */
+ public function test_output_widget_control_templates_without_sidebars() {
+ global $wp_registered_sidebars;
+
+ $original_sidebars = $wp_registered_sidebars;
+ $wp_registered_sidebars = array();
+ $manager = new WP_Customize_Manager();
+ $widgets = new WP_Customize_Widgets( $manager );
+
+ if ( $manager->get_panel( 'widgets' ) ) {
+ $manager->remove_panel( 'widgets' );
+ }
+
+ ob_start();
+
+ $widgets->output_widget_control_templates();
+
+ $output = ob_get_clean();
+ $wp_registered_sidebars = $original_sidebars;
+
+ $this->assertStringNotContainsString( 'Warning', $output, 'Failed asserting that the output does not contain "Warning".' );
+ $this->assertStringNotContainsString( 'Notice', $output, 'Failed asserting that the output does not contain "Notice".' );
+ $this->assertStringNotContainsString( 'Error', $output, 'Failed asserting that the output does not contain "Error".' );
+
+ // Check that the output contains expected widget controls HTML.
+ $this->assertStringContainsString( 'id="widgets-left"', $output, 'Failed asserting that the output contains "id=widgets-left".' );
+ $this->assertStringContainsString( 'id="available-widgets"', $output, 'Failed asserting that the output contains "id=available-widgets".' );
+ $this->assertStringNotContainsString( 'id="accordion-panel-widgets"', $output, 'Failed asserting that the output does not contain "id=accordion-panel-widgets".' );
+ }
}
diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php
index 89bfb4ef92..d00c77b5a1 100644
--- a/tests/phpunit/tests/dependencies/scripts.php
+++ b/tests/phpunit/tests/dependencies/scripts.php
@@ -79,7 +79,7 @@ JS;
$expected .= "<script type='text/javascript' src='http://example.com?ver=1.2' id='empty-deps-version-js'></script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='empty-deps-null-version-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
// No scripts left to print.
$this->assertSame( '', get_echo( 'wp_print_scripts' ) );
@@ -125,7 +125,7 @@ JS;
'id' => 'ms-isa-1-js-after',
)
);
- $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "after" position, that are attached to a deferred main script, are failing to print/execute.' );
+ $this->assertEqualHTML( $expected, $output, '<body>', 'Inline scripts in the "after" position, that are attached to a deferred main script, are failing to print/execute.' );
}
/**
@@ -154,7 +154,7 @@ JS;
)
);
- $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "after" position, that are attached to a blocking main script, are failing to print/execute.' );
+ $this->assertEqualHTML( $expected, $output, '<body>', 'Inline scripts in the "after" position, that are attached to a blocking main script, are failing to print/execute.' );
}
/**
@@ -187,9 +187,9 @@ JS;
'id' => 'ds-i1-1-js-before',
)
);
- $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-1.js' id='ds-i1-1-js' $strategy data-wp-strategy='{$strategy}'></script>\n";
- $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-2.js' id='ds-i1-2-js' $strategy data-wp-strategy='{$strategy}'></script>\n";
- $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-3.js' id='ds-i1-3-js' $strategy data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-1.js' id='ds-i1-1-js' {$strategy}='{$strategy}' data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-2.js' id='ds-i1-2-js' {$strategy}='{$strategy}' data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-3.js' id='ds-i1-3-js' {$strategy}='{$strategy}' data-wp-strategy='{$strategy}'></script>\n";
$expected .= wp_get_inline_script_tag(
'console.log("before last");',
array(
@@ -197,9 +197,9 @@ JS;
'type' => 'text/javascript',
)
);
- $expected .= "<script type='text/javascript' src='http://example.org/ms-i1-1.js' id='ms-i1-1-js' {$strategy} data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= "<script type='text/javascript' src='http://example.org/ms-i1-1.js' id='ms-i1-1-js' {$strategy}='{$strategy}' data-wp-strategy='{$strategy}'></script>\n";
- $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "before" position, that are attached to a deferred main script, are failing to print/execute.' );
+ $this->assertEqualHTML( $expected, $output, '<body>', 'Inline scripts in the "before" position, that are attached to a deferred main script, are failing to print/execute.' );
}
/**
@@ -216,8 +216,8 @@ JS;
// No dependents, No dependencies then async.
wp_enqueue_script( 'main-script-a1', '/main-script-a1.js', array(), null, array( 'strategy' => 'async' ) );
$output = get_echo( 'wp_print_scripts' );
- $expected = "<script type='text/javascript' src='/main-script-a1.js' id='main-script-a1-js' async data-wp-strategy='async'></script>\n";
- $this->assertEqualMarkup( $expected, $output, 'Scripts enqueued with an async loading strategy are failing to have the async attribute applied to the script handle when being printed.' );
+ $expected = "<script type='text/javascript' src='/main-script-a1.js' id='main-script-a1-js' async='async' data-wp-strategy='async'></script>\n";
+ $this->assertEqualHTML( $expected, $output, '<body>', 'Scripts enqueued with an async loading strategy are failing to have the async attribute applied to the script handle when being printed.' );
}
/**
@@ -238,9 +238,9 @@ JS;
wp_enqueue_script( 'dependency-script-a2', '/dependency-script-a2.js', array(), null );
wp_enqueue_script( 'main-script-a2', '/main-script-a2.js', array( 'dependency-script-a2' ), null, compact( 'strategy' ) );
$output = get_echo( 'wp_print_scripts' );
- $expected = "<script id='dependency-script-a2-js' src='/dependency-script-a2.js'></script>\n";
- $expected .= "<script type='text/javascript' src='/main-script-a2.js' id='main-script-a2-js' {$strategy} data-wp-strategy='{$strategy}'></script>";
- $this->assertEqualMarkup( $expected, $output, 'Dependents of a blocking dependency are free to have any strategy.' );
+ $expected = "<script id='dependency-script-a2-js' src='/dependency-script-a2.js' type='text/javascript'></script>\n";
+ $expected .= "<script type='text/javascript' src='/main-script-a2.js' id='main-script-a2-js' {$strategy}='{$strategy}' data-wp-strategy='{$strategy}'></script>";
+ $this->assertEqualHTML( $expected, $output, '<body>', 'Dependents of a blocking dependency are free to have any strategy.' );
}
/**
@@ -264,7 +264,7 @@ JS;
<script type='text/javascript' src='/main-script-a3.js' id='main-script-a3-js' data-wp-strategy='{$strategy}'></script>
<script id="dependent-script-a3-js" src="/dependent-script-a3.js" type="text/javascript"></script>
JS;
- $this->assertEqualMarkup( $expected, $output, 'Blocking dependents must force delayed dependencies to become blocking.' );
+ $this->assertEqualHTML( $expected, $output, '<body>', 'Blocking dependents must force delayed dependencies to become blocking.' );
}
/**
@@ -511,18 +511,26 @@ JS;
},
'expected_markup' => <<<HTML
<script id="blocking-not-async-without-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-not-async-without-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-not-async-without-dependency:%20script' id='blocking-not-async-without-dependency-js'></script>
<script id="blocking-not-async-without-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-not-async-without-dependency: after inline" )
+/* ]]> */
</script>
<script id="async-with-blocking-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-with-blocking-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-with-blocking-dependency:%20script' id='async-with-blocking-dependency-js' data-wp-strategy='async'></script>
<script id="async-with-blocking-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-with-blocking-dependency: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -548,25 +556,37 @@ HTML
},
'expected_markup' => <<<HTML
<script id="async-no-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-no-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-no-dependency:%20script' id='async-no-dependency-js' data-wp-strategy='async'></script>
<script id="async-no-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-no-dependency: after inline" )
+/* ]]> */
</script>
<script id="async-one-async-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-one-async-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-one-async-dependency:%20script' id='async-one-async-dependency-js' data-wp-strategy='async'></script>
<script id="async-one-async-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-one-async-dependency: after inline" )
+/* ]]> */
</script>
<script id="async-two-async-dependencies-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-two-async-dependencies: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-two-async-dependencies:%20script' id='async-two-async-dependencies-js' data-wp-strategy='async'></script>
<script id="async-two-async-dependencies-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-two-async-dependencies: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -584,18 +604,26 @@ HTML
},
'expected_markup' => <<<HTML
<script id="async-with-blocking-dependent-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-with-blocking-dependent: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-with-blocking-dependent:%20script' id='async-with-blocking-dependent-js' data-wp-strategy='async'></script>
<script id="async-with-blocking-dependent-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-with-blocking-dependent: after inline" )
+/* ]]> */
</script>
<script id="blocking-dependent-of-async-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-dependent-of-async: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-dependent-of-async:%20script' id='blocking-dependent-of-async-js'></script>
<script id="blocking-dependent-of-async-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-dependent-of-async: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -613,18 +641,26 @@ HTML
},
'expected_markup' => <<<HTML
<script id="async-with-defer-dependent-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-with-defer-dependent: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-with-defer-dependent:%20script' id='async-with-defer-dependent-js' data-wp-strategy='async'></script>
<script id="async-with-defer-dependent-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-with-defer-dependent: after inline" )
+/* ]]> */
</script>
<script id="defer-dependent-of-async-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-async: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-async:%20script' id='defer-dependent-of-async-js' data-wp-strategy='defer'></script>
<script id="defer-dependent-of-async-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-async: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -645,17 +681,25 @@ HTML
},
'expected_markup' => <<<HTML
<script id="blocking-bundle-of-none-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-bundle-of-none: before inline" )
+/* ]]> */
</script>
<script id="blocking-bundle-of-none-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-bundle-of-none: after inline" )
+/* ]]> */
</script>
<script id="defer-dependent-of-blocking-bundle-of-none-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-none: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-none:%20script' id='defer-dependent-of-blocking-bundle-of-none-js' data-wp-strategy='defer'></script>
<script id="defer-dependent-of-blocking-bundle-of-none-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-none: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -679,25 +723,37 @@ HTML
},
'expected_markup' => <<<HTML
<script id="blocking-bundle-member-one-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-bundle-member-one: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-bundle-member-one:%20script' id='blocking-bundle-member-one-js'></script>
<script id="blocking-bundle-member-one-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-bundle-member-one: after inline" )
+/* ]]> */
</script>
<script id="blocking-bundle-member-two-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-bundle-member-two: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-bundle-member-two:%20script' id='blocking-bundle-member-two-js'></script>
<script id="blocking-bundle-member-two-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-bundle-member-two: after inline" )
+/* ]]> */
</script>
<script id="defer-dependent-of-blocking-bundle-of-two-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-two: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-two:%20script' id='defer-dependent-of-blocking-bundle-of-two-js' data-wp-strategy='defer'></script>
<script id="defer-dependent-of-blocking-bundle-of-two-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-two: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -720,17 +776,25 @@ HTML
},
'expected_markup' => <<<HTML
<script id="defer-bundle-of-none-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-bundle-of-none: before inline" )
+/* ]]> */
</script>
<script id="defer-bundle-of-none-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-bundle-of-none: after inline" )
+/* ]]> */
</script>
<script id="defer-dependent-of-defer-bundle-of-none-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-defer-bundle-of-none: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-bundle-of-none:%20script' id='defer-dependent-of-defer-bundle-of-none-js' data-wp-strategy='defer'></script>
<script id="defer-dependent-of-defer-bundle-of-none-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-defer-bundle-of-none: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -751,25 +815,37 @@ HTML
},
'expected_markup' => <<<HTML
<script id="blocking-dependency-with-defer-following-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-dependency-with-defer-following-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-following-dependency:%20script' id='blocking-dependency-with-defer-following-dependency-js'></script>
<script id="blocking-dependency-with-defer-following-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-dependency-with-defer-following-dependency: after inline" )
+/* ]]> */
</script>
<script id="defer-dependency-with-blocking-preceding-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependency-with-blocking-preceding-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-preceding-dependency:%20script' id='defer-dependency-with-blocking-preceding-dependency-js' data-wp-strategy='defer'></script>
<script id="defer-dependency-with-blocking-preceding-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependency-with-blocking-preceding-dependency: after inline" )
+/* ]]> */
</script>
<script id="defer-dependent-of-blocking-and-defer-dependencies-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-blocking-and-defer-dependencies: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-and-defer-dependencies:%20script' id='defer-dependent-of-blocking-and-defer-dependencies-js' data-wp-strategy='defer'></script>
<script id="defer-dependent-of-blocking-and-defer-dependencies-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-blocking-and-defer-dependencies: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -790,25 +866,37 @@ HTML
},
'expected_markup' => <<<HTML
<script id="defer-dependency-with-blocking-following-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependency-with-blocking-following-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-following-dependency:%20script' id='defer-dependency-with-blocking-following-dependency-js' data-wp-strategy='defer'></script>
<script id="defer-dependency-with-blocking-following-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependency-with-blocking-following-dependency: after inline" )
+/* ]]> */
</script>
<script id="blocking-dependency-with-defer-preceding-dependency-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-dependency-with-defer-preceding-dependency: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-preceding-dependency:%20script' id='blocking-dependency-with-defer-preceding-dependency-js'></script>
<script id="blocking-dependency-with-defer-preceding-dependency-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "blocking-dependency-with-defer-preceding-dependency: after inline" )
+/* ]]> */
</script>
<script id="defer-dependent-of-defer-and-blocking-dependencies-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-defer-and-blocking-dependencies: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-and-blocking-dependencies:%20script' id='defer-dependent-of-defer-and-blocking-dependencies-js' data-wp-strategy='defer'></script>
<script id="defer-dependent-of-defer-and-blocking-dependencies-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-defer-and-blocking-dependencies: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -826,18 +914,26 @@ HTML
},
'expected_markup' => <<<HTML
<script id="defer-with-async-dependent-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-with-async-dependent: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-with-async-dependent:%20script' id='defer-with-async-dependent-js' data-wp-strategy='defer'></script>
<script id="defer-with-async-dependent-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-with-async-dependent: after inline" )
+/* ]]> */
</script>
<script id="async-dependent-of-defer-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-dependent-of-defer: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-dependent-of-defer:%20script' id='async-dependent-of-defer-js' data-wp-strategy='async'></script>
<script id="async-dependent-of-defer-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "async-dependent-of-defer: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -851,9 +947,11 @@ HTML
},
'expected_markup' => <<<HTML
<script id="defer-with-before-inline-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-with-before-inline: before inline" )
+/* ]]> */
</script>
-<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-with-before-inline:%20script' id='defer-with-before-inline-js' defer data-wp-strategy='defer'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-with-before-inline:%20script' id='defer-with-before-inline-js' defer='defer' data-wp-strategy='defer'></script>
HTML
,
),
@@ -867,7 +965,9 @@ HTML
'expected_markup' => <<<HTML
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-with-after-inline:%20script' id='defer-with-after-inline-js' data-wp-strategy='defer'></script>
<script id="defer-with-after-inline-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-with-after-inline: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -883,9 +983,9 @@ HTML
wp_enqueue_script( 'theme-functions', 'https://example.com/theme-functions.js', array( 'jquery' ), null, array( 'strategy' => 'defer' ) );
},
'expected_markup' => <<<HTML
-<script type='text/javascript' src='http://$wp_tests_domain/wp-includes/js/jquery/jquery.js' id='jquery-core-js' defer data-wp-strategy='defer'></script>
-<script type='text/javascript' src='http://$wp_tests_domain/wp-includes/js/jquery/jquery-migrate.js' id='jquery-migrate-js' defer data-wp-strategy='defer'></script>
-<script type='text/javascript' src='https://example.com/theme-functions.js' id='theme-functions-js' defer data-wp-strategy='defer'></script>
+<script type='text/javascript' src='http://$wp_tests_domain/wp-includes/js/jquery/jquery.js' id='jquery-core-js' defer='defer' data-wp-strategy='defer'></script>
+<script type='text/javascript' src='http://$wp_tests_domain/wp-includes/js/jquery/jquery-migrate.js' id='jquery-migrate-js' defer='defer' data-wp-strategy='defer'></script>
+<script type='text/javascript' src='https://example.com/theme-functions.js' id='theme-functions-js' defer='defer' data-wp-strategy='defer'></script>
HTML
,
),
@@ -912,11 +1012,15 @@ HTML
<script type='text/javascript' src='https://example.com/external.js?script_event_log=inner-bundle-member-two:%20script' id='inner-bundle-member-two-js' data-wp-strategy='defer'></script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=outer-bundle-leaf-member:%20script' id='outer-bundle-leaf-member-js'></script>
<script id="defer-dependent-of-nested-aliases-js-before" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-nested-aliases: before inline" )
+/* ]]> */
</script>
<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-nested-aliases:%20script' id='defer-dependent-of-nested-aliases-js' data-wp-strategy='defer'></script>
<script id="defer-dependent-of-nested-aliases-js-after" type="text/javascript">
+/* <![CDATA[ */
scriptEventLog.push( "defer-dependent-of-nested-aliases: after inline" )
+/* ]]> */
</script>
HTML
,
@@ -935,9 +1039,9 @@ HTML
$this->enqueue_test_script( 'defer-dependent-of-async-aliases', 'defer', array( $alias_handle ) );
},
'expected_markup' => <<<HTML
-<script type='text/javascript' src='https://example.com/external.js?script_event_log=async1:%20script' id='async1-js' defer data-wp-strategy='async'></script>
-<script type='text/javascript' src='https://example.com/external.js?script_event_log=async2:%20script' id='async2-js' defer data-wp-strategy='async'></script>
-<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-async-aliases:%20script' id='defer-dependent-of-async-aliases-js' defer data-wp-strategy='defer'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async1:%20script' id='async1-js' defer='defer' data-wp-strategy='async'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async2:%20script' id='async2-js' defer='defer' data-wp-strategy='async'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-async-aliases:%20script' id='defer-dependent-of-async-aliases-js' defer='defer' data-wp-strategy='defer'></script>
HTML
,
),
@@ -960,7 +1064,7 @@ HTML
public function test_various_strategy_dependency_chains( $set_up, $expected_markup ) {
$set_up();
$actual_markup = get_echo( 'wp_print_scripts' );
- $this->assertEqualMarkup( trim( $expected_markup ), trim( $actual_markup ), "Actual markup:\n{$actual_markup}" );
+ $this->assertEqualHTML( trim( $expected_markup ), trim( $actual_markup ), '<body>', "Actual markup:\n{$actual_markup}" );
}
/**
@@ -1036,12 +1140,12 @@ HTML
wp_enqueue_script( 'dependent-script-d4-2', '/dependent-script-d4-2.js', array( 'dependent-script-d4-1' ), null, array( 'strategy' => 'async' ) );
wp_enqueue_script( 'dependent-script-d4-3', '/dependent-script-d4-3.js', array( 'dependent-script-d4-2' ), null, array( 'strategy' => 'defer' ) );
$output = get_echo( 'wp_print_scripts' );
- $expected = "<script type='text/javascript' src='/main-script-d4.js' id='main-script-d4-js' defer data-wp-strategy='defer'></script>\n";
- $expected .= "<script type='text/javascript' src='/dependent-script-d4-1.js' id='dependent-script-d4-1-js' defer data-wp-strategy='defer'></script>\n";
- $expected .= "<script type='text/javascript' src='/dependent-script-d4-2.js' id='dependent-script-d4-2-js' defer data-wp-strategy='async'></script>\n";
- $expected .= "<script type='text/javascript' src='/dependent-script-d4-3.js' id='dependent-script-d4-3-js' defer data-wp-strategy='defer'></script>\n";
+ $expected = "<script type='text/javascript' src='/main-script-d4.js' id='main-script-d4-js' defer='defer' data-wp-strategy='defer'></script>\n";
+ $expected .= "<script type='text/javascript' src='/dependent-script-d4-1.js' id='dependent-script-d4-1-js' defer='defer' data-wp-strategy='defer'></script>\n";
+ $expected .= "<script type='text/javascript' src='/dependent-script-d4-2.js' id='dependent-script-d4-2-js' defer='defer' data-wp-strategy='async'></script>\n";
+ $expected .= "<script type='text/javascript' src='/dependent-script-d4-3.js' id='dependent-script-d4-3-js' defer='defer' data-wp-strategy='defer'></script>\n";
- $this->assertEqualMarkup( $expected, $output, 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' );
+ $this->assertEqualHTML( $expected, $output, '<body>', 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' );
}
/**
@@ -1113,7 +1217,7 @@ HTML
$expected_header .= "<script type='text/javascript' src='/enqueue-header-old.js' id='enqueue-header-old-js'></script>\n";
$expected_header .= "<script type='text/javascript' src='/enqueue-header-new.js' id='enqueue-header-new-js'></script>\n";
- $this->assertEqualMarkup( $expected_header, $actual_header, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
+ $this->assertEqualHTML( $expected_header, $actual_header, '<body>', 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
$this->assertEmpty( $actual_footer, 'Expected footer to be empty since all scripts were for head.' );
}
@@ -1141,7 +1245,7 @@ HTML
$expected_footer .= "<script type='text/javascript' src='/enqueue-footer-new.js' id='enqueue-footer-new-js'></script>\n";
$this->assertEmpty( $actual_header, 'Expected header to be empty since all scripts targeted footer.' );
- $this->assertEqualMarkup( $expected_footer, $actual_footer, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
+ $this->assertEqualHTML( $expected_footer, $actual_footer, '<body>', 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
}
/**
@@ -1260,7 +1364,7 @@ HTML
wp_register_script( 'invalid-strategy', '/defaults.js', array(), null, array( 'strategy' => 'random-strategy' ) );
wp_enqueue_script( 'invalid-strategy' );
- $this->assertEqualMarkup(
+ $this->assertEqualHTML(
"<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
get_echo( 'wp_print_scripts' )
);
@@ -1285,7 +1389,7 @@ HTML
wp_script_add_data( 'invalid-strategy', 'strategy', 'random-strategy' );
wp_enqueue_script( 'invalid-strategy' );
- $this->assertEqualMarkup(
+ $this->assertEqualHTML(
"<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
get_echo( 'wp_print_scripts' )
);
@@ -1306,7 +1410,7 @@ HTML
public function test_script_strategy_doing_it_wrong_via_enqueue() {
wp_enqueue_script( 'invalid-strategy', '/defaults.js', array(), null, array( 'strategy' => 'random-strategy' ) );
- $this->assertEqualMarkup(
+ $this->assertEqualHTML(
"<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
get_echo( 'wp_print_scripts' )
);
@@ -1342,9 +1446,9 @@ HTML
$concatenate_scripts = $old_value;
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=one-concat-dep,two-concat-dep,three-concat-dep&amp;ver={$wp_version}'></script>\n";
- $expected .= "<script type='text/javascript' src='/main-script.js' id='main-defer-script-js' defer data-wp-strategy='defer'></script>\n";
+ $expected .= "<script type='text/javascript' src='/main-script.js' id='main-defer-script-js' defer='defer' data-wp-strategy='defer'></script>\n";
- $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with a "defer" loading strategy. Deferred scripts should not be part of the script concat loading query.' );
+ $this->assertEqualHTML( $expected, $print_scripts, '<body>', 'Scripts are being incorrectly concatenated when a main script is registered with a "defer" loading strategy. Deferred scripts should not be part of the script concat loading query.' );
}
/**
@@ -1377,9 +1481,9 @@ HTML
$concatenate_scripts = $old_value;
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=one-concat-dep-1,two-concat-dep-1,three-concat-dep-1&amp;ver={$wp_version}'></script>\n";
- $expected .= "<script type='text/javascript' src='/main-script.js' id='main-async-script-1-js' async data-wp-strategy='async'></script>\n";
+ $expected .= "<script type='text/javascript' src='/main-script.js' id='main-async-script-1-js' async='async' data-wp-strategy='async'></script>\n";
- $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with an "async" loading strategy. Async scripts should not be part of the script concat loading query.' );
+ $this->assertEqualHTML( $expected, $print_scripts, '<body>', 'Scripts are being incorrectly concatenated when a main script is registered with an "async" loading strategy. Async scripts should not be part of the script concat loading query.' );
}
/**
@@ -1416,9 +1520,9 @@ HTML
$concatenate_scripts = $old_value;
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=one-concat-dep-2,two-concat-dep-2,three-concat-dep-2,four-concat-dep-2,five-concat-dep-2,six-concat-dep-2&amp;ver={$wp_version}'></script>\n";
- $expected .= "<script type='text/javascript' src='/main-script.js' id='deferred-script-2-js' defer data-wp-strategy='defer'></script>\n";
+ $expected .= "<script type='text/javascript' src='/main-script.js' id='deferred-script-2-js' defer='defer' data-wp-strategy='defer'></script>\n";
- $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered as deferred after other blocking scripts are registered. Deferred scripts should not be part of the script concat loader query string. ' );
+ $this->assertEqualHTML( $expected, $print_scripts, '<body>', 'Scripts are being incorrectly concatenated when a main script is registered as deferred after other blocking scripts are registered. Deferred scripts should not be part of the script concat loader query string. ' );
}
/**
@@ -1427,6 +1531,8 @@ HTML
public function test_wp_enqueue_script_with_html5_support_does_not_contain_type_attribute() {
global $wp_version;
+ $this->add_html5_script_theme_support();
+
$GLOBALS['wp_scripts'] = new WP_Scripts();
$GLOBALS['wp_scripts']->default_version = get_bloginfo( 'version' );
@@ -1434,7 +1540,7 @@ HTML
$expected = "<script src='http://example.com?ver={$wp_version}' id='empty-deps-no-version-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1473,7 +1579,7 @@ HTML
$expected .= "<script type='text/javascript' src='{$wp_scripts->base_url}ftp://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver={$wp_version}' id='jquery-ftp-js'></script>\n";
// Go!
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
// No scripts left to print.
$this->assertSame( '', get_echo( 'wp_print_scripts' ) );
@@ -1516,7 +1622,7 @@ HTML
$expected .= "<script type='text/javascript' src='http://example.com' id='test-only-data-js'></script>\n";
// Go!
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
// No scripts left to print.
$this->assertSame( '', get_echo( 'wp_print_scripts' ) );
@@ -1531,10 +1637,10 @@ HTML
// Enqueue and add conditional comments.
wp_enqueue_script( 'test-only-conditional', 'example.com', array(), null );
wp_script_add_data( 'test-only-conditional', 'conditional', 'gt IE 7' );
- $expected = "<!--[if gt IE 7]>\n<script type='text/javascript' src='http://example.com' id='test-only-conditional-js'></script>\n<![endif]-->\n";
+ $expected = "<!--[if gt IE 7]>\n<script type=\"text/javascript\" src=\"http://example.com\" id=\"test-only-conditional-js\"></script>\n<![endif]-->\n";
// Go!
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
// No scripts left to print.
$this->assertSame( '', get_echo( 'wp_print_scripts' ) );
@@ -1555,7 +1661,7 @@ HTML
$expected = str_replace( "'", '"', $expected );
// Go!
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
// No scripts left to print.
$this->assertSame( '', get_echo( 'wp_print_scripts' ) );
@@ -1573,10 +1679,10 @@ HTML
$expected = "<script type='text/javascript' src='http://example.com' id='test-invalid-js'></script>\n";
// Go!
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
// No scripts left to print.
- $this->assertEqualMarkup( '', get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( '', get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1602,7 +1708,7 @@ HTML
wp_enqueue_script( 'handle-three' );
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1690,8 +1796,8 @@ HTML
$expected_header .= "<script type='text/javascript' src='/child-head.js' id='child-head-js'></script>\n";
$expected_footer = "<script type='text/javascript' src='/parent.js' id='parent-js'></script>\n";
- $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' );
- $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' );
+ $this->assertEqualHTML( $expected_header, $header, '<body>', 'Expected same header markup.' );
+ $this->assertEqualHTML( $expected_footer, $footer, '<body>', 'Expected same footer markup.' );
}
/**
@@ -1711,8 +1817,8 @@ HTML
$expected_footer = "<script type='text/javascript' src='/child-footer.js' id='child-footer-js'></script>\n";
$expected_footer .= "<script type='text/javascript' src='/parent.js' id='parent-js'></script>\n";
- $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' );
- $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' );
+ $this->assertEqualHTML( $expected_header, $header, '<body>', 'Expected same header markup.' );
+ $this->assertEqualHTML( $expected_footer, $footer, '<body>', 'Expected same footer markup.' );
}
/**
@@ -1742,8 +1848,8 @@ HTML
$expected_footer .= "<script type='text/javascript' src='/child2-footer.js' id='child2-footer-js'></script>\n";
$expected_footer .= "<script type='text/javascript' src='/parent-footer.js' id='parent-footer-js'></script>\n";
- $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' );
- $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' );
+ $this->assertEqualHTML( $expected_header, $header, '<body>', 'Expected same header markup.' );
+ $this->assertEqualHTML( $expected_footer, $footer, '<body>', 'Expected same footer markup.' );
}
/**
@@ -1770,10 +1876,16 @@ HTML
wp_enqueue_script( 'test-example', 'example.com', array(), null );
wp_add_inline_script( 'test-example', 'console.log("before");', 'before' );
- $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
+ $expected = <<<HTML
+<script type='text/javascript' id='test-example-js-before'>
+/* <![CDATA[ */
+console.log("before");
+/* ]]> */
+</script>
+HTML;
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1784,9 +1896,15 @@ HTML
wp_add_inline_script( 'test-example', 'console.log("after");' );
$expected = "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected .= <<<HTML
+<script type='text/javascript' id='test-example-js-after'>
+/* <![CDATA[ */
+console.log("after");
+/* ]]> */
+</script>
+HTML;
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1797,11 +1915,11 @@ HTML
wp_add_inline_script( 'test-example', 'console.log("before");', 'before' );
wp_add_inline_script( 'test-example', 'console.log("after");' );
- $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
+ $expected = "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1812,9 +1930,9 @@ HTML
wp_enqueue_script( 'test-example' );
wp_add_inline_script( 'test-example', 'console.log("before");', 'before' );
- $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
+ $expected = "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1825,9 +1943,9 @@ HTML
wp_enqueue_script( 'test-example' );
wp_add_inline_script( 'test-example', 'console.log("after");' );
- $expected = "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected = "<script type='text/javascript' id='test-example-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1839,10 +1957,10 @@ HTML
wp_add_inline_script( 'test-example', 'console.log("before");', 'before' );
wp_add_inline_script( 'test-example', 'console.log("after");' );
- $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected = "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1855,11 +1973,11 @@ HTML
wp_add_inline_script( 'test-example', 'console.log("after");' );
wp_add_inline_script( 'test-example', 'console.log("after");' );
- $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\nconsole.log(\"before\");\n</script>\n";
+ $expected = "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\nconsole.log(\"after\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1872,11 +1990,11 @@ HTML
wp_add_inline_script( 'test-example', 'console.log("after");' );
$expected = "<script type='text/javascript' id='test-example-js-extra'>\n/* <![CDATA[ */\nvar testExample = {\"foo\":\"bar\"};\n/* ]]> */\n</script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1895,13 +2013,13 @@ HTML
wp_add_inline_script( 'one', 'console.log("before one");', 'before' );
wp_add_inline_script( 'two', 'console.log("before two");', 'before' );
- $expected = "<script type='text/javascript' id='one-js-before'>\nconsole.log(\"before one\");\n</script>\n";
+ $expected = "<script type='text/javascript' id='one-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before one\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}one.js?ver={$wp_version}' id='one-js'></script>\n";
- $expected .= "<script type='text/javascript' id='two-js-before'>\nconsole.log(\"before two\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='two-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before two\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}two.js?ver={$wp_version}' id='two-js'></script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}three.js?ver={$wp_version}' id='three-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1919,12 +2037,12 @@ HTML
wp_add_inline_script( 'one', 'console.log("before one");', 'before' );
- $expected = "<script type='text/javascript' id='one-js-before'>\nconsole.log(\"before one\");\n</script>\n";
+ $expected = "<script type='text/javascript' id='one-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before one\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}one.js?ver={$wp_version}' id='one-js'></script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}two.js?ver={$wp_version}' id='two-js'></script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}three.js?ver={$wp_version}' id='three-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1946,12 +2064,12 @@ HTML
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=one&amp;ver={$wp_version}'></script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}two.js?ver={$wp_version}' id='two-js'></script>\n";
- $expected .= "<script type='text/javascript' id='two-js-after'>\nconsole.log(\"after two\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='two-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after two\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}three.js?ver={$wp_version}' id='three-js'></script>\n";
- $expected .= "<script type='text/javascript' id='three-js-after'>\nconsole.log(\"after three\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='three-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after three\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}four.js?ver={$wp_version}' id='four-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -1969,9 +2087,9 @@ HTML
$expected_localized = str_replace( "'", '"', $expected_localized );
$expected = "<!--[if gte IE 9]>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
$expected .= "<![endif]-->\n";
$expected = str_replace( "'", '"', $expected );
@@ -1982,7 +2100,7 @@ HTML
wp_script_add_data( 'test-example', 'conditional', 'gte IE 9' );
$this->assertSame( $expected_localized, get_echo( 'wp_print_scripts' ) );
- $this->assertEqualMarkup( $expected, $wp_scripts->print_html );
+ $this->assertEqualHTML( $expected, $wp_scripts->print_html );
$this->assertTrue( $wp_scripts->do_concat );
}
@@ -1999,7 +2117,7 @@ HTML
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=jquery-core,jquery-migrate&amp;ver={$wp_version}'></script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
wp_enqueue_script( 'test-example', 'http://example.com', array( 'jquery' ), null );
wp_add_inline_script( 'test-example', 'console.log("after");' );
@@ -2007,7 +2125,7 @@ HTML
wp_print_scripts();
$print_scripts = get_echo( '_print_scripts' );
- $this->assertEqualMarkup( $expected, $print_scripts );
+ $this->assertEqualHTML( $expected, $print_scripts );
}
/**
@@ -2023,8 +2141,8 @@ HTML
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=jquery-core,jquery-migrate&amp;ver={$wp_version}'></script>\n";
$expected .= "<!--[if gte IE 9]>\n";
- $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected .= "<script type=\"text/javascript\" src=\"http://example.com\" id=\"test-example-js\"></script>\n";
+ $expected .= "<script type=\"text/javascript\" id=\"test-example-js-after\">\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
$expected .= "<![endif]-->\n";
wp_enqueue_script( 'test-example', 'http://example.com', array( 'jquery' ), null );
@@ -2034,7 +2152,7 @@ HTML
wp_print_scripts();
$print_scripts = get_echo( '_print_scripts' );
- $this->assertEqualMarkup( $expected, $print_scripts );
+ $this->assertEqualHTML( $expected, $print_scripts );
}
/**
@@ -2050,7 +2168,7 @@ HTML
$wp_scripts->do_concat = true;
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=jquery-core,jquery-migrate&amp;ver={$wp_version}'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
wp_enqueue_script( 'test-example', 'http://example.com', array( 'jquery' ), null );
@@ -2059,7 +2177,7 @@ HTML
wp_print_scripts();
$print_scripts = get_echo( '_print_scripts' );
- $this->assertEqualMarkup( $expected, $print_scripts );
+ $this->assertEqualHTML( $expected, $print_scripts );
}
/**
@@ -2075,15 +2193,17 @@ HTML
$wp_scripts->do_concat = true;
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=jquery-core,jquery-migrate,wp-dom-ready,wp-hooks&amp;ver={$wp_version}'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/dist/i18n.min.js' id='wp-i18n-js'></script>\n";
$expected .= "<script type='text/javascript' id='wp-i18n-js-after'>\n";
+ $expected .= "/* <![CDATA[ */\n";
$expected .= "wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } );\n";
+ $expected .= "/* ]]> */\n";
$expected .= "</script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/dist/a11y.min.js' id='wp-a11y-js'></script>\n";
$expected .= "<script type='text/javascript' src='http://example2.com' id='test-example2-js'></script>\n";
- $expected .= "<script type='text/javascript' id='test-example2-js-after'>\nconsole.log(\"after\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='test-example2-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after\");\n/* ]]> */\n</script>\n";
wp_enqueue_script( 'test-example', 'http://example.com', array( 'jquery' ), null );
wp_add_inline_script( 'test-example', 'console.log("before");', 'before' );
@@ -2109,7 +2229,7 @@ HTML
$print_scripts // Printed scripts.
);
- $this->assertEqualMarkup( $expected, $print_scripts );
+ $this->assertEqualHTML( $expected, $print_scripts );
}
/**
@@ -2126,7 +2246,9 @@ HTML
$expected_tail = "<script type='text/javascript' src='/customize-dependency.js' id='customize-dependency-js'></script>\n";
$expected_tail .= "<script type='text/javascript' id='customize-dependency-js-after'>\n";
+ $expected_tail .= "/* <![CDATA[ */\n";
$expected_tail .= "tryCustomizeDependency()\n";
+ $expected_tail .= "/* ]]> */\n";
$expected_tail .= "</script>\n";
$handle = 'customize-dependency';
@@ -2142,7 +2264,7 @@ HTML
$tail = substr( $print_scripts, strrpos( $print_scripts, '<script type="text/javascript" src="/customize-dependency.js" id="customize-dependency-js">' ) );
- $this->assertEqualMarkup( $expected_tail, $tail );
+ $this->assertEqualHTML( $expected_tail, $tail );
}
/**
@@ -2161,12 +2283,12 @@ HTML
wp_enqueue_script( 'four', '/wp-includes/js/script4.js' );
$expected = "<script type='text/javascript' src='/wp-includes/js/script.js?ver={$wp_version}' id='one-js'></script>\n";
- $expected .= "<script type='text/javascript' id='one-js-after'>\nconsole.log(\"after one\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='one-js-after'>\n/* <![CDATA[ */\nconsole.log(\"after one\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/script2.js?ver={$wp_version}' id='two-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/script3.js?ver={$wp_version}' id='three-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/script4.js?ver={$wp_version}' id='four-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2185,11 +2307,11 @@ HTML
wp_enqueue_script( 'four', '/wp-includes/js/script4.js' );
$expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&amp;load%5Bchunk_0%5D=one,two&amp;ver={$wp_version}'></script>\n";
- $expected .= "<script type='text/javascript' id='three-js-before'>\nconsole.log(\"before three\");\n</script>\n";
+ $expected .= "<script type='text/javascript' id='three-js-before'>\n/* <![CDATA[ */\nconsole.log(\"before three\");\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/script3.js?ver={$wp_version}' id='three-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/script4.js?ver={$wp_version}' id='four-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2206,7 +2328,7 @@ HTML
),
'delayed' => false,
'expected_data' => '/*before foo 1*/',
- 'expected_tag' => "<script id='foo-js-before' type='text/javascript'>\n/*before foo 1*/\n</script>\n",
+ 'expected_tag' => "<script id='foo-js-before' type='text/javascript'>\n/* <![CDATA[ */\n/*before foo 1*/\n/* ]]> */\n</script>\n",
),
'after-blocking' => array(
'position' => 'after',
@@ -2216,7 +2338,7 @@ HTML
),
'delayed' => false,
'expected_data' => "/*after foo 1*/\n/*after foo 2*/",
- 'expected_tag' => "<script id='foo-js-after' type='text/javascript'>\n/*after foo 1*/\n/*after foo 2*/\n</script>\n",
+ 'expected_tag' => "<script id='foo-js-after' type='text/javascript'>\n/* <![CDATA[ */\n/*after foo 1*/\n/*after foo 2*/\n/* ]]> */\n</script>\n",
),
'before-delayed' => array(
'position' => 'before',
@@ -2225,7 +2347,7 @@ HTML
),
'delayed' => true,
'expected_data' => '/*before foo 1*/',
- 'expected_tag' => "<script id='foo-js-before' type='text/javascript'>\n/*before foo 1*/\n</script>\n",
+ 'expected_tag' => "<script id='foo-js-before' type='text/javascript'>\n/* <![CDATA[ */\n/*before foo 1*/\n/* ]]> */\n</script>\n",
),
'after-delayed' => array(
'position' => 'after',
@@ -2235,7 +2357,7 @@ HTML
),
'delayed' => true,
'expected_data' => "/*after foo 1*/\n/*after foo 2*/",
- 'expected_tag' => "<script id='foo-js-after' type='text/javascript'>\n/*after foo 1*/\n/*after foo 2*/\n</script>\n",
+ 'expected_tag' => "<script id='foo-js-after' type='text/javascript'>\n/* <![CDATA[ */\n/*after foo 1*/\n/*after foo 2*/\n/* ]]> */\n</script>\n",
),
);
}
@@ -2287,13 +2409,13 @@ HTML
$this->assertSame( $expected_data, $wp_scripts->get_inline_script_data( $handle, $position ) );
$this->assertSame( $expected_data, $wp_scripts->print_inline_script( $handle, $position, false ) );
- $this->assertEqualMarkup(
+ $this->assertEqualHTML(
$expected_tag,
$wp_scripts->get_inline_script_tag( $handle, $position )
);
ob_start();
$output = $wp_scripts->print_inline_script( $handle, $position, true );
- $this->assertEqualMarkup( $expected_tag, ob_get_clean() );
+ $this->assertEqualHTML( $expected_tag, ob_get_clean() );
$this->assertEquals( $expected_data, $output );
}
@@ -2321,7 +2443,7 @@ HTML
);
$expected .= "<script type='text/javascript' src='/wp-includes/js/script.js' id='test-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2348,7 +2470,7 @@ HTML
);
$expected .= "<script type='text/javascript' src='/wp-content/plugins/my-plugin/js/script.js' id='plugin-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2375,7 +2497,7 @@ HTML
);
$expected .= "<script type='text/javascript' src='/wp-content/themes/my-theme/js/script.js' id='theme-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2402,7 +2524,7 @@ HTML
);
$expected .= "<script type='text/javascript' src='/wp-admin/js/script.js' id='script-handle-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2432,7 +2554,7 @@ HTML
$expected = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js' id='wp-i18n-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-admin/js/script.js' id='test-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2461,7 +2583,7 @@ HTML
);
$expected .= "<script type='text/javascript' src='/wp-includes/js/script.js' id='test-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2491,7 +2613,7 @@ HTML
$expected .= "<script type='text/javascript' src='/wp-includes/js/script.js' id='test-dependency-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/script2.js' id='test-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2880,7 +3002,7 @@ HTML
$expected = "<script type='text/javascript' id='test-example-js-extra'>\n/* <![CDATA[ */\nvar testExample = {$expected};\n/* ]]> */\n</script>\n";
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
- $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
+ $this->assertEqualHTML( $expected, get_echo( 'wp_print_scripts' ) );
}
/**
@@ -2945,7 +3067,7 @@ HTML
$expected .= "<script type='text/javascript' src='/plugins/wp-i18n.js' id='wp-i18n-js'></script>\n";
$expected .= "<script type='text/javascript' src='/default/common.js' id='common-js'></script>\n";
- $this->assertEqualMarkup( $expected, $print_scripts );
+ $this->assertEqualHTML( $expected, $print_scripts );
}
/**
@@ -2981,87 +3103,6 @@ HTML
}
/**
- * Parse an HTML markup fragment.
- *
- * @param string $markup Markup.
- * @return DOMDocument Document containing the normalized markup fragment.
- */
- protected function parse_markup_fragment( $markup ) {
- $dom = new DOMDocument();
- $dom->loadHTML(
- "<!DOCTYPE html><html><head><meta charset=utf8></head><body>{$markup}</body></html>"
- );
-
- /** @var DOMElement $body */
- $body = $dom->getElementsByTagName( 'body' )->item( 0 );
-
- // Trim whitespace nodes added before/after which can be added when parsing.
- foreach ( array( $body->firstChild, $body->lastChild ) as $node ) {
- if ( $node instanceof DOMText && '' === trim( $node->data ) ) {
- $body->removeChild( $node );
- }
- }
-
- // Normalize other whitespace nodes.
- $xpath = new DOMXPath( $dom );
- foreach ( $xpath->query( '//text()' ) as $node ) {
- /** @var DOMText $node */
- if ( preg_match( '/^\s+$/', $node->nodeValue ) ) {
- $node->nodeValue = ' ';
- }
- }
-
- return $dom;
- }
-
- /**
- * Assert markup is equal after normalizing script tags.
- *
- * @param string $expected Expected markup.
- * @param string $actual Actual markup.
- * @param string $message Message.
- */
- protected function assertEqualMarkup( $expected, $actual, $message = '' ) {
- $expected_dom = $this->parse_markup_fragment( $expected );
- $actual_dom = $this->parse_markup_fragment( $actual );
- foreach ( array( $expected_dom, $actual_dom ) as $dom ) {
- $xpath = new DOMXPath( $dom );
- /** @var DOMElement $script */
-
- // Normalize type attribute. When missing, it defaults to text/javascript.
- foreach ( $xpath->query( '//script[ not( @type ) ]' ) as $script ) {
- $script->setAttribute( 'type', 'text/javascript' );
- }
-
- // Normalize script contents to remove CDATA wrapper.
- foreach ( $xpath->query( '//script[ contains( text(), "<![CDATA[" ) ]' ) as $script ) {
- $script->textContent = str_replace(
- array(
- "/* <![CDATA[ */\n",
- "\n/* ]]> */",
- ),
- '',
- $script->textContent
- );
- }
-
- // Normalize XHTML-compatible boolean attributes to HTML5 ones.
- foreach ( array( 'async', 'defer' ) as $attribute ) {
- foreach ( iterator_to_array( $xpath->query( "//script[ @{$attribute} = '{$attribute}' ]" ) ) as $script ) {
- $script->removeAttribute( $attribute );
- $script->setAttributeNode( $dom->createAttribute( $attribute ) );
- }
- }
- }
-
- $this->assertEquals(
- $expected_dom->getElementsByTagName( 'body' )->item( 0 ),
- $actual_dom->getElementsByTagName( 'body' )->item( 0 ),
- $message
- );
- }
-
- /**
* Adds html5 script theme support.
*/
protected function add_html5_script_theme_support() {
@@ -3100,8 +3141,8 @@ HTML
wp_scripts()->do_footer_items();
$footer = ob_get_clean();
- $this->assertEqualMarkup( $expected_header, $header, 'Expected header script markup to match.' );
- $this->assertEqualMarkup( $expected_footer, $footer, 'Expected footer script markup to match.' );
+ $this->assertEqualHTML( $expected_header, $header, '<body>', 'Expected header script markup to match.' );
+ $this->assertEqualHTML( $expected_footer, $footer, '<body>', 'Expected footer script markup to match.' );
$this->assertEqualSets( $expected_in_footer, wp_scripts()->in_footer, 'Expected to have the same handles for in_footer.' );
$this->assertEquals( $expected_groups, wp_scripts()->groups, 'Expected groups to match.' );
}
diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php
index cb6b1f1345..a1e70c2ff1 100644
--- a/tests/phpunit/tests/media.php
+++ b/tests/phpunit/tests/media.php
@@ -999,7 +999,6 @@ VIDEO;
$content = apply_filters( 'the_content', $video );
$expected = '<div style="width: ' . $width . 'px;" class="wp-video">' .
- "<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->\n" .
'<video class="wp-video-shortcode" id="video-' . $post_id . '-1" width="' . $width . '" height="' . $h . '" preload="metadata" controls="controls">' .
'<source type="video/mp4" src="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4?_=1" />' .
'<!-- WebM/VP8 for Firefox4, Opera, and Chrome --><source type="video/webm" src="myvideo.webm" />' .
diff --git a/tests/phpunit/tests/rest-api/rest-settings-controller.php b/tests/phpunit/tests/rest-api/rest-settings-controller.php
index e8f90b53f2..2e5e978655 100644
--- a/tests/phpunit/tests/rest-api/rest-settings-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-settings-controller.php
@@ -385,14 +385,21 @@ class WP_Test_REST_Settings_Controller extends WP_Test_REST_Controller_Testcase
}
/**
- * @doesNotPerformAssertions
+ * Settings can't be created
*/
public function test_create_item() {
- // Controller does not implement create_item().
+ wp_set_current_user( self::$administrator );
+
+ $request = new WP_REST_Request( 'POST', '/wp/v2/settings' );
+ $request->set_param( 'new_setting', 'New value' );
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 400, $response->get_status() );
}
public function test_update_item() {
wp_set_current_user( self::$administrator );
+
$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
$request->set_param( 'title', 'The new title!' );
$response = rest_get_server()->dispatch( $request );
@@ -403,6 +410,27 @@ class WP_Test_REST_Settings_Controller extends WP_Test_REST_Controller_Testcase
$this->assertSame( get_option( 'blogname' ), $data['title'] );
}
+ public function test_update_nonexistent_item() {
+ wp_set_current_user( self::$administrator );
+
+ $request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
+ $request->set_param( 'i_do_no_exist', 'New value' );
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 400, $response->get_status() );
+ }
+
+ public function test_update_partially_valid_items() {
+ wp_set_current_user( self::$administrator );
+
+ $request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
+ $request->set_param( 'title', 'The new title!' );
+ $request->set_param( 'i_do_no_exist', 'New value' );
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 400, $response->get_status() );
+ }
+
public function update_setting_custom_callback( $result, $name, $value, $args ) {
if ( 'title' === $name && 'The new title!' === $value ) {
// Do not allow changing the title in this case.
diff --git a/tests/phpunit/tests/user/getTheAuthorPosts.php b/tests/phpunit/tests/user/getTheAuthorPosts.php
index 5cd87bc79b..3a0abac5de 100644
--- a/tests/phpunit/tests/user/getTheAuthorPosts.php
+++ b/tests/phpunit/tests/user/getTheAuthorPosts.php
@@ -42,7 +42,7 @@ class Tests_User_GetTheAuthorPosts extends WP_UnitTestCase {
// Test with no global post, result should be 0 because no author is found.
$this->assertSame( 0, get_the_author_posts() );
$GLOBALS['post'] = self::$post_id;
- $this->assertEquals( 1, get_the_author_posts() );
+ $this->assertSame( 1, get_the_author_posts() );
}
/**
@@ -60,7 +60,7 @@ class Tests_User_GetTheAuthorPosts extends WP_UnitTestCase {
);
$GLOBALS['post'] = $cpt_ids[0];
- $this->assertEquals( 2, get_the_author_posts() );
+ $this->assertSame( 2, get_the_author_posts() );
_unregister_post_type( 'wptests_pt' );
}
diff --git a/tools/local-env/scripts/docker.js b/tools/local-env/scripts/docker.js
index c1dc2b27e1..e39b42a812 100644
--- a/tools/local-env/scripts/docker.js
+++ b/tools/local-env/scripts/docker.js
@@ -1,21 +1,36 @@
-const dotenv = require( 'dotenv' );
+/* jshint node:true */
+
+const dotenv = require( 'dotenv' );
const dotenvExpand = require( 'dotenv-expand' );
-const { execSync } = require( 'child_process' );
+const { spawnSync } = require( 'child_process' );
const local_env_utils = require( './utils' );
dotenvExpand.expand( dotenv.config() );
const composeFiles = local_env_utils.get_compose_files();
-if (process.argv.includes('--coverage-html')) {
+if ( process.argv.includes( '--coverage-html' ) ) {
process.env.LOCAL_PHP_XDEBUG = 'true';
process.env.LOCAL_PHP_XDEBUG_MODE = 'coverage';
}
-// This try-catch prevents the superfluous Node.js debugging information from being shown if the command fails.
-try {
- // Execute any Docker compose command passed to this script.
- execSync( 'docker compose ' + composeFiles + ' ' + process.argv.slice( 2 ).join( ' ' ), { stdio: 'inherit' } );
-} catch ( error ) {
- process.exit( 1 );
+// Add --no-TTY (-T) arg after exec and run commands when STDIN is not a TTY.
+const dockerCommand = process.argv.slice( 2 );
+if ( [ 'exec', 'run' ].includes( dockerCommand[0] ) && ! process.stdin.isTTY ) {
+ dockerCommand.splice( 1, 0, '--no-TTY' );
}
+
+// Execute any Docker compose command passed to this script.
+const returns = spawnSync(
+ 'docker',
+ [
+ 'compose',
+ ...composeFiles
+ .map( ( composeFile ) => [ '-f', composeFile ] )
+ .flat(),
+ ...dockerCommand,
+ ],
+ { stdio: 'inherit' }
+);
+
+process.exit( returns.status );
diff --git a/tools/local-env/scripts/install.js b/tools/local-env/scripts/install.js
index ad75da48c4..19a0f46e08 100644
--- a/tools/local-env/scripts/install.js
+++ b/tools/local-env/scripts/install.js
@@ -1,9 +1,10 @@
+/* jshint node:true */
+
const dotenv = require( 'dotenv' );
const dotenvExpand = require( 'dotenv-expand' );
const wait_on = require( 'wait-on' );
const { execSync } = require( 'child_process' );
-const { renameSync, readFileSync, writeFileSync } = require( 'fs' );
-const { utils } = require( './utils.js' );
+const { readFileSync, writeFileSync } = require( 'fs' );
const local_env_utils = require( './utils' );
dotenvExpand.expand( dotenv.config() );
@@ -12,7 +13,10 @@ dotenvExpand.expand( dotenv.config() );
local_env_utils.determine_auth_option();
// Create wp-config.php.
-wp_cli( 'config create --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --force' );
+wp_cli( `config create --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --force --config-file="wp-config.php"` );
+
+// Since WP-CLI runs as root, the wp-config.php created above will be read-only. This needs to be writable for the sake of E2E tests.
+execSync( 'node ./tools/local-env/scripts/docker.js exec cli chmod 666 wp-config.php' );
// Add the debug settings to wp-config.php.
// Windows requires this to be done as an additional step, rather than using the --extra-php option in the previous step.
@@ -23,26 +27,35 @@ wp_cli( `config set SCRIPT_DEBUG ${process.env.LOCAL_SCRIPT_DEBUG} --raw --type=
wp_cli( `config set WP_ENVIRONMENT_TYPE ${process.env.LOCAL_WP_ENVIRONMENT_TYPE} --type=constant` );
wp_cli( `config set WP_DEVELOPMENT_MODE ${process.env.LOCAL_WP_DEVELOPMENT_MODE} --type=constant` );
-// Move wp-config.php to the base directory, so it doesn't get mixed up in the src or build directories.
-renameSync( `${process.env.LOCAL_DIR}/wp-config.php`, 'wp-config.php' );
-
// Read in wp-tests-config-sample.php, edit it to work with our config, then write it to wp-tests-config.php.
const testConfig = readFileSync( 'wp-tests-config-sample.php', 'utf8' )
.replace( 'youremptytestdbnamehere', 'wordpress_develop_tests' )
.replace( 'yourusernamehere', 'root' )
.replace( 'yourpasswordhere', 'password' )
.replace( 'localhost', 'mysql' )
- .replace( "'WP_TESTS_DOMAIN', 'example.org'", `'WP_TESTS_DOMAIN', '${process.env.LOCAL_WP_TESTS_DOMAIN}'` )
- .concat( "\ndefine( 'FS_METHOD', 'direct' );\n" );
+ .replace( `'WP_TESTS_DOMAIN', 'example.org'`, `'WP_TESTS_DOMAIN', '${process.env.LOCAL_WP_TESTS_DOMAIN}'` )
+ .concat( `\ndefine( 'FS_METHOD', 'direct' );\n` );
writeFileSync( 'wp-tests-config.php', testConfig );
// Once the site is available, install WordPress!
-wait_on( { resources: [ `tcp:localhost:${process.env.LOCAL_PORT}`] } )
+wait_on( {
+ resources: [ `tcp:localhost:${process.env.LOCAL_PORT}`],
+ timeout: 3000,
+} )
+ .catch( err => {
+ console.error( `Error: It appears the development environment has not been started. Message: ${ err.message }` );
+ console.error( `Did you forget to do 'npm run env:start'?` );
+ process.exit( 1 );
+ } )
.then( () => {
wp_cli( 'db reset --yes' );
const installCommand = process.env.LOCAL_MULTISITE === 'true' ? 'multisite-install' : 'install';
wp_cli( `core ${ installCommand } --title="WordPress Develop" --admin_user=admin --admin_password=password --admin_email=test@example.com --skip-email --url=http://localhost:${process.env.LOCAL_PORT}` );
+ } )
+ .catch( err => {
+ console.error( `Error: Unable to reset DB and install WordPress. Message: ${ err.message }` );
+ process.exit( 1 );
} );
/**
@@ -51,7 +64,5 @@ wait_on( { resources: [ `tcp:localhost:${process.env.LOCAL_PORT}`] } )
* @param {string} cmd The WP-CLI command to run.
*/
function wp_cli( cmd ) {
- const composeFiles = local_env_utils.get_compose_files();
-
- execSync( `docker compose ${composeFiles} run --quiet-pull --rm cli ${cmd} --path=/var/www/${process.env.LOCAL_DIR}`, { stdio: 'inherit' } );
+ execSync( `npm --silent run env:cli -- ${cmd} --path=/var/www/${process.env.LOCAL_DIR}`, { stdio: 'inherit' } );
}
diff --git a/tools/local-env/scripts/start.js b/tools/local-env/scripts/start.js
index 0dc8b95700..b0389b2fb0 100644
--- a/tools/local-env/scripts/start.js
+++ b/tools/local-env/scripts/start.js
@@ -1,11 +1,13 @@
+/* jshint node:true */
+
const dotenv = require( 'dotenv' );
const dotenvExpand = require( 'dotenv-expand' );
-const { execSync } = require( 'child_process' );
+const { execSync, spawnSync } = require( 'child_process' );
const local_env_utils = require( './utils' );
const { constants, copyFile } = require( 'node:fs' );
// Copy the default .env file when one is not present.
-copyFile( '.env.example', '.env', constants.COPYFILE_EXCL, (e) => {
+copyFile( '.env.example', '.env', constants.COPYFILE_EXCL, () => {
console.log( '.env file already exists. .env.example was not copied.' );
});
@@ -28,18 +30,38 @@ try {
}
// Start the local-env containers.
-const containers = ( process.env.LOCAL_PHP_MEMCACHED === 'true' )
- ? 'wordpress-develop memcached'
- : 'wordpress-develop';
-execSync( `docker compose ${composeFiles} up --quiet-pull -d ${containers}`, { stdio: 'inherit' } );
+const containers = [ 'wordpress-develop', 'cli' ];
+if ( process.env.LOCAL_PHP_MEMCACHED === 'true' ) {
+ containers.push( 'memcached' );
+}
+
+spawnSync(
+ 'docker',
+ [
+ 'compose',
+ ...composeFiles.map( ( composeFile ) => [ '-f', composeFile ] ).flat(),
+ 'up',
+ '--quiet-pull',
+ '-d',
+ ...containers,
+ ],
+ { stdio: 'inherit' }
+);
// If Docker Toolbox is being used, we need to manually forward LOCAL_PORT to the Docker VM.
if ( process.env.DOCKER_TOOLBOX_INSTALL_PATH ) {
// VBoxManage is added to the PATH on every platform except Windows.
- const vboxmanage = process.env.VBOX_MSI_INSTALL_PATH ? `${ process.env.VBOX_MSI_INSTALL_PATH }/VBoxManage` : 'VBoxManage'
+ const vboxmanage = process.env.VBOX_MSI_INSTALL_PATH ? `${ process.env.VBOX_MSI_INSTALL_PATH }/VBoxManage` : 'VBoxManage';
// Check if the port forwarding is already configured for this port.
- const vminfoBuffer = execSync( `"${ vboxmanage }" showvminfo "${ process.env.DOCKER_MACHINE_NAME }" --machinereadable` );
+ const vminfoBuffer = spawnSync(
+ vboxmanage,
+ [
+ 'showvminfo',
+ process.env.DOCKER_MACHINE_NAME,
+ '--machinereadable'
+ ]
+ ).stdout;
const vminfo = vminfoBuffer.toString().split( /[\r\n]+/ );
vminfo.forEach( ( info ) => {
@@ -53,10 +75,29 @@ if ( process.env.DOCKER_TOOLBOX_INSTALL_PATH ) {
// Delete rules that are using the port we need.
if ( rule[ 3 ] === process.env.LOCAL_PORT || rule[ 5 ] === process.env.LOCAL_PORT ) {
- execSync( `"${ vboxmanage }" controlvm "${ process.env.DOCKER_MACHINE_NAME }" natpf1 delete ${ rule[ 0 ] }`, { stdio: 'inherit' } );
+ spawnSync(
+ vboxmanage,
+ [
+ 'controlvm',
+ process.env.DOCKER_MACHINE_NAME,
+ 'natpf1',
+ 'delete',
+ rule[ 0 ]
+ ],
+ { stdio: 'inherit' }
+ );
}
} );
// Add our port forwarding rule.
- execSync( `"${ vboxmanage }" controlvm "${ process.env.DOCKER_MACHINE_NAME }" natpf1 "tcp-port${ process.env.LOCAL_PORT },tcp,127.0.0.1,${ process.env.LOCAL_PORT },,${ process.env.LOCAL_PORT }"`, { stdio: 'inherit' } );
+ spawnSync(
+ vboxmanage,
+ [
+ 'controlvm',
+ process.env.DOCKER_MACHINE_NAME,
+ 'natpf1',
+ `tcp-port${ process.env.LOCAL_PORT },tcp,127.0.0.1,${ process.env.LOCAL_PORT },,${ process.env.LOCAL_PORT }`
+ ],
+ { stdio: 'inherit' }
+ );
}
diff --git a/tools/local-env/scripts/utils.js b/tools/local-env/scripts/utils.js
index d76f3068a5..3f3e601db2 100644
--- a/tools/local-env/scripts/utils.js
+++ b/tools/local-env/scripts/utils.js
@@ -1,3 +1,5 @@
+/* jshint node:true */
+
const { existsSync } = require( 'node:fs' );
const local_env_utils = {
@@ -10,12 +12,14 @@ const local_env_utils = {
*
* When PHP 7.2 or 7.3 is used in combination with MySQL 8.4, an override file will also be returned to ensure
* that the mysql_native_password plugin authentication plugin is on and available for use.
+ *
+ * @return {string[]} Compose files.
*/
get_compose_files: function() {
- var composeFiles = '-f docker-compose.yml';
+ const composeFiles = [ 'docker-compose.yml' ];
if ( existsSync( 'docker-compose.override.yml' ) ) {
- composeFiles = composeFiles + ' -f docker-compose.override.yml';
+ composeFiles.push( 'docker-compose.override.yml' );
}
if ( process.env.LOCAL_DB_TYPE !== 'mysql' ) {
@@ -28,7 +32,7 @@ const local_env_utils = {
// PHP 7.2/7.3 in combination with MySQL 8.4 requires additional configuration to function properly.
if ( process.env.LOCAL_DB_VERSION === '8.4' ) {
- composeFiles = composeFiles + ' -f tools/local-env/old-php-mysql-84.override.yml';
+ composeFiles.push( 'tools/local-env/old-php-mysql-84.override.yml' );
}
return composeFiles;