unresolved = array(); // Only inside the attributes of blocks whose ids are media. Any other // block's "id" is its own business, and a number that happens to be in // the map would be repointed at an unrelated item. $value = (string) preg_replace_callback( '#()#s', function ( $block ) use ( $map ) { $attributes = (string) preg_replace_callback( '#"(id|mediaId)":(\d+)#', function ( $matches ) use ( $map ) { return '"' . $matches[1] . '":' . $this->remap( (int) $matches[2], $map ); }, $block[3] ); $attributes = (string) preg_replace_callback( '#"ids":\[([\d,\s]*)\]#', function ( $matches ) use ( $map ) { $ids = array_filter( array_map( 'trim', explode( ',', $matches[1] ) ), static fn( $id ) => '' !== $id ); return '"ids":[' . implode( ',', array_map( fn( $id ) => $this->remap( (int) $id, $map ), $ids ) ) . ']'; }, $attributes ); return $block[1] . $attributes . $block[4]; }, $content ); $value = (string) preg_replace_callback( '#wp-image-(\d+)#', function ( $matches ) use ( $map ) { return 'wp-image-' . $this->remap( (int) $matches[1], $map ); }, $value ); return array( 'value' => $value, 'unresolved' => array_values( array_unique( $this->unresolved ) ), ); } /** * Translate one id, recording it when the map has no entry. * * @param int $id Source-site id. * @param Id_Map $map The id map. * @return int */ private function remap( int $id, Id_Map $map ): int { $new = $map->get( Reference_Hint::TYPE_POST, $id ); if ( null === $new ) { $this->unresolved[] = $id; return $id; } return $new; } }