*/ public static function source_labels(): array { return array( 'title' => __( 'Post Title', 'feedweaver' ), 'permalink' => __( 'Permalink', 'feedweaver' ), 'excerpt' => __( 'Excerpt', 'feedweaver' ), 'date' => __( 'Publication Date', 'feedweaver' ), 'modified' => __( 'Modified Date', 'feedweaver' ), 'author' => __( 'Author Name', 'feedweaver' ), 'featured_image' => __( 'Featured Image URL', 'feedweaver' ), 'categories' => __( 'Category Names', 'feedweaver' ), 'post_id' => __( 'Post ID', 'feedweaver' ), 'guid' => __( 'WordPress GUID', 'feedweaver' ), 'featured_image_size' => __( 'Featured Image File Size (bytes)', 'feedweaver' ), 'featured_image_type' => __( 'Featured Image Type (MIME)', 'feedweaver' ), 'taxonomy' => __( 'Taxonomy', 'feedweaver' ), 'meta' => __( 'Custom Field', 'feedweaver' ), 'none' => __( 'No value (attributes only)', 'feedweaver' ), ); } /** * URL of a Help & Documentation section. * * @param string $anchor Section id. * @return string */ public static function help_url( string $anchor = '' ): string { return admin_url( 'admin.php?page=' . Admin::PAGE_HELP ) . ( '' !== $anchor ? '#' . $anchor : '' ); } /** * Renders the form. * * @param Feed_Config $config Feed being edited. * @param int $feed_id Feed ID, 0 for new. * @param array $post_types Eligible post types. * @param array> $taxonomies Eligible taxonomies for the chosen types (see Taxonomy_Discovery). * @param array $meta_keys Discovered custom fields. * @param array{has_token:bool,https_ok:bool,local_site:bool} $access Access control state (never a token or verifier). * @param array{name:string,url:string,description:string,language:string} $site Site defaults shown as RSS placeholders. */ public function render( Feed_Config $config, int $feed_id, array $post_types, array $taxonomies, array $meta_keys, array $access = array(), array $site = array() ): void { $site = array_merge( array( 'name' => '', 'url' => '', 'description' => '', 'language' => '', ), $site ); $access = array_merge( array( 'has_token' => false, 'https_ok' => true, 'local_site' => false, ), $access ); ?>
orientation( $feed_id ); ?> address_bar( $config, $feed_id ); ?> card_details( $config ); ?> card_source( $config, $post_types, $taxonomies ); ?> card_format( $config ); ?> card_mapping( $config, $meta_keys, $taxonomies ); ?> card_output( $config, $meta_keys, $site ); ?> card_access( $config, $feed_id, $access ); ?> card_publish( $config, $feed_id ); ?>

$post_types Post types. * @param array> $taxonomies Taxonomies for the chosen types. */ private function card_source( Feed_Config $config, array $post_types, array $taxonomies ): void { $unavailable = array_diff( $config->post_types, array_keys( $post_types ) ); ?>

$label ) : ?>

tax_filters as $taxonomy => $term_ids ) : ?>

>

$meta_keys Discovered keys. * @param array> $taxonomies Taxonomies for the chosen types. */ private function card_mapping( Feed_Config $config, array $meta_keys, array $taxonomies ): void { $labels = self::source_labels(); ?>

mappings ) as $i => $mapping ) : ?> mapping_row( (string) $i, $mapping, $labels, $meta_keys, $taxonomies ); ?>

mappings ? 'hidden' : ''; ?>>

$mapping Mapping. * @param array $labels Source labels. * @param array $meta_keys Discovered keys. * @param array> $taxonomies Taxonomies for the chosen types. */ private function mapping_row( string $index, array $mapping, array $labels, array $meta_keys, array $taxonomies ): void { $source = isset( $mapping['source'] ) ? (string) $mapping['source'] : ''; $meta_key = ''; $tax_key = ''; if ( 0 === strpos( $source, 'meta:' ) ) { $meta_key = substr( $source, 5 ); $source = 'meta'; } elseif ( 0 === strpos( $source, 'tax:' ) ) { $tax_key = substr( $source, 4 ); $source = 'taxonomy'; } $tax_names = array_column( $taxonomies, 'name' ); $is_tax = 'taxonomy' === $source; $path = isset( $mapping['path'] ) ? (string) $mapping['path'] : ''; $is_meta = 'meta' === $source; $known = in_array( $meta_key, array_column( $meta_keys, 'key' ), true ); $manual = '' !== $meta_key && ! $known; $select_val = $manual ? self::MANUAL : $meta_key; $name = 'fw[mappings][' . $index . ']'; ?>
> > >
>

slug ) { return; } $url = Endpoint::url( $config->slug ); $protected = Feed_Config::ACCESS_PROTECTED === $config->access; ?>

enabled ? esc_html__( 'Enabled', 'feedweaver' ) : esc_html__( 'Disabled', 'feedweaver' ); ?>

enabled && ! $protected ) : ?>

enabled ) { esc_html_e( 'This feed is switched off, so this address shows a "not found" page. Tick Enabled under Preview & Publish and save to turn it on.', 'feedweaver' ); } elseif ( $protected ) { esc_html_e( 'This address needs a token. Whoever you give it to adds ?access_key=THE_TOKEN to the end, or sends the token as a Bearer header (see Access Control below). A token is shown only once, when you generate it, and is never part of this address.', 'feedweaver' ); } else { esc_html_e( 'Anyone can read this address.', 'feedweaver' ); } ?>

format, $formats, true ) ? '' : ' hidden' ); } /** * Section 4. * * @param Feed_Config $config Config. * @param array $meta_keys Discovered custom fields (suggestions for key boxes). * @param array{name:string,url:string,description:string,language:string} $site Site defaults shown as RSS placeholders. */ private function card_output( Feed_Config $config, array $meta_keys, array $site ): void { ?>

>

date_format ? '' : 'hidden'; ?>>

date_example( $config->date_custom ) ); ?>

rss_settings( $config, $meta_keys, $site ); ?>
>

>

>
advanced_xml( $config, $meta_keys ); ?>
$meta_keys Discovered custom fields. * @param array{name:string,url:string,description:string,language:string} $site Site defaults. */ private function rss_settings( Feed_Config $config, array $meta_keys, array $site ): void { $rss = $config->rss; $enclosure = $this->enclosure_choices( $config ); ?>
>

enclosure ? 'open' : ''; ?>>

>
>
> >

*/ private function enclosure_choices( Feed_Config $config ): array { $out = array( 'url' => '', 'url_meta' => '', 'length' => 'featured_image_size', 'length_meta' => '', 'type' => 'featured_image_type', 'type_meta' => '', 'type_text' => '', ); if ( null === $config->enclosure ) { return $out; } foreach ( array( 'url', 'length', 'type' ) as $part ) { $spec = isset( $config->enclosure[ $part ] ) ? $config->enclosure[ $part ] : array(); $type = isset( $spec['type'] ) ? $spec['type'] : ''; $value = isset( $spec['value'] ) ? (string) $spec['value'] : ''; if ( 'static' === $type ) { $out[ $part ] = 'static'; $out[ $part . '_text' ] = $value; } elseif ( 0 === strpos( $value, 'meta:' ) ) { $out[ $part ] = 'meta'; $out[ $part . '_meta' ] = substr( $value, 5 ); } elseif ( '' !== $value ) { $out[ $part ] = $value; } } return $out; } /** * The advanced XML settings: namespaces, attributes and repeated element names. Collapsed * by default and shown only for custom XML and RSS, so ordinary feeds never see them. * * @param Feed_Config $config Config. * @param array $meta_keys Discovered keys (unused here; the datalist is shared). */ private function advanced_xml( Feed_Config $config, array $meta_keys ): void { unset( $meta_keys ); $paths = Xml_Options_Validator::element_paths( $config->mappings ); $tax_paths = array(); foreach ( $config->mappings as $mapping ) { if ( 0 === strpos( (string) $mapping['source'], 'tax:' ) ) { $tax_paths[] = trim( (string) $mapping['path'] ); } } ?>
>

namespaces ? 'open' : ''; ?>>

namespaces ) as $i => $row ) : ?> namespace_row( (string) $i, $row ); ?>

attributes ? 'open' : ''; ?>>

. Choose the element, name the attribute, and give it fixed text or a WordPress field. An attribute whose field is empty for an item is left out. To make an element that has only attributes, map the source "No value (attributes only)".', 'feedweaver' ); ?>

attributes ) as $i => $row ) : ?> attribute_row( (string) $i, $row, $paths ); ?>

repeat_names ? 'open' : ''; ?>>

repeat_names ) as $i => $row ) : ?> repeat_row( (string) $i, $row, $tax_paths ); ?>

> >
access; ?>

>


slug ) : ?>


enabled ) : ?>