ID;
echo '
' . esc_html__( 'AI readiness (E-E-A-T)', 'acid-aeo' ) . '
';
echo '' . esc_html__( 'Used in the author’s Person schema node, so an answer engine can attribute what it quotes.', 'acid-aeo' ) . '
';
wp_nonce_field( self::NONCE, self::NONCE . '_nonce' );
echo '';
}
/**
* Saves the section from a profile screen.
*
* @param mixed $user_id ID of the user being saved.
* @return void
*/
public function save( $user_id ): void {
$user_id = (int) $user_id;
if ( $user_id <= 0 || ! current_user_can( 'edit_user', $user_id ) ) {
return;
}
$nonce = isset( $_POST[ self::NONCE . '_nonce' ] )
? sanitize_text_field( wp_unslash( $_POST[ self::NONCE . '_nonce' ] ) )
: '';
if ( '' === $nonce || ! wp_verify_nonce( $nonce, self::NONCE ) ) {
return;
}
update_user_meta( $user_id, self::JOB_TITLE, sanitize_text_field( $this->posted( self::JOB_TITLE ) ) );
update_user_meta( $user_id, self::SAME_AS, $this->urls( $this->posted( self::SAME_AS ) ) );
update_user_meta( $user_id, self::KNOWS_ABOUT, sanitize_text_field( $this->posted( self::KNOWS_ABOUT ) ) );
update_user_meta( $user_id, self::ALUMNI_OF, sanitize_text_field( $this->posted( self::ALUMNI_OF ) ) );
}
/**
* One submitted field, unslashed and sanitized as plain text.
*
* Line breaks survive, because the profile URLs arrive one per line; every
* caller narrows the value further for its own field.
*
* The caller has already verified the nonce and the capability.
*
* @param string $field Field name.
* @return string Sanitized value, empty when the field was not posted.
*/
private function posted( string $field ): string {
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in save(), which is this method's only caller.
if ( ! isset( $_POST[ $field ] ) || ! is_scalar( $_POST[ $field ] ) ) {
return '';
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in save(), which is this method's only caller.
return sanitize_textarea_field( (string) wp_unslash( $_POST[ $field ] ) );
}
/**
* Keeps the lines of a textarea that are valid URLs.
*
* @param string $value Raw textarea value.
* @return string One URL per line.
*/
private function urls( string $value ): string {
$lines = preg_split( '/\R/', $value );
$urls = [];
foreach ( is_array( $lines ) ? $lines : [] as $line ) {
$url = esc_url_raw( trim( $line ) );
if ( '' !== $url ) {
$urls[] = $url;
}
}
return implode( "\n", array_unique( $urls ) );
}
/**
* One user meta value as a string.
*
* @param int $user_id User ID.
* @param string $key Meta key.
* @return string Meta value.
*/
private function meta( int $user_id, string $key ): string {
$value = get_user_meta( $user_id, $key, true );
return is_scalar( $value ) ? (string) $value : '';
}
/**
* Renders one single line field.
*
* @param string $field Field name and meta key.
* @param string $label Translated label.
* @param string $value Current value.
* @param string $description Translated help text.
* @return void
*/
private function text_row( string $field, string $label, string $value, string $description ): void {
printf(
' | %4$s |
',
esc_attr( $field ),
esc_html( $label ),
esc_attr( $value ),
esc_html( $description )
);
}
/**
* Renders one multi line field.
*
* @param string $field Field name and meta key.
* @param string $label Translated label.
* @param string $value Current value.
* @param string $description Translated help text.
* @return void
*/
private function textarea_row( string $field, string $label, string $value, string $description ): void {
printf(
' | %4$s |
',
esc_attr( $field ),
esc_html( $label ),
esc_textarea( $value ),
esc_html( $description )
);
}
}