Dateien nach „bavarian-rank-engine/includes/Admin“ hochladen
This commit is contained in:
parent
30cc5ed244
commit
0f8c5b2684
5 changed files with 494 additions and 0 deletions
100
bavarian-rank-engine/includes/Admin/MetaPage.php
Normal file
100
bavarian-rank-engine/includes/Admin/MetaPage.php
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
namespace BavarianRankEngine\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class MetaPage {
|
||||
public function register(): void {
|
||||
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
}
|
||||
|
||||
public function register_settings(): void {
|
||||
register_setting(
|
||||
'bre_meta',
|
||||
SettingsPage::OPTION_KEY_META,
|
||||
array(
|
||||
'sanitize_callback' => array( $this, 'sanitize' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function enqueue_assets( string $hook ): void {
|
||||
if ( $hook !== 'bavarian-rank_page_bre-meta' ) {
|
||||
return;
|
||||
}
|
||||
wp_enqueue_style( 'bre-admin', BRE_URL . 'assets/admin.css', array(), BRE_VERSION );
|
||||
wp_enqueue_script( 'bre-admin', BRE_URL . 'assets/admin.js', array( 'jquery' ), BRE_VERSION, true );
|
||||
wp_localize_script(
|
||||
'bre-admin',
|
||||
'breAdmin',
|
||||
array(
|
||||
'nonce' => wp_create_nonce( 'bre_admin' ),
|
||||
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function sanitize( mixed $input ): array {
|
||||
$input = is_array( $input ) ? $input : array();
|
||||
$clean = array();
|
||||
|
||||
$clean['meta_auto_enabled'] = ! empty( $input['meta_auto_enabled'] );
|
||||
$clean['token_mode'] = in_array( $input['token_mode'] ?? '', array( 'limit', 'full' ), true )
|
||||
? $input['token_mode'] : 'limit';
|
||||
$clean['token_limit'] = max( 100, (int) ( $input['token_limit'] ?? 1000 ) );
|
||||
$clean['prompt'] = sanitize_textarea_field( $input['prompt'] ?? SettingsPage::getDefaultPrompt() );
|
||||
|
||||
$all_post_types = array_keys( get_post_types( array( 'public' => true ) ) );
|
||||
$clean['meta_post_types'] = array_values(
|
||||
array_intersect(
|
||||
array_map( 'sanitize_key', (array) ( $input['meta_post_types'] ?? array() ) ),
|
||||
$all_post_types
|
||||
)
|
||||
);
|
||||
|
||||
$schema_types = array( 'organization', 'author', 'speakable', 'article_about', 'breadcrumb', 'ai_meta_tags' );
|
||||
$clean['schema_enabled'] = array_values(
|
||||
array_intersect(
|
||||
array_map( 'sanitize_key', (array) ( $input['schema_enabled'] ?? array() ) ),
|
||||
$schema_types
|
||||
)
|
||||
);
|
||||
|
||||
$org_raw = $input['schema_same_as']['organization'] ?? '';
|
||||
if ( is_array( $org_raw ) ) {
|
||||
$org_raw = implode( "\n", $org_raw );
|
||||
}
|
||||
$clean['schema_same_as'] = array(
|
||||
'organization' => array_values(
|
||||
array_filter(
|
||||
array_map(
|
||||
'esc_url_raw',
|
||||
array_map( 'trim', explode( "\n", $org_raw ) )
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
return $clean;
|
||||
}
|
||||
|
||||
public function render(): void {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
$settings = SettingsPage::getSettings();
|
||||
$post_types = get_post_types( array( 'public' => true ), 'objects' );
|
||||
$schema_labels = array(
|
||||
'organization' => __( 'Organization (sameAs Social Profiles)', 'bavarian-rank-engine' ),
|
||||
'author' => __( 'Author (sameAs Profile Links)', 'bavarian-rank-engine' ),
|
||||
'speakable' => __( 'Speakable (for AI assistants)', 'bavarian-rank-engine' ),
|
||||
'article_about' => __( 'Article about/mentions', 'bavarian-rank-engine' ),
|
||||
'breadcrumb' => __( 'BreadcrumbList', 'bavarian-rank-engine' ),
|
||||
'ai_meta_tags' => __( 'AI-optimized Meta Tags (max-snippet etc.)', 'bavarian-rank-engine' ),
|
||||
);
|
||||
include BRE_DIR . 'includes/Admin/views/meta.php';
|
||||
}
|
||||
}
|
||||
140
bavarian-rank-engine/includes/Admin/ProviderPage.php
Normal file
140
bavarian-rank-engine/includes/Admin/ProviderPage.php
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
namespace BavarianRankEngine\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use BavarianRankEngine\ProviderRegistry;
|
||||
use BavarianRankEngine\Helpers\KeyVault;
|
||||
|
||||
class ProviderPage {
|
||||
private const PRICING_URLS = array(
|
||||
'openai' => 'https://openai.com/de-DE/api/pricing',
|
||||
'anthropic' => 'https://platform.claude.com/docs/en/about-claude/pricing',
|
||||
'gemini' => 'https://ai.google.dev/gemini-api/docs/pricing?hl=de',
|
||||
'grok' => 'https://docs.x.ai/developers/models',
|
||||
);
|
||||
|
||||
public function register(): void {
|
||||
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
add_action( 'wp_ajax_bre_test_connection', array( $this, 'ajax_test_connection' ) );
|
||||
add_action( 'wp_ajax_bre_get_default_prompt', array( $this, 'ajax_get_default_prompt' ) );
|
||||
}
|
||||
|
||||
public function register_settings(): void {
|
||||
register_setting(
|
||||
'bre_provider',
|
||||
SettingsPage::OPTION_KEY_PROVIDER,
|
||||
array(
|
||||
'sanitize_callback' => array( $this, 'sanitize' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function enqueue_assets( string $hook ): void {
|
||||
if ( $hook !== 'bavarian-rank_page_bre-provider' ) {
|
||||
return;
|
||||
}
|
||||
wp_enqueue_style( 'bre-admin', BRE_URL . 'assets/admin.css', array(), BRE_VERSION );
|
||||
wp_enqueue_script( 'bre-admin', BRE_URL . 'assets/admin.js', array( 'jquery' ), BRE_VERSION, true );
|
||||
wp_localize_script(
|
||||
'bre-admin',
|
||||
'breAdmin',
|
||||
array(
|
||||
'nonce' => wp_create_nonce( 'bre_admin' ),
|
||||
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function sanitize( mixed $input ): array {
|
||||
$input = is_array( $input ) ? $input : array();
|
||||
$raw_ex = get_option( SettingsPage::OPTION_KEY_PROVIDER, array() );
|
||||
$existing = is_array( $raw_ex ) ? $raw_ex : array();
|
||||
$clean = array();
|
||||
|
||||
$clean['provider'] = sanitize_key( $input['provider'] ?? 'openai' );
|
||||
|
||||
$clean['api_keys'] = array();
|
||||
foreach ( ( $input['api_keys'] ?? array() ) as $provider_id => $raw ) {
|
||||
$provider_id = sanitize_key( $provider_id );
|
||||
$raw = sanitize_text_field( $raw );
|
||||
if ( $raw !== '' ) {
|
||||
$clean['api_keys'][ $provider_id ] = KeyVault::encrypt( $raw );
|
||||
} elseif ( isset( $existing['api_keys'][ $provider_id ] ) ) {
|
||||
$clean['api_keys'][ $provider_id ] = $existing['api_keys'][ $provider_id ];
|
||||
}
|
||||
}
|
||||
|
||||
$clean['models'] = array();
|
||||
foreach ( ( $input['models'] ?? array() ) as $provider_id => $model ) {
|
||||
$clean['models'][ sanitize_key( $provider_id ) ] = sanitize_text_field( $model );
|
||||
}
|
||||
|
||||
$clean['costs'] = array();
|
||||
foreach ( ( $input['costs'] ?? array() ) as $provider_id => $models ) {
|
||||
$provider_id = sanitize_key( $provider_id );
|
||||
foreach ( (array) $models as $model_id => $prices ) {
|
||||
$in = (float) str_replace( ',', '.', $prices['input'] ?? '0' );
|
||||
$out = (float) str_replace( ',', '.', $prices['output'] ?? '0' );
|
||||
if ( $in > 0 || $out > 0 ) {
|
||||
$clean['costs'][ $provider_id ][ sanitize_text_field( $model_id ) ] = array(
|
||||
'input' => max( 0.0, $in ),
|
||||
'output' => max( 0.0, $out ),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $clean;
|
||||
}
|
||||
|
||||
public function ajax_test_connection(): void {
|
||||
check_ajax_referer( 'bre_admin', 'nonce' );
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_send_json_error( __( 'Insufficient permissions.', 'bavarian-rank-engine' ) );
|
||||
}
|
||||
$provider_id = sanitize_key( $_POST['provider'] ?? '' );
|
||||
$settings = SettingsPage::getSettings();
|
||||
$api_key = $settings['api_keys'][ $provider_id ] ?? '';
|
||||
if ( empty( $api_key ) ) {
|
||||
wp_send_json_error( __( 'No API key saved. Please save first.', 'bavarian-rank-engine' ) );
|
||||
}
|
||||
$provider = ProviderRegistry::instance()->get( $provider_id );
|
||||
if ( ! $provider ) {
|
||||
wp_send_json_error( __( 'Unknown provider.', 'bavarian-rank-engine' ) );
|
||||
}
|
||||
$result = $provider->testConnection( $api_key );
|
||||
if ( $result['success'] ) {
|
||||
wp_send_json_success( $result['message'] );
|
||||
} else {
|
||||
wp_send_json_error( $result['message'] );
|
||||
}
|
||||
}
|
||||
|
||||
public function ajax_get_default_prompt(): void {
|
||||
check_ajax_referer( 'bre_admin', 'nonce' );
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
wp_send_json_success( SettingsPage::getDefaultPrompt() );
|
||||
}
|
||||
|
||||
public function render(): void {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
$settings = SettingsPage::getSettings();
|
||||
$providers = ProviderRegistry::instance()->all();
|
||||
$masked_keys = array();
|
||||
$raw_settings = get_option( SettingsPage::OPTION_KEY_PROVIDER, array() );
|
||||
foreach ( ( $raw_settings['api_keys'] ?? array() ) as $id => $stored ) {
|
||||
$plain = KeyVault::decrypt( $stored );
|
||||
$masked_keys[ $id ] = KeyVault::mask( $plain );
|
||||
}
|
||||
$pricing_urls = self::PRICING_URLS;
|
||||
include BRE_DIR . 'includes/Admin/views/provider.php';
|
||||
}
|
||||
}
|
||||
41
bavarian-rank-engine/includes/Admin/RobotsPage.php
Normal file
41
bavarian-rank-engine/includes/Admin/RobotsPage.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
namespace BavarianRankEngine\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use BavarianRankEngine\Features\RobotsTxt;
|
||||
|
||||
class RobotsPage {
|
||||
public function register(): void {
|
||||
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
||||
}
|
||||
|
||||
public function register_settings(): void {
|
||||
register_setting(
|
||||
'bre_robots',
|
||||
'bre_robots_settings',
|
||||
array( $this, 'sanitize' )
|
||||
);
|
||||
}
|
||||
|
||||
public function sanitize( mixed $input ): array {
|
||||
$input = is_array( $input ) ? $input : array();
|
||||
$blocked = array_values(
|
||||
array_intersect(
|
||||
array_map( 'sanitize_text_field', (array) ( $input['blocked_bots'] ?? array() ) ),
|
||||
array_keys( RobotsTxt::KNOWN_BOTS )
|
||||
)
|
||||
);
|
||||
return array( 'blocked_bots' => $blocked );
|
||||
}
|
||||
|
||||
public function render(): void {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
$settings = RobotsTxt::getSettings();
|
||||
include BRE_DIR . 'includes/Admin/views/robots.php';
|
||||
}
|
||||
}
|
||||
72
bavarian-rank-engine/includes/Admin/SeoWidget.php
Normal file
72
bavarian-rank-engine/includes/Admin/SeoWidget.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
namespace BavarianRankEngine\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class SeoWidget {
|
||||
public function register(): void {
|
||||
add_action( 'add_meta_boxes', array( $this, 'add_boxes' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
|
||||
}
|
||||
|
||||
public function add_boxes(): void {
|
||||
$settings = SettingsPage::getSettings();
|
||||
$post_types = $settings['meta_post_types'] ?? array( 'post', 'page' );
|
||||
foreach ( $post_types as $pt ) {
|
||||
add_meta_box(
|
||||
'bre_seo_widget',
|
||||
__( 'SEO Analyse (BRE)', 'bavarian-rank-engine' ),
|
||||
array( $this, 'render' ),
|
||||
$pt,
|
||||
'side',
|
||||
'default'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function render( \WP_Post $post ): void {
|
||||
$title_len = mb_strlen( $post->post_title );
|
||||
?>
|
||||
<div id="bre-seo-widget" data-site-url="<?php echo esc_attr( home_url() ); ?>">
|
||||
<table style="width:100%;border-collapse:collapse;font-size:12px;line-height:1.8;">
|
||||
<tr>
|
||||
<td style="color:#888;"><?php esc_html_e( 'Titel:', 'bavarian-rank-engine' ); ?></td>
|
||||
<td id="bre-title-stat" style="text-align:right;font-weight:bold;">
|
||||
<?php echo esc_html( $title_len ); ?> / 60
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="color:#888;"><?php esc_html_e( 'Wörter:', 'bavarian-rank-engine' ); ?></td>
|
||||
<td id="bre-words-stat" style="text-align:right;">—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="color:#888;"><?php esc_html_e( 'Lesezeit:', 'bavarian-rank-engine' ); ?></td>
|
||||
<td id="bre-read-stat" style="text-align:right;">—</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr style="margin:8px 0;border:none;border-top:1px solid #eee;">
|
||||
<strong style="font-size:11px;color:#555;"><?php esc_html_e( 'Überschriften', 'bavarian-rank-engine' ); ?></strong>
|
||||
<div id="bre-headings-stat" style="font-size:11px;margin-top:4px;color:#333;">—</div>
|
||||
<hr style="margin:8px 0;border:none;border-top:1px solid #eee;">
|
||||
<strong style="font-size:11px;color:#555;"><?php esc_html_e( 'Links', 'bavarian-rank-engine' ); ?></strong>
|
||||
<div id="bre-links-stat" style="font-size:11px;margin-top:4px;color:#333;">—</div>
|
||||
<div id="bre-seo-warnings" style="margin-top:8px;font-size:11px;color:#d63638;line-height:1.6;"></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function enqueue( string $hook ): void {
|
||||
if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) ) {
|
||||
return;
|
||||
}
|
||||
wp_enqueue_script(
|
||||
'bre-seo-widget',
|
||||
BRE_URL . 'assets/seo-widget.js',
|
||||
array( 'jquery' ),
|
||||
BRE_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
141
bavarian-rank-engine/includes/Admin/SettingsPage.php
Normal file
141
bavarian-rank-engine/includes/Admin/SettingsPage.php
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
namespace BavarianRankEngine\Admin;
|
||||
|
||||
use BavarianRankEngine\Helpers\KeyVault;
|
||||
|
||||
class SettingsPage {
|
||||
/**
|
||||
* Option key for provider + API key data (retains old key name for data continuity).
|
||||
*/
|
||||
public const OPTION_KEY_PROVIDER = 'bre_settings';
|
||||
|
||||
/**
|
||||
* Option key for meta generator settings.
|
||||
*/
|
||||
public const OPTION_KEY_META = 'bre_meta_settings';
|
||||
|
||||
/**
|
||||
* Returns merged settings from both option keys with defaults applied.
|
||||
* Called by MetaGenerator, SchemaEnhancer, BulkPage, and admin pages.
|
||||
*/
|
||||
public static function getSettings(): array {
|
||||
$defaults = array(
|
||||
'provider' => 'openai',
|
||||
'api_keys' => array(),
|
||||
'models' => array(),
|
||||
'meta_auto_enabled' => true,
|
||||
'meta_post_types' => array( 'post', 'page' ),
|
||||
'token_mode' => 'limit',
|
||||
'token_limit' => 1000,
|
||||
'prompt' => self::getDefaultPrompt(),
|
||||
'schema_enabled' => array(),
|
||||
'schema_same_as' => array(),
|
||||
'costs' => array(),
|
||||
);
|
||||
|
||||
$saved_provider = get_option( self::OPTION_KEY_PROVIDER, array() );
|
||||
$saved_provider = is_array( $saved_provider ) ? $saved_provider : array();
|
||||
|
||||
$saved_meta = get_option( self::OPTION_KEY_META, array() );
|
||||
$saved_meta = is_array( $saved_meta ) ? $saved_meta : array();
|
||||
|
||||
$settings = array_merge( $defaults, $saved_provider, $saved_meta );
|
||||
|
||||
foreach ( $settings['api_keys'] as $id => $stored ) {
|
||||
$decrypted = KeyVault::decrypt( $stored );
|
||||
// Fallback: if decrypt returns empty, the stored value is a legacy plain-text key
|
||||
$settings['api_keys'][ $id ] = $decrypted !== '' ? $decrypted : $stored;
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
public static function getDefaultPrompt(): string {
|
||||
return 'Schreibe eine SEO-optimierte Meta-Beschreibung für den folgenden Artikel.' . "\n"
|
||||
. 'Die Beschreibung soll für menschliche Leser verständlich und hilfreich sein,' . "\n"
|
||||
. 'den Inhalt treffend zusammenfassen und zwischen 150 und 160 Zeichen lang sein.' . "\n"
|
||||
. 'Schreibe die Meta-Beschreibung auf {language}.' . "\n"
|
||||
. 'Antworte ausschließlich mit der Meta-Beschreibung, ohne Erklärung.' . "\n\n"
|
||||
. 'Titel: {title}' . "\n"
|
||||
. 'Inhalt: {content}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Kept for backwards compatibility — used by BulkPage and tests.
|
||||
* Validates and sanitises a combined settings array (provider + meta fields).
|
||||
*/
|
||||
public function sanitize_settings( mixed $input ): array {
|
||||
$input = is_array( $input ) ? $input : array();
|
||||
$raw_existing = get_option( self::OPTION_KEY_PROVIDER, array() );
|
||||
$existing = is_array( $raw_existing ) ? $raw_existing : array();
|
||||
$clean = array();
|
||||
|
||||
$clean['provider'] = sanitize_key( $input['provider'] ?? 'openai' );
|
||||
$clean['meta_auto_enabled'] = ! empty( $input['meta_auto_enabled'] );
|
||||
$clean['token_mode'] = in_array( $input['token_mode'] ?? '', array( 'limit', 'full' ), true )
|
||||
? $input['token_mode'] : 'limit';
|
||||
$clean['token_limit'] = max( 100, (int) ( $input['token_limit'] ?? 1000 ) );
|
||||
$clean['prompt'] = sanitize_textarea_field( $input['prompt'] ?? self::getDefaultPrompt() );
|
||||
|
||||
$clean['api_keys'] = array();
|
||||
foreach ( ( $input['api_keys'] ?? array() ) as $provider_id => $raw ) {
|
||||
$provider_id = sanitize_key( $provider_id );
|
||||
$raw = sanitize_text_field( $raw );
|
||||
if ( $raw !== '' ) {
|
||||
$clean['api_keys'][ $provider_id ] = KeyVault::encrypt( $raw );
|
||||
} elseif ( isset( $existing['api_keys'][ $provider_id ] ) ) {
|
||||
$clean['api_keys'][ $provider_id ] = $existing['api_keys'][ $provider_id ];
|
||||
}
|
||||
}
|
||||
|
||||
$clean['models'] = array();
|
||||
foreach ( ( $input['models'] ?? array() ) as $provider_id => $model ) {
|
||||
$clean['models'][ sanitize_key( $provider_id ) ] = sanitize_text_field( $model );
|
||||
}
|
||||
|
||||
$clean['costs'] = array();
|
||||
foreach ( ( $input['costs'] ?? array() ) as $provider_id => $models ) {
|
||||
$provider_id = sanitize_key( $provider_id );
|
||||
foreach ( (array) $models as $model_id => $prices ) {
|
||||
$model_id = sanitize_text_field( $model_id );
|
||||
$clean['costs'][ $provider_id ][ $model_id ] = array(
|
||||
'input' => max( 0.0, (float) ( $prices['input'] ?? 0 ) ),
|
||||
'output' => max( 0.0, (float) ( $prices['output'] ?? 0 ) ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$all_post_types = array_keys( get_post_types( array( 'public' => true ) ) );
|
||||
$clean['meta_post_types'] = array_values(
|
||||
array_intersect(
|
||||
array_map( 'sanitize_key', (array) ( $input['meta_post_types'] ?? array() ) ),
|
||||
$all_post_types
|
||||
)
|
||||
);
|
||||
|
||||
$schema_types = array( 'organization', 'author', 'speakable', 'article_about', 'breadcrumb', 'ai_meta_tags' );
|
||||
$clean['schema_enabled'] = array_values(
|
||||
array_intersect(
|
||||
array_map( 'sanitize_key', (array) ( $input['schema_enabled'] ?? array() ) ),
|
||||
$schema_types
|
||||
)
|
||||
);
|
||||
|
||||
$org_raw = $input['schema_same_as']['organization'] ?? '';
|
||||
if ( is_array( $org_raw ) ) {
|
||||
$org_raw = implode( "\n", $org_raw );
|
||||
}
|
||||
$clean['schema_same_as'] = array(
|
||||
'organization' => array_values(
|
||||
array_filter(
|
||||
array_map(
|
||||
'esc_url_raw',
|
||||
array_map( 'trim', explode( "\n", $org_raw ) )
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
return $clean;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue