repository = $repository ?? new Repository(); } /** * @param list}> $items * @return array{updated: int, errors: list} */ public function update( array $items ): array { $adapter = SeoMetaRegistry::get_active(); $updated = 0; $errors = []; if ( 'none' === $adapter->get_id() ) { return [ 'updated' => 0, 'errors' => [ [ 'post_id' => 0, 'message' => __( 'No SEO plugin adapter is active.', '4wp-seo-helper' ), ], ], ]; } foreach ( $items as $item ) { $post_id = (int) ( $item['post_id'] ?? 0 ); $fields = is_array( $item['fields'] ?? null ) ? $item['fields'] : []; if ( $post_id <= 0 ) { $errors[] = [ 'post_id' => $post_id, 'message' => __( 'Invalid post ID.', '4wp-seo-helper' ), ]; continue; } if ( ! Auth::can_edit_inventory() && ! current_user_can( 'edit_post', $post_id ) ) { $errors[] = [ 'post_id' => $post_id, 'message' => __( 'Insufficient permissions.', '4wp-seo-helper' ), ]; continue; } if ( null === $this->repository->get_record( $post_id ) ) { $errors[] = [ 'post_id' => $post_id, 'message' => __( 'Post is not in the SEO inventory scope.', '4wp-seo-helper' ), ]; continue; } $normalized = $this->normalize_fields( $fields ); $has_focus = array_key_exists( 'focus_keyphrases', $fields ) || array_key_exists( 'focus_keyword', $fields ); if ( empty( $normalized ) && ! $has_focus ) { $errors[] = [ 'post_id' => $post_id, 'message' => __( 'No supported fields provided.', '4wp-seo-helper' ), ]; continue; } if ( $has_focus ) { $raw_phrases = array_key_exists( 'focus_keyphrases', $fields ) ? $fields['focus_keyphrases'] : $fields['focus_keyword']; $phrases = FocusKeyphrases::normalize_input( $raw_phrases ); FocusKeyphrases::save( $post_id, $phrases ); $normalized['focus_keyword'] = FocusKeyphrases::primary( $phrases ); } if ( ! $adapter->write( $post_id, $normalized ) ) { $errors[] = [ 'post_id' => $post_id, 'message' => __( 'Failed to write SEO meta.', '4wp-seo-helper' ), ]; continue; } HistoryLogger::record_seo( $post_id ); ++$updated; } return [ 'updated' => $updated, 'errors' => $errors, ]; } /** * @param array $fields * @return array */ private function normalize_fields( array $fields ): array { $aliases = [ 'seo_title' => 'title', 'meta_description' => 'description', ]; $normalized = []; foreach ( $fields as $key => $value ) { $key = sanitize_key( (string) $key ); if ( isset( $aliases[ $key ] ) ) { $key = $aliases[ $key ]; } $allowed = [ 'title', 'description', 'focus_keyword', 'focus_keyphrases', 'canonical', 'noindex', 'og_title', 'og_description', 'og_image', ]; if ( ! in_array( $key, $allowed, true ) ) { continue; } if ( 'focus_keyphrases' === $key ) { continue; } if ( 'noindex' === $key ) { $normalized[ $key ] = (bool) $value; continue; } $normalized[ $key ] = sanitize_text_field( (string) $value ); } return $normalized; } }