paginate( '', $page, 500 ); foreach ( $batch['items'] as $rule ) { $lines[] = implode( ',', array_map( array( self::class, 'cell' ), array( $rule['source_path'], $rule['target_url'], (string) $rule['code'], $rule['match_mode'], $rule['enabled'] ? '1' : '0' ) ) ); } ++$page; $fetched = count( $batch['items'] ); } while ( 500 === $fetched ); return implode( "\n", $lines ) . "\n"; } /** * Import CSV text. Existing sources are updated; invalid rows are reported. * * @param RedirectRepository $repo Repository. * @param string $csv CSV text. * @return array{created:int,updated:int,errors:array} */ public static function import( RedirectRepository $repo, string $csv ): array { $result = array( 'created' => 0, 'updated' => 0, 'errors' => array(), ); $csv = (string) preg_replace( '/^\xEF\xBB\xBF/', '', $csv ); $lines = preg_split( '/\r\n|\r|\n/', $csv ); foreach ( (array) $lines as $index => $line ) { if ( '' === trim( (string) $line ) ) { continue; } $cells = str_getcsv( (string) $line, ',', '"', '\\' ); if ( 0 === $index && isset( $cells[0] ) && 'source' === strtolower( trim( (string) $cells[0] ) ) ) { continue; } if ( count( $cells ) < 2 ) { /* translators: %d: line number. */ $result['errors'][] = sprintf( __( 'Line %d: expected at least a source and a target.', 'unbreak' ), $index + 1 ); continue; } $input = array( 'source_path' => (string) $cells[0], 'target_url' => (string) $cells[1], 'code' => isset( $cells[2] ) && '' !== $cells[2] ? (int) $cells[2] : 301, 'match_mode' => isset( $cells[3] ) && '' !== $cells[3] ? (string) $cells[3] : '404', 'enabled' => isset( $cells[4] ) && '' !== $cells[4] ? (int) $cells[4] : 1, ); $source = Path::normalize( $input['source_path'], true ); $existing = null !== $source ? $repo->find_by_source( $source ) : null; $saved = $repo->save( $input, null !== $existing ? (int) $existing['id'] : 0 ); if ( is_wp_error( $saved ) ) { /* translators: 1: line number, 2: error message. */ $result['errors'][] = sprintf( __( 'Line %1$d: %2$s', 'unbreak' ), $index + 1, $saved->get_error_message() ); continue; } ++$result[ null !== $existing ? 'updated' : 'created' ]; } return $result; } /** * Quote a CSV cell when needed (and neutralize spreadsheet formulas). * * @param string $value Value. */ private static function cell( string $value ): string { if ( '' !== $value && in_array( $value[0], array( '=', '+', '-', '@' ), true ) ) { $value = "'" . $value; } if ( preg_match( '/[",\r\n]/', $value ) ) { return '"' . str_replace( '"', '""', $value ) . '"'; } return $value; } }