Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion inc/admin-pages/class-shortcodes-admin-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,13 @@ public function get_data() {
$params[ $key ]['options'] = '0 | 1';
break;
case 'select':
$params[ $key ]['options'] = implode(' | ', array_keys(wu_get_isset($value, 'options', [])));
$options = wu_get_isset($value, 'options', []);

if (is_callable($options)) {
$options = call_user_func($options);
}

$params[ $key ]['options'] = implode(' | ', array_keys($options));
break;
case 'int':
$params[ $key ]['options'] = __('integer', 'ultimate-multisite');
Expand Down
19 changes: 9 additions & 10 deletions inc/builders/block-editor/class-block-editor-widget-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,35 +198,34 @@ public function load_block_settings($blocks, $element) {
}

/**
* Generates the list of attributes supported based on the fields.
* Generates the list of attributes supported based on element field types and defaults.
*
* @since 2.0.0
* Field definitions are read as metadata only; option providers are not evaluated.
*
* @param \WP_Ultimo\UI\Base_Element $element The element being registered.
* @return array
*/
public function get_attributes_from_fields($element) {

$fields = $element->fields();

$defaults = $element->defaults();
$fields = $element->fields();

$_fields = [];

foreach ($fields as $field_id => $field) {
$type = 'string';
foreach ($defaults as $field_id => $default_value) {
$type = $fields[ $field_id ]['type'] ?? 'string';

if ('toggle' === $field['type']) {
if ('toggle' === $type) {
$type = 'boolean';
}

if ('number' === $field['type']) {
if ('number' === $type) {
$type = 'integer';
}

$default_value = wu_get_isset($defaults, $field_id, '');

$_fields[ $field_id ] = [
'default' => wu_get_isset($field, 'value', $default_value),
'default' => $default_value,
'type' => $type,
];
}
Expand Down
6 changes: 6 additions & 0 deletions inc/compat/class-gutenberg-support.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public function init(): void {
*/
public function add_scripts(): void {

$screen = get_current_screen();

if ( ! $screen || ! $screen->is_block_editor()) {
return;
}

wp_register_script('wu-gutenberg-support', wu_get_asset('gutenberg-support.js', 'js'), ['jquery'], wu_get_version(), true);

// translators: the placeholder is replaced with the network name.
Expand Down
28 changes: 28 additions & 0 deletions inc/functions/pages.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,34 @@ function wu_is_new_site_page() {
return absint(wu_get_setting('default_new_site_page', 0)) === $post->ID;
}

/**
* Returns a request-memoized list of pages for select field options.
*
* @since 2.0.0
* @param string $default_label The label for the current page option.
* @return array
*/
function wu_get_pages_as_options($default_label) {

static $pages = null;

if (null === $pages) {
$pages = get_pages(
[
'exclude' => [get_the_ID()], // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
]
) ?: [];
}

$pages_list = [0 => $default_label];

foreach ($pages as $page) {
$pages_list[ $page->ID ] = $page->post_title;
}

return $pages_list;
}

/**
* Checks if the current page is a login page.
*
Expand Down
16 changes: 1 addition & 15 deletions inc/ui/class-current-site-element.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,26 +162,12 @@ public function fields() {
'value' => 1,
];

$pages = get_pages(
[
'exclude' => [get_the_ID()], // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
]
);

$pages = $pages ?: [];

$pages_list = [0 => __('Current Page', 'ultimate-multisite')];

foreach ($pages as $page) {
$pages_list[ $page->ID ] = $page->post_title;
}

$fields['breadcrumbs_my_sites_page'] = [
'type' => 'select',
'title' => __('My Sites Page', 'ultimate-multisite'),
'value' => 0,
'desc' => __('The page with the customer sites list.', 'ultimate-multisite'),
'options' => $pages_list,
'options' => fn() => wu_get_pages_as_options(__('Current Page', 'ultimate-multisite')),
];

$fields['display_description'] = [
Expand Down
16 changes: 1 addition & 15 deletions inc/ui/class-my-sites-element.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,20 +162,6 @@ public function fields() {
],
];

$pages = get_pages(
[
'exclude' => [get_the_ID()], // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
]
);

$pages = $pages ?: [];

$pages_list = [0 => __('Current Page', 'ultimate-multisite')];

foreach ($pages as $page) {
$pages_list[ $page->ID ] = $page->post_title;
}

$fields['custom_manage_page'] = [
'type' => 'select',
'title' => __('Manage Redirect Page', 'ultimate-multisite'),
Expand All @@ -185,7 +171,7 @@ public function fields() {
'required' => [
'site_manage_type' => 'custom_page',
],
'options' => $pages_list,
'options' => fn() => wu_get_pages_as_options(__('Current Page', 'ultimate-multisite')),
];

$fields['columns'] = [
Expand Down
16 changes: 1 addition & 15 deletions inc/ui/class-site-actions-element.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,27 +182,13 @@ public function fields() {
'value' => 1,
];

$pages = get_pages(
[
'exclude' => [get_the_ID()], // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
]
);

$pages = $pages ?: [];

$pages_list = [0 => __('Default', 'ultimate-multisite')];

foreach ($pages as $page) {
$pages_list[ $page->ID ] = $page->post_title;
}

$fields['redirect_after_delete'] = [
'type' => 'select',
'title' => __('Redirect After Delete', 'ultimate-multisite'),
'value' => 0,
'desc' => __('The page to redirect user after delete current site.', 'ultimate-multisite'),
'tooltip' => '',
'options' => $pages_list,
'options' => fn() => wu_get_pages_as_options(__('Default', 'ultimate-multisite')),
];

return $fields;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,58 @@ public function test_is_block_preview_passes_through_outside_rest(): void {

$this->assertFalse($result, 'Should return false when not in REST edit context.');
}

/**
* Test attributes use defaults without evaluating field option providers.
*/
public function test_get_attributes_from_fields_does_not_evaluate_field_options(): void {

$element = $this->getMockBuilder('\WP_Ultimo\UI\Simple_Text_Element')
->disableOriginalConstructor()
->onlyMethods(['defaults', 'fields'])
->getMock();

$element->expects($this->once())
->method('defaults')
->willReturn(
[
'enabled' => true,
'columns' => 4,
'site_manage_type' => 'default',
]
);

$element->expects($this->once())
->method('fields')
->willReturn(
[
'enabled' => [
'type' => 'toggle',
'options' => static function () {
throw new \RuntimeException('Block attribute registration must not evaluate options.');
},
],
'columns' => ['type' => 'number'],
'site_manage_type' => ['type' => 'select'],
]
);

$this->assertSame(
[
'enabled' => [
'default' => true,
'type' => 'boolean',
],
'columns' => [
'default' => 4,
'type' => 'integer',
],
'site_manage_type' => [
'default' => 'default',
'type' => 'select',
],
],
$this->manager->get_attributes_from_fields($element)
);
}
}
21 changes: 21 additions & 0 deletions tests/WP_Ultimo/Functions/Pages_Functions_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,27 @@ public function test_is_new_site_page_false_without_post(): void {
$this->assertFalse($result);
}

/**
* Test page options are memoized per request with context-specific defaults.
*/
public function test_get_pages_as_options_memoizes_pages(): void {

$page_id = self::factory()->post->create(
[
'post_type' => 'page',
'post_title' => 'Example page',
]
);

$first = wu_get_pages_as_options('Current Page');
$second = wu_get_pages_as_options('Default');

$this->assertSame('Current Page', $first[0]);
$this->assertSame('Default', $second[0]);
$this->assertSame('Example page', $first[ $page_id ]);
$this->assertSame($first[ $page_id ], $second[ $page_id ]);
}

/**
* Test wu_is_login_page returns bool.
*/
Expand Down
32 changes: 32 additions & 0 deletions tests/WP_Ultimo/General_Compat_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,38 @@ public function test_init_registers_divi_cache_purge_hook(): void {
$this->assertNotFalse(has_action('wu_duplicate_site', [$instance, 'clear_divi_static_css_cache']));
}

/**
* Test Gutenberg support skips ordinary admin screens.
*/
public function test_gutenberg_support_skips_ordinary_admin_screens(): void {

set_current_screen('dashboard');
wp_deregister_script('wu-gutenberg-support');

Gutenberg_Support::get_instance()->add_scripts();

$this->assertFalse(wp_script_is('wu-gutenberg-support', 'registered'));
$this->assertFalse(wp_script_is('wu-gutenberg-support', 'enqueued'));
}

/**
* Test Gutenberg support enqueues and localizes assets in the block editor.
*/
public function test_gutenberg_support_loads_on_block_editor_screens(): void {

set_current_screen('post');
$screen = get_current_screen();

$screen->is_block_editor(true);

wp_deregister_script('wu-gutenberg-support');

Gutenberg_Support::get_instance()->add_scripts();

$this->assertTrue(wp_script_is('wu-gutenberg-support', 'enqueued'));
$this->assertNotEmpty(wp_scripts()->get_data('wu-gutenberg-support', 'data'));
}
Comment thread
superdav42 marked this conversation as resolved.

/**
* Test Divi et-cache files are deleted only for the cloned site.
*/
Expand Down
Loading