Skip to content

Commit d51e4f4

Browse files
authored
Merge branch 'trunk' into add/context-for-scale
2 parents 5ed709a + 0fced49 commit d51e4f4

16 files changed

Lines changed: 551 additions & 30 deletions

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
},
3333
"lock": false
3434
},
35+
"autoload-dev": {
36+
"psr-4": {
37+
"WordPress\\PHPStan\\": "tests/phpstan/"
38+
}
39+
},
3540
"scripts": {
3641
"phpstan": "@php ./vendor/bin/phpstan analyse --memory-limit=2G",
3742
"compat": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcompat.xml.dist --report=summary,source",

src/wp-admin/css/common.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,6 @@ a#remove-post-thumbnail:hover,
961961

962962
#publishing-action .spinner {
963963
float: none;
964-
margin-top: 5px;
965964
}
966965

967966
#misc-publishing-actions {
@@ -2460,7 +2459,7 @@ h1.nav-tab-wrapper, /* Back-compat for pre-4.4 */
24602459
filter: alpha(opacity=70);
24612460
width: 20px;
24622461
height: 20px;
2463-
margin: 4px 10px 0;
2462+
margin: 10px 10px 0;
24642463
}
24652464

24662465
.spinner.is-active,
@@ -2480,6 +2479,7 @@ h1.nav-tab-wrapper, /* Back-compat for pre-4.4 */
24802479
}
24812480
#template .submit .spinner {
24822481
float: none;
2482+
vertical-align: top;
24832483
}
24842484

24852485
.metabox-holder .stuffbox > h3, /* Back-compat for pre-4.4 */

src/wp-admin/css/customize-controls.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,10 @@ body.trashing #publish-settings {
572572
display: block;
573573
}
574574

575+
.accordion-section-title button.accordion-trigger .spinner {
576+
margin-top: 0;
577+
}
578+
575579
@media (prefers-reduced-motion: reduce) {
576580
#customize-theme-controls .accordion-section-title,
577581
#customize-outer-theme-controls .accordion-section-title {

src/wp-admin/css/dashboard.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
/* Required min-height to make the jQuery UI Sortable drop zone work. */
6161
min-height: 0;
6262
margin: 0 8px 20px;
63-
padding: 0;
6463
}
6564

6665
#dashboard-widgets .meta-box-sortables:not(:empty) {

src/wp-admin/css/edit.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,6 @@ body.post-type-wp_navigation .inline-edit-status {
173173

174174
/* Post Screen */
175175

176-
.metabox-holder .postbox-container .meta-box-sortables {
177-
padding: 4px;
178-
}
179-
180176
/* Only highlight drop zones when dragging and only in the 2 columns layout. */
181177
.is-dragging-metaboxes .metabox-holder .postbox-container .meta-box-sortables {
182178
border-radius: 8px;

src/wp-admin/css/list-tables.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,7 @@ div.action-links,
16091609
}
16101610

16111611
.plugin-card h3 {
1612-
margin: 0 12px 12px 0;
1612+
margin: 0 12px 16px 0;
16131613
font-size: 18px;
16141614
line-height: 1.3;
16151615
}

src/wp-includes/class-wp-connector-registry.php

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
* env_var_name?: non-empty-string
4141
* },
4242
* plugin?: array{
43-
* file: non-empty-string
43+
* file: non-empty-string,
44+
* is_active?: callable(): bool
4445
* }
4546
* }
4647
*/
@@ -109,8 +110,12 @@ final class WP_Connector_Registry {
109110
* @type array $plugin {
110111
* Optional. Plugin data for install/activate UI.
111112
*
112-
* @type string $file The plugin's main file path relative to the plugins
113-
* directory (e.g. 'my-plugin/my-plugin.php' or 'hello.php').
113+
* @type string $file Optional. The plugin's main file path relative to the
114+
* plugins directory (e.g. 'my-plugin/my-plugin.php' or
115+
* 'hello.php').
116+
* @type callable $is_active Optional callback to determine whether the plugin
117+
* is active. Receives no arguments and must return bool.
118+
* Defaults to `__return_true`.
114119
* }
115120
* }
116121
* @return array|null The registered connector data on success, null on failure.
@@ -243,8 +248,30 @@ public function register( string $id, array $args ): ?array {
243248
}
244249
}
245250

246-
if ( ! empty( $args['plugin'] ) && is_array( $args['plugin'] ) && ! empty( $args['plugin']['file'] ) ) {
247-
$connector['plugin'] = array( 'file' => $args['plugin']['file'] );
251+
$connector['plugin'] = array();
252+
253+
if ( ! empty( $args['plugin'] ) && is_array( $args['plugin'] ) ) {
254+
if ( ! empty( $args['plugin']['file'] ) ) {
255+
$connector['plugin']['file'] = $args['plugin']['file'];
256+
}
257+
258+
if ( isset( $args['plugin']['is_active'] ) ) {
259+
if ( ! is_callable( $args['plugin']['is_active'] ) ) {
260+
_doing_it_wrong(
261+
__METHOD__,
262+
/* translators: %s: Connector ID. */
263+
sprintf( __( 'Connector "%s" plugin is_active must be callable.' ), esc_html( $id ) ),
264+
'7.0.0'
265+
);
266+
return null;
267+
}
268+
269+
$connector['plugin']['is_active'] = $args['plugin']['is_active'];
270+
}
271+
}
272+
273+
if ( ! isset( $connector['plugin']['is_active'] ) ) {
274+
$connector['plugin']['is_active'] = '__return_true';
248275
}
249276

250277
$this->registered_connectors[ $id ] = $connector;

src/wp-includes/connectors.php

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,17 @@ function _wp_connectors_register_default_ai_providers( WP_Connector_Registry $re
367367
}
368368
}
369369
}
370+
371+
if ( ! isset( $args['plugin']['is_active'] ) ) {
372+
$args['plugin']['is_active'] = static function () use ( $ai_registry, $id ): bool {
373+
try {
374+
return $ai_registry->hasProvider( $id );
375+
} catch ( Exception $e ) {
376+
return false;
377+
}
378+
};
379+
}
380+
370381
$registry->register( $id, $args );
371382
}
372383
}
@@ -538,10 +549,9 @@ function _wp_connectors_rest_settings_dispatch( WP_REST_Response $response, WP_R
538549
* @access private
539550
*/
540551
function _wp_register_default_connector_settings(): void {
541-
$ai_registry = AiClient::defaultRegistry();
542552
$registered_settings = get_registered_settings();
543553

544-
foreach ( wp_get_connectors() as $connector_id => $connector_data ) {
554+
foreach ( wp_get_connectors() as $connector_data ) {
545555
$auth = $connector_data['authentication'];
546556
if ( 'api_key' !== $auth['method'] || empty( $auth['setting_name'] ) ) {
547557
continue;
@@ -552,8 +562,11 @@ function _wp_register_default_connector_settings(): void {
552562
continue;
553563
}
554564

555-
// For AI providers, skip if the provider is not in the AI Client registry.
556-
if ( 'ai_provider' === $connector_data['type'] && ! $ai_registry->hasProvider( $connector_id ) ) {
565+
if ( ! isset( $connector_data['plugin']['is_active'] ) || ! is_callable( $connector_data['plugin']['is_active'] ) ) {
566+
continue;
567+
}
568+
569+
if ( ! call_user_func( $connector_data['plugin']['is_active'] ) ) {
557570
continue;
558571
}
559572

@@ -638,10 +651,6 @@ function _wp_connectors_pass_default_keys_to_ai_client(): void {
638651
function _wp_connectors_get_connector_script_module_data( array $data ): array {
639652
$registry = AiClient::defaultRegistry();
640653

641-
if ( ! function_exists( 'is_plugin_active' ) ) {
642-
require_once ABSPATH . 'wp-admin/includes/plugin.php';
643-
}
644-
645654
$connectors = array();
646655
foreach ( wp_get_connectors() as $connector_id => $connector_data ) {
647656
$auth = $connector_data['authentication'];
@@ -674,8 +683,8 @@ function _wp_connectors_get_connector_script_module_data( array $data ): array {
674683

675684
if ( ! empty( $connector_data['plugin']['file'] ) ) {
676685
$file = $connector_data['plugin']['file'];
677-
$is_installed = file_exists( wp_normalize_path( WP_PLUGIN_DIR . '/' . $file ) );
678-
$is_activated = $is_installed && is_plugin_active( $file );
686+
$is_activated = (bool) call_user_func( $connector_data['plugin']['is_active'] );
687+
$is_installed = $is_activated || file_exists( wp_normalize_path( WP_PLUGIN_DIR . '/' . $file ) );
679688

680689
$connector_out['plugin'] = array(
681690
'file' => $file,

src/wp-includes/http.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,26 @@ function ms_allowed_http_request_hosts( $is_external, $host ) {
716716
* When a specific component has been requested: null if the component
717717
* doesn't exist in the given URL; a string or - in the case of
718718
* PHP_URL_PORT - integer when it does. See parse_url()'s return values.
719+
*
720+
* @phpstan-param int<-1, 7> $component
721+
* @phpstan-return (
722+
* $component is -1
723+
* ? false|array{
724+
* scheme?: string,
725+
* host?: string,
726+
* port?: int<0, 65535>,
727+
* user?: string,
728+
* pass?: string,
729+
* path?: string,
730+
* query?: string,
731+
* fragment?: string,
732+
* }
733+
* : (
734+
* $component is 2
735+
* ? int<0, 65535>|null
736+
* : string|null
737+
* )
738+
* )
719739
*/
720740
function wp_parse_url( $url, $component = -1 ) {
721741
$to_unset = array();
@@ -763,6 +783,36 @@ function wp_parse_url( $url, $component = -1 ) {
763783
* When a specific component has been requested: null if the component
764784
* doesn't exist in the given URL; a string or - in the case of
765785
* PHP_URL_PORT - integer when it does. See parse_url()'s return values.
786+
*
787+
* @phpstan-param false|array{
788+
* scheme?: string,
789+
* host?: string,
790+
* port?: int<0, 65535>,
791+
* user?: string,
792+
* pass?: string,
793+
* path?: string,
794+
* query?: string,
795+
* fragment?: string,
796+
* } $url_parts
797+
* @phpstan-param int<-1, 7> $component
798+
* @phpstan-return (
799+
* $component is -1
800+
* ? false|array{
801+
* scheme?: string,
802+
* host?: string,
803+
* port?: int<0, 65535>,
804+
* user?: string,
805+
* pass?: string,
806+
* path?: string,
807+
* query?: string,
808+
* fragment?: string,
809+
* }
810+
* : (
811+
* $component is 2
812+
* ? int<0, 65535>|null
813+
* : string|null
814+
* )
815+
* )
766816
*/
767817
function _get_component_from_parsed_url_array( $url_parts, $component = -1 ) {
768818
if ( -1 === $component ) {
@@ -789,6 +839,9 @@ function _get_component_from_parsed_url_array( $url_parts, $component = -1 ) {
789839
*
790840
* @param int $constant PHP_URL_* constant.
791841
* @return string|false The named key or false.
842+
*
843+
* @phpstan-param int<-1, 7> $constant
844+
* @phpstan-return 'scheme'|'host'|'port'|'user'|'pass'|'path'|'query'|'fragment'|false
792845
*/
793846
function _wp_translate_php_url_constant_to_key( $constant ) {
794847
$translation = array(

src/wp-includes/l10n.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,7 @@ function load_script_module_textdomain( string $id, string $domain = 'default',
12061206
* @return string|false The JSON-encoded translated strings on success, false otherwise.
12071207
*/
12081208
function _load_script_textdomain_from_src( string $handle, string $src, string $domain, string $path, bool $is_module ) {
1209+
/** @var WP_Textdomain_Registry $wp_textdomain_registry */
12091210
global $wp_textdomain_registry;
12101211

12111212
$locale = determine_locale();
@@ -1214,7 +1215,9 @@ function _load_script_textdomain_from_src( string $handle, string $src, string $
12141215
$path = $wp_textdomain_registry->get( $domain, $locale );
12151216
}
12161217

1217-
$path = untrailingslashit( $path );
1218+
if ( $path ) {
1219+
$path = untrailingslashit( $path );
1220+
}
12181221

12191222
// If a path was given and the handle file exists simply return it.
12201223
$file_base = 'default' === $domain ? $locale : $domain . '-' . $locale;
@@ -1231,8 +1234,17 @@ function _load_script_textdomain_from_src( string $handle, string $src, string $
12311234
$relative = false;
12321235
$languages_path = WP_LANG_DIR;
12331236

1234-
$src_url = wp_parse_url( $src );
1237+
$src_url = wp_parse_url( $src );
1238+
if ( ! $src_url ) {
1239+
return load_script_translations( false, $handle, $domain );
1240+
}
1241+
$src_url['path'] ??= '';
1242+
12351243
$content_url = wp_parse_url( content_url() );
1244+
if ( ! $content_url ) {
1245+
return load_script_translations( false, $handle, $domain );
1246+
}
1247+
12361248
$plugins_url = wp_parse_url( plugins_url() );
12371249
$site_url = wp_parse_url( site_url() );
12381250
$theme_root = get_theme_root();
@@ -1304,7 +1316,7 @@ function _load_script_textdomain_from_src( string $handle, string $src, string $
13041316
$relative = apply_filters( 'load_script_textdomain_relative_path', $relative, $src, $is_module );
13051317

13061318
// If the source is not from WP.
1307-
if ( false === $relative ) {
1319+
if ( ! is_string( $relative ) ) {
13081320
return load_script_translations( false, $handle, $domain );
13091321
}
13101322

0 commit comments

Comments
 (0)