'deltabreen_location', 'post_status' => array( 'publish', 'draft', 'pending', 'private' ), 'title' => $title, 'posts_per_page' => 5, 'fields' => 'ids', 'no_found_rows' => true, ) ); foreach ( $ids as $id ) { if ( (string) get_post_meta( $id, '_deltabreen_address', true ) === $address ) { return (int) $id; } } return 0; } /** The category of that name, made if it is new. */ function deltabreen_maps_import_category( $name ) { $name = deltabreen_maps_clean_text( $name, 60 ); if ( '' === $name ) { return 0; } $term = term_exists( $name, 'deltabreen_location_cat' ); if ( ! $term ) { $term = wp_insert_term( $name, 'deltabreen_location_cat' ); } return is_wp_error( $term ) ? 0 : (int) $term['term_id']; } /** * Save one imported row. * * @param array $row name, address, city, postcode, country, lat, lng, phone, url, category, hours, notes, photo, button, * button_url. * @return string created, updated, or a reason it was skipped. */ function deltabreen_maps_import_row( $row ) { $row = is_array( $row ) ? $row : array(); foreach ( $row as $k => $v ) { // Undo the export's formula guard, so a file exported here comes back as it was ("'+353 …" is "+353 …"). if ( is_string( $v ) && preg_match( "/^'[=+\-@]/", $v ) ) { $row[ $k ] = substr( $v, 1 ); } } $title = deltabreen_maps_clean_text( $row['name'] ?? '', 200 ); if ( '' === $title ) { return __( 'no name', 'maps-by-deltabreen' ); } $address = deltabreen_maps_clean_text( $row['address'] ?? '', 200 ); $id = deltabreen_maps_find_location( $title, $address ); $result = $id ? 'updated' : 'created'; if ( ! $id ) { $id = wp_insert_post( array( 'post_type' => 'deltabreen_location', 'post_status' => 'publish', 'post_title' => $title, ), true ); if ( is_wp_error( $id ) ) { return $id->get_error_message(); } } // Only the columns the file has are written, so an update keeps what the file does not mention. $in = array( 'address' => $address ); foreach ( array( 'city', 'postcode', 'country', 'lng', 'lat', 'phone', 'url', 'notes', 'photo', 'button', 'button_url' ) as $field ) { if ( array_key_exists( $field, $row ) ) { $in[ $field ] = $row[ $field ]; } } if ( array_key_exists( 'hours', $row ) ) { // Hours from the file replace the day-by-day hours, which would otherwise win. $in['hours'] = array(); $in['hours_text'] = $row['hours']; } deltabreen_maps_save_location_meta( $id, $in ); $term = deltabreen_maps_import_category( $row['category'] ?? '' ); if ( $term ) { wp_set_object_terms( $id, array( $term ), 'deltabreen_location_cat' ); } return $result; } add_action( 'rest_api_init', function () { register_rest_route( 'deltabreen-maps/v1', '/locations/import', array( 'methods' => 'POST', 'permission_callback' => function () { return current_user_can( 'manage_options' ); }, 'args' => array( 'rows' => array( 'type' => 'array', 'required' => true, 'maxItems' => DELTABREEN_MAPS_IMPORT_BATCH, 'items' => array( 'type' => 'object' ), ), ), 'callback' => function ( WP_REST_Request $req ) { $results = array(); foreach ( (array) $req['rows'] as $row ) { $results[] = deltabreen_maps_import_row( $row ); } return array( 'results' => $results ); }, ) ); } ); /** A spreadsheet cell that cannot run as a formula when the file is opened. */ function deltabreen_maps_csv_cell( $v ) { $v = (string) $v; if ( '' === $v || is_numeric( $v ) ) { return $v; } return in_array( $v[0], array( '=', '+', '-', '@', "\t", "\r" ), true ) ? "'" . $v : $v; } add_action( 'admin_post_deltabreen_maps_export', function () { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to export locations.', 'maps-by-deltabreen' ), 403 ); } check_admin_referer( 'deltabreen_maps_export' ); nocache_headers(); header( 'Content-Type: text/csv; charset=utf-8' ); header( 'Content-Disposition: attachment; filename="map-locations-' . gmdate( 'Y-m-d' ) . '.csv"' ); $out = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- php://output, not a file. fputcsv( $out, array( 'name', 'address', 'city', 'postcode', 'country', 'latitude', 'longitude', 'phone', 'website', 'category', 'hours', 'notes', 'photo', 'button', 'button_url' ) ); $posts = get_posts( array( 'post_type' => 'deltabreen_location', 'post_status' => array( 'publish', 'draft', 'pending', 'private' ), 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', 'no_found_rows' => true, ) ); foreach ( $posts as $post ) { $terms = get_the_terms( $post, 'deltabreen_location_cat' ); $meta = function ( $field ) use ( $post ) { return (string) get_post_meta( $post->ID, '_deltabreen_' . $field, true ); }; fputcsv( $out, array_map( 'deltabreen_maps_csv_cell', array( html_entity_decode( $post->post_title, ENT_QUOTES, 'UTF-8' ), $meta( 'address' ), $meta( 'city' ), $meta( 'postcode' ), $meta( 'country' ), $meta( 'lat' ), $meta( 'lng' ), $meta( 'phone' ), $meta( 'url' ), ( $terms && ! is_wp_error( $terms ) ) ? html_entity_decode( $terms[0]->name, ENT_QUOTES, 'UTF-8' ) : '', deltabreen_maps_location_hours( $post->ID ), $meta( 'notes' ), $meta( 'photo' ), $meta( 'button' ), $meta( 'button_url' ), ) ) ); } fclose( $out ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- php://output, not a file. exit; } );