Skip to content

Commit f75ff52

Browse files
authored
Merge branch 'trunk' into fix/65014-site-health-dashicons
2 parents ed90582 + 74c99a3 commit f75ff52

16 files changed

+242
-239
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "https://develop.svn.wordpress.org/trunk"
88
},
99
"gutenberg": {
10-
"sha": "0d133bf7e7437d65d68a06551f3d613a7d8e4361",
10+
"sha": "e2970ba736edb99e08fb369d4fb0c378189468ee",
1111
"ghcrRepo": "WordPress/gutenberg/gutenberg-wp-develop-build"
1212
},
1313
"engines": {

src/wp-includes/assets/script-loader-packages.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
'wp-url',
101101
'wp-warning'
102102
),
103-
'version' => '0c1dfcebf759791c9a8b'
103+
'version' => '2300d40abe29e438beda'
104104
),
105105
'block-library.js' => array(
106106
'dependencies' => array(
@@ -142,7 +142,7 @@
142142
'import' => 'dynamic'
143143
)
144144
),
145-
'version' => 'd72ed53f961f90f21ed4'
145+
'version' => '67d1a681ec0100a25d78'
146146
),
147147
'block-serialization-default-parser.js' => array(
148148
'dependencies' => array(
@@ -428,7 +428,7 @@
428428
'import' => 'static'
429429
)
430430
),
431-
'version' => 'a688ac97344ffdfcca99'
431+
'version' => 'd36eb0c37b644e4cd4c8'
432432
),
433433
'edit-widgets.js' => array(
434434
'dependencies' => array(
@@ -519,7 +519,7 @@
519519
'import' => 'static'
520520
)
521521
),
522-
'version' => '49ff59c135229f1cc371'
522+
'version' => '63782008412a6163c9f0'
523523
),
524524
'element.js' => array(
525525
'dependencies' => array(
@@ -817,7 +817,7 @@
817817
'wp-hooks',
818818
'wp-private-apis'
819819
),
820-
'version' => '89ec294039260fd01952'
820+
'version' => '8186bfbc15b827d261f5'
821821
),
822822
'theme.js' => array(
823823
'dependencies' => array(

src/wp-includes/assets/script-modules-packages.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@
166166
'import' => 'static'
167167
)
168168
),
169-
'version' => '105defe2f1526f8a43e8'
169+
'version' => '42d3f09bba14cce3054d'
170170
),
171171
'connectors/index.js' => array(
172172
'dependencies' => array(
@@ -177,7 +177,7 @@
177177
'wp-i18n',
178178
'wp-private-apis'
179179
),
180-
'version' => 'e973aa806299e3d70144'
180+
'version' => '274797868955a828dfdc'
181181
),
182182
'core-abilities/index.js' => array(
183183
'dependencies' => array(

src/wp-includes/build/routes/connectors-home/content.js

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ var import_element4 = __toESM(require_element());
702702
var import_i18n = __toESM(require_i18n());
703703
import { speak } from "@wordpress/a11y";
704704
function useConnectorPlugin({
705-
pluginSlug,
705+
file: pluginFileFromServer,
706706
settingName,
707707
connectorName,
708708
isInstalled,
@@ -714,6 +714,8 @@ function useConnectorPlugin({
714714
const [isBusy, setIsBusy] = (0, import_element4.useState)(false);
715715
const [connectedState, setConnectedState] = (0, import_element4.useState)(initialIsConnected);
716716
const [pluginStatusOverride, setPluginStatusOverride] = (0, import_element4.useState)(null);
717+
const pluginBasename = pluginFileFromServer?.replace(/\.php$/, "");
718+
const pluginSlug = pluginBasename?.includes("/") ? pluginBasename.split("/")[0] : pluginBasename;
717719
const {
718720
derivedPluginStatus,
719721
canManagePlugins,
@@ -728,7 +730,7 @@ function useConnectorPlugin({
728730
kind: "root",
729731
name: "plugin"
730732
});
731-
if (!pluginSlug) {
733+
if (!pluginFileFromServer) {
732734
const hasLoaded = store2.hasFinishedResolution(
733735
"getEntityRecord",
734736
["root", "site"]
@@ -740,15 +742,14 @@ function useConnectorPlugin({
740742
canInstallPlugins: canCreate
741743
};
742744
}
743-
const pluginId = `${pluginSlug}/plugin`;
744745
const plugin = store2.getEntityRecord(
745746
"root",
746747
"plugin",
747-
pluginId
748+
pluginBasename
748749
);
749750
const hasFinished = store2.hasFinishedResolution(
750751
"getEntityRecord",
751-
["root", "plugin", pluginId]
752+
["root", "plugin", pluginBasename]
752753
);
753754
if (!hasFinished) {
754755
return {
@@ -779,7 +780,7 @@ function useConnectorPlugin({
779780
canInstallPlugins: canCreate
780781
};
781782
},
782-
[pluginSlug, settingName, isInstalled, isActivated]
783+
[pluginBasename, settingName, isInstalled, isActivated]
783784
);
784785
const pluginStatus = pluginStatusOverride ?? derivedPluginStatus;
785786
const canActivatePlugins = canManagePlugins;
@@ -823,15 +824,18 @@ function useConnectorPlugin({
823824
}
824825
};
825826
const activatePlugin = async () => {
826-
if (!pluginSlug) {
827+
if (!pluginFileFromServer) {
827828
return;
828829
}
829830
setIsBusy(true);
830831
try {
831832
await saveEntityRecord(
832833
"root",
833834
"plugin",
834-
{ plugin: `${pluginSlug}/plugin`, status: "active" },
835+
{
836+
plugin: pluginBasename,
837+
status: "active"
838+
},
835839
{ throwOnError: true }
836840
);
837841
setPluginStatusOverride("active");
@@ -1030,6 +1034,27 @@ var DefaultConnectorLogo = () => /* @__PURE__ */ React.createElement(
10301034
}
10311035
)
10321036
);
1037+
var AkismetLogo = () => /* @__PURE__ */ React.createElement(
1038+
"svg",
1039+
{
1040+
width: "40",
1041+
height: "40",
1042+
viewBox: "0 0 44 44",
1043+
fill: "none",
1044+
xmlns: "http://www.w3.org/2000/svg",
1045+
"aria-hidden": "true"
1046+
},
1047+
/* @__PURE__ */ React.createElement("rect", { width: "44", height: "44", fill: "#357B49", rx: "6" }),
1048+
/* @__PURE__ */ React.createElement(
1049+
"path",
1050+
{
1051+
fill: "#fff",
1052+
fillRule: "evenodd",
1053+
d: "m29.746 28.31-6.392-16.797c-.152-.397-.305-.672-.789-.675-.673 0-1.408.611-1.746 1.316l-7.378 16.154c-.072.16-.143.311-.214.454-.5.995-1.045 1.546-2.357 1.626a.399.399 0 0 0-.16.033l-.01.004a.399.399 0 0 0-.23.392v.01c0 .054.01.106.03.155l.004.01a.416.416 0 0 0 .394.252h6.212a.417.417 0 0 0 .307-.12.416.416 0 0 0 .124-.305.398.398 0 0 0-.105-.302.399.399 0 0 0-.294-.127c-.757 0-2.197-.062-2.197-1.164.02-.318.103-.63.245-.916l1.399-3.152c.52-1.163 1.654-1.163 2.572-1.163h5.843c.023 0 .044 0 .062.003.13.014.16.081.214.242l1.534 4.07a2.857 2.857 0 0 1 .216 1.04c0 .054-.003.104-.01.153-.09.726-.831.887-1.49.887a.4.4 0 0 0-.294.127l-.007.008-.007.008a.401.401 0 0 0-.092.286v.01c0 .054.01.106.03.155l.005.01a.42.42 0 0 0 .395.252h7.011a.413.413 0 0 0 .279-.13.412.412 0 0 0 .11-.297.387.387 0 0 0-.09-.294.388.388 0 0 0-.277-.135c-1.448-.122-2.295-.643-2.847-2.08Zm-11.985-5.844 2.847-6.304c.361-.728.659-1.486.889-2.265 0-.06.03-.092.06-.092s.061.032.061.091c.02.122.045.247.073.374.197.888.584 1.878.914 2.723l.176.453 1.684 4.529a.927.927 0 0 1 .092.4.473.473 0 0 1-.009.094c-.041.202-.228.272-.602.272h-6.063c-.122 0-.184-.03-.184-.092a.36.36 0 0 1 .062-.183Zm17.107-.721c0 .786-.446 1.231-1.25 1.231-.806 0-1.125-.409-1.125-1.034 0-.786.465-1.231 1.25-1.231.785 0 1.125.427 1.125 1.034ZM9.629 23.002c.803 0 1.25-.447 1.25-1.231 0-.607-.343-1.036-1.128-1.036-.785 0-1.25.447-1.25 1.231 0 .625.325 1.036 1.128 1.036Z",
1054+
clipRule: "evenodd"
1055+
}
1056+
)
1057+
);
10331058
var GeminiLogo = () => /* @__PURE__ */ React.createElement(
10341059
"svg",
10351060
{
@@ -1123,7 +1148,8 @@ function getConnectorData() {
11231148
var CONNECTOR_LOGOS = {
11241149
google: GeminiLogo,
11251150
openai: OpenAILogo,
1126-
anthropic: ClaudeLogo
1151+
anthropic: ClaudeLogo,
1152+
akismet: AkismetLogo
11271153
};
11281154
function getConnectorLogo(connectorId, logoUrl) {
11291155
if (logoUrl) {
@@ -1161,7 +1187,8 @@ function ApiKeyConnector({
11611187
const auth = authentication?.method === "api_key" ? authentication : void 0;
11621188
const settingName = auth?.settingName ?? "";
11631189
const helpUrl = auth?.credentialsUrl ?? void 0;
1164-
const pluginSlug = plugin?.slug;
1190+
const pluginFile = plugin?.file?.replace(/\.php$/, "");
1191+
const pluginSlug = pluginFile?.includes("/") ? pluginFile.split("/")[0] : pluginFile;
11651192
let helpLabel;
11661193
try {
11671194
if (helpUrl) {
@@ -1184,7 +1211,7 @@ function ApiKeyConnector({
11841211
saveApiKey,
11851212
removeApiKey
11861213
} = useConnectorPlugin({
1187-
pluginSlug,
1214+
file: plugin?.file,
11881215
settingName,
11891216
connectorName: name,
11901217
isInstalled: plugin?.isInstalled,
@@ -1259,16 +1286,20 @@ function registerDefaultConnectors() {
12591286
const connectors = getConnectorData();
12601287
const sanitize = (s) => s.replace(/[^a-z0-9-_]/gi, "-");
12611288
for (const [connectorId, data] of Object.entries(connectors)) {
1289+
if (connectorId === "akismet" && !data.plugin?.isInstalled) {
1290+
continue;
1291+
}
12621292
const { authentication } = data;
12631293
const connectorName = sanitize(connectorId);
12641294
const args = {
12651295
name: data.name,
12661296
description: data.description,
1297+
type: data.type,
12671298
logo: getConnectorLogo(connectorId, data.logoUrl),
12681299
authentication,
12691300
plugin: data.plugin
12701301
};
1271-
if (data.type === "ai_provider" && authentication.method === "api_key") {
1302+
if (authentication.method === "api_key") {
12721303
args.render = ApiKeyConnector;
12731304
}
12741305
registerConnector(connectorName, args);
@@ -1562,6 +1593,7 @@ function ConnectorsPage() {
15621593
slug: connector.slug,
15631594
name: connector.name,
15641595
description: connector.description,
1596+
type: connector.type,
15651597
logo: connector.logo,
15661598
authentication: connector.authentication,
15671599
plugin: connector.plugin
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-private-apis', 'wp-theme', 'wp-url'), 'module_dependencies' => array(array('id' => '@wordpress/a11y', 'import' => 'static'), array('id' => '@wordpress/connectors', 'import' => 'static'), array('id' => '@wordpress/route', 'import' => 'static')), 'version' => 'e598f70e4e13735c7300');
1+
<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-private-apis', 'wp-theme', 'wp-url'), 'module_dependencies' => array(array('id' => '@wordpress/a11y', 'import' => 'static'), array('id' => '@wordpress/connectors', 'import' => 'static'), array('id' => '@wordpress/route', 'import' => 'static')), 'version' => '067df442b07dc9245aee');

src/wp-includes/build/routes/connectors-home/content.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ final class WP_Connector_Registry {
7171
* For connectors with `api_key` authentication, a `setting_name` can be provided
7272
* explicitly. If omitted, one is automatically generated using the pattern
7373
* `connectors_{$type}_{$id}_api_key`, with hyphens in the type and ID normalized
74-
* to underscores (e.g., connector type `spam_filtering` with ID `akismet` produces
75-
* `connectors_spam_filtering_akismet_api_key`). This setting name is used for the
74+
* to underscores (e.g., connector type `spam_filtering` with ID `my_plugin` produces
75+
* `connectors_spam_filtering_my_plugin_api_key`). This setting name is used for the
7676
* Settings API registration and REST API exposure.
7777
*
7878
* Registering a connector with an ID that is already registered will trigger a
@@ -110,7 +110,7 @@ final class WP_Connector_Registry {
110110
* Optional. Plugin data for install/activate UI.
111111
*
112112
* @type string $file The plugin's main file path relative to the plugins
113-
* directory (e.g. 'akismet/akismet.php' or 'hello.php').
113+
* directory (e.g. 'my-plugin/my-plugin.php' or 'hello.php').
114114
* }
115115
* }
116116
* @return array|null The registered connector data on success, null on failure.

src/wp-includes/connectors.php

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function wp_is_connector_registered( string $id ): bool {
5959
* Optional. Plugin data for install/activate UI.
6060
*
6161
* @type string $file The plugin's main file path relative to the plugins
62-
* directory (e.g. 'akismet/akismet.php' or 'hello.php').
62+
* directory (e.g. 'my-plugin/my-plugin.php' or 'hello.php').
6363
* }
6464
* }
6565
* @phpstan-return ?array{
@@ -120,7 +120,7 @@ function wp_get_connector( string $id ): ?array {
120120
* Optional. Plugin data for install/activate UI.
121121
*
122122
* @type string $file The plugin's main file path relative to the plugins
123-
* directory (e.g. 'akismet/akismet.php' or 'hello.php').
123+
* directory (e.g. 'my-plugin/my-plugin.php' or 'hello.php').
124124
* }
125125
* }
126126
* }
@@ -210,25 +210,6 @@ function _wp_connectors_init(): void {
210210
_wp_connectors_register_default_ai_providers( $registry );
211211
}
212212

213-
// Non-AI default connectors.
214-
$registry->register(
215-
'akismet',
216-
array(
217-
'name' => __( 'Akismet Anti-spam' ),
218-
'description' => __( 'Protect your site from spam.' ),
219-
'type' => 'spam_filtering',
220-
'plugin' => array(
221-
'file' => 'akismet/akismet.php',
222-
),
223-
'authentication' => array(
224-
'method' => 'api_key',
225-
'credentials_url' => 'https://akismet.com/get/',
226-
'setting_name' => 'wordpress_api_key',
227-
'constant_name' => 'WPCOM_API_KEY',
228-
),
229-
)
230-
);
231-
232213
/**
233214
* Fires when the connector registry is ready for plugins to register connectors.
234215
*
@@ -417,9 +398,9 @@ function _wp_connectors_mask_api_key( string $key ): string {
417398
* @since 7.0.0
418399
* @access private
419400
*
420-
* @param string $setting_name The option name for the API key (e.g., 'connectors_spam_filtering_akismet_api_key').
421-
* @param string $env_var_name Optional. Environment variable name to check (e.g., 'AKISMET_API_KEY').
422-
* @param string $constant_name Optional. PHP constant name to check (e.g., 'AKISMET_API_KEY').
401+
* @param string $setting_name The option name for the API key (e.g., 'connectors_spam_filtering_my_plugin_api_key').
402+
* @param string $env_var_name Optional. Environment variable name to check (e.g., 'MY_PLUGIN_API_KEY').
403+
* @param string $constant_name Optional. PHP constant name to check (e.g., 'MY_PLUGIN_API_KEY').
423404
* @return string The key source: 'env', 'constant', 'database', or 'none'.
424405
*/
425406
function _wp_connectors_get_api_key_source( string $setting_name, string $env_var_name = '', string $constant_name = '' ): string {

tests/phpunit/tests/connectors/wpConnectorsGetConnectorSettings.php

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ public function test_returns_expected_connector_keys(): void {
3737
$this->assertArrayHasKey( 'google', $connectors );
3838
$this->assertArrayHasKey( 'openai', $connectors );
3939
$this->assertArrayHasKey( 'anthropic', $connectors );
40-
$this->assertArrayHasKey( 'akismet', $connectors );
4140
$this->assertArrayHasKey( 'mock-connectors-test', $connectors );
42-
$this->assertCount( 5, $connectors );
41+
$this->assertCount( 4, $connectors );
4342
}
4443

4544
/**
@@ -57,7 +56,7 @@ public function test_each_connector_has_required_fields(): void {
5756
$this->assertArrayHasKey( 'description', $connector_data, "Connector '{$connector_id}' is missing 'description'." );
5857
$this->assertIsString( $connector_data['description'], "Connector '{$connector_id}' description should be a string." );
5958
$this->assertArrayHasKey( 'type', $connector_data, "Connector '{$connector_id}' is missing 'type'." );
60-
$this->assertContains( $connector_data['type'], array( 'ai_provider', 'spam_filtering' ), "Connector '{$connector_id}' has unexpected type '{$connector_data['type']}'." );
59+
$this->assertContains( $connector_data['type'], array( 'ai_provider' ), "Connector '{$connector_id}' has unexpected type '{$connector_data['type']}'." );
6160
$this->assertArrayHasKey( 'authentication', $connector_data, "Connector '{$connector_id}' is missing 'authentication'." );
6261
$this->assertIsArray( $connector_data['authentication'], "Connector '{$connector_id}' authentication should be an array." );
6362
$this->assertArrayHasKey( 'method', $connector_data['authentication'], "Connector '{$connector_id}' authentication is missing 'method'." );
@@ -80,16 +79,11 @@ public function test_api_key_connectors_have_setting_name_and_credentials_url():
8079
++$api_key_count;
8180

8281
$this->assertArrayHasKey( 'setting_name', $connector_data['authentication'], "Connector '{$connector_id}' authentication is missing 'setting_name'." );
83-
84-
// AI providers use the connectors_ai_{id}_api_key convention.
85-
// Non-AI connectors may use custom setting names.
86-
if ( 'ai_provider' === $connector_data['type'] ) {
87-
$this->assertSame(
88-
'connectors_ai_' . str_replace( '-', '_', $connector_id ) . '_api_key',
89-
$connector_data['authentication']['setting_name'] ?? null,
90-
"Connector '{$connector_id}' setting_name does not match expected format."
91-
);
92-
}
82+
$this->assertSame(
83+
'connectors_ai_' . str_replace( '-', '_', $connector_id ) . '_api_key',
84+
$connector_data['authentication']['setting_name'] ?? null,
85+
"Connector '{$connector_id}' setting_name does not match expected format."
86+
);
9387
}
9488

9589
$this->assertGreaterThan( 0, $api_key_count, 'At least one connector should use api_key authentication.' );

0 commit comments

Comments
 (0)