$field) { if (isset($tabs[$field['tab']])) { $groups[$field['tab']][$key] = $field; } } $count = array_sum(array_map('count', $groups)); ?>

$fields) : ?>

$field) { self::render_card($key, $field); } ?>

$field) { self::render_card($key, $field); } ?>

> />

$name) { $items[] = esc_html($name); if (!isset($active[$slug])) { continue; } $busy[] = (string) $name; if (isset($site[$slug]) && current_user_can('deactivate_plugin', $site[$slug])) { // Comes back to this tab, where the setting then takes over. $url = WPStarter_Replaced_Plugins::deactivate_url($site[$slug]); /* translators: %s: plugin name */ $links[] = sprintf('%2$s', esc_url($url), esc_html(sprintf(__('Deactivate %s', 'wp-plugin-starter-template'), $name))); } } printf( '

%1$s %2$s

', esc_html__('Replaces:', 'wp-plugin-starter-template'), implode(', ', $items) // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. ); if ($busy) { printf( '

%1$s %2$s

', /* translators: %s: plugin names */ esc_html(sprintf(__('%s is still active, so it does this job and this setting waits until it is deactivated.', 'wp-plugin-starter-template'), implode(', ', $busy))), implode(' · ', $links) // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. ); } } /** * Plugins active on this site (not network-wide) keyed by directory slug. * * @return array slug => plugin file */ private static function active_plugins_by_slug() { static $active = null; if (null === $active) { $active = array(); foreach (WPStarter_Feature::stored_active_plugins() as $file) { $slug = dirname((string) $file); if ('.' !== $slug) { $active[$slug] = (string) $file; } } } return $active; } /** * Render a child field row. * * @param string $key Setting key. * @param array $field Schema entry. */ public static function render_field($key, array $field) { $value = WPStarter_Settings::get($key); $id = 'wps-' . $key; $desc_id = $id . '-desc'; $attrs = sprintf('id="%1$s" data-wps-setting="%2$s" aria-describedby="%3$s"', esc_attr($id), esc_attr($key), esc_attr($desc_id)); $is_multi = 'multi' === $field['type']; ?>
', $attrs); // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. $choices = WPStarter_Settings::options_for($field); if (!empty($field['open']) && '' !== (string) $value && !array_key_exists((string) $value, $choices)) { // A saved choice whose plugin is not loaded here stays shown. $choices[(string) $value] = (string) $value; } foreach ($choices as $option_value => $option_label) { printf( '', esc_attr((string) $option_value), selected((string) $value, (string) $option_value, false), esc_html($option_label) ); } echo ''; break; case 'multi': $chosen = array_map('strval', (array) $value); $choices = WPStarter_Settings::options_for($field); // With some plugins skipped on this request, a saved // choice may belong to one of them; keep it too. if (!empty($field['open']) || WPStarter_Feature::plugins_skipped()) { // Saved items that are not registered right now stay visible so they can be unticked. foreach (array_diff($chosen, array_map('strval', array_keys($choices))) as $missing) { $choices[$missing] = $missing; } } $long = count($choices) > 12; if ($long) { // Long lists (such as every active plugin) scroll, with quick choices. printf( ' · ', esc_attr($id), esc_html__('Select all', 'wp-plugin-starter-template'), esc_html__('Clear', 'wp-plugin-starter-template') ); } // The group carries data-wps-setting; the JS saves every checked value. printf( '
', $attrs, // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. esc_attr($id . '-label'), $long ? ' is-long' : '' ); foreach ($choices as $option_value => $option_label) { printf( '', esc_attr((string) $option_value), checked(in_array((string) $option_value, $chosen, true), true, false), esc_html($option_label) ); } echo '
'; break; case 'url': printf( '', $attrs, // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. esc_attr((string) $value), esc_attr(isset($field['placeholder']) ? $field['placeholder'] : '') ); break; case 'times': printf( '', $attrs, // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. esc_attr((string) $value), esc_attr(isset($field['placeholder']) ? $field['placeholder'] : '') ); break; case 'int': printf( '', $attrs, // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. esc_attr((string) $value), esc_attr(isset($field['min']) ? (string) $field['min'] : ''), esc_attr(isset($field['max']) ? (string) $field['max'] : '') ); if (!empty($field['unit'])) { echo ' ' . esc_html($field['unit']) . ''; } break; case 'lines': case 'domains': printf( '', isset($field['rows']) ? (int) $field['rows'] : 3, $attrs, // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. esc_attr(isset($field['placeholder']) ? $field['placeholder'] : ''), esc_textarea((string) $value) ); break; case 'media': // The hidden input carries data-wps-setting; the JS sets it // from the media dialog and saves it. $image_id = (int) $value; $preview = $image_id ? wp_get_attachment_image_url($image_id, 'thumbnail') : ''; echo '
'; printf( '', esc_attr($key), esc_attr((string) $image_id) ); if ($preview) { printf('', esc_url($preview)); } else { echo ''; } printf( '', esc_attr($id), esc_attr($desc_id), esc_html__('Choose picture', 'wp-plugin-starter-template') ); printf( '', $image_id ? '' : ' hidden', esc_html__('Remove', 'wp-plugin-starter-template') ); echo '
'; break; case 'bool': printf( '', $attrs, // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. checked((bool) $value, true, false) ); break; case 'text': default: printf( '', $attrs, // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. esc_attr((string) $value), esc_attr(isset($field['placeholder']) ? $field['placeholder'] : '') ); break; } ?>