From d066ece33102ad1e1a579c0061f1d8fffdf7ead4 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:11:08 +0200 Subject: [PATCH 01/18] Map -> CMB2: remove unused map settings --- includes/Admin.php | 7 --- src/Wordpress/CustomPostType/Map.php | 72 ------------------------ templates/map-settings-page-template.php | 35 ------------ 3 files changed, 114 deletions(-) delete mode 100644 templates/map-settings-page-template.php diff --git a/includes/Admin.php b/includes/Admin.php index 9352a495b..1ed8811ca 100644 --- a/includes/Admin.php +++ b/includes/Admin.php @@ -29,13 +29,6 @@ function commonsbooking_admin() { ); } - // Map marker upload scripts - // TODO needs to be evaluated. Maybe not working on all systems - if ( get_current_screen()->id == 'cb_map' ) { - $script_path = COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-marker-upload.js'; - wp_enqueue_script( 'cb-map-marker-upload_js', $script_path ); - } - // CB 0.X migration wp_localize_script( 'cb-scripts-admin', diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index 5b00b2457..2adf154bf 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -24,16 +24,6 @@ class Map extends CustomPostType { * Initiates needed hooks. */ public function initHooks() { - $cb_map_settings = new MapSettings(); - - // deactivated individual map settings because we don't need them righ now - // map setting should be integrated in CB settings in the future - //$cb_map_settings->prepare_settings(); - - if ( $cb_map_settings->get_option( 'booking_page_link_replacement' ) ) { - add_action( 'wp_enqueue_scripts', array( Map::class, 'replace_map_link_target' ), 11 ); - } - // Add shortcodes add_shortcode( 'cb_map', array( new MapShortcode(), 'execute' ) ); @@ -46,37 +36,6 @@ public static function getView() { return new \CommonsBooking\View\Map(); } - /** - * enforce the replacement of the original (google maps) link target on cb_item booking pages - **/ - public static function replace_map_link_target() { - global $post; - $cb_item = 'cb_items'; - if ( is_object( $post ) && $post->post_type == $cb_item ) { - //get timeframes of item - $cb_data = new CB_Data(); - $date_start = date( 'Y-m-d' ); // current date - $timeframes = $cb_data->get_timeframes( $post->ID, $date_start ); - - $geo_coordinates = []; - if ( $timeframes ) { - foreach ( $timeframes as $timeframe ) { - $geo_coordinates[ $timeframe['id'] ] = [ - 'lat' => get_post_meta( $timeframe['location_id'], 'cb-map_latitude', true ), - 'lon' => get_post_meta( $timeframe['location_id'], 'cb-map_longitude', true ), - ]; - } - } - - wp_register_script( 'cb_map_replace_map_link_js', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-replace-link.js' ); - - wp_add_inline_script( 'cb_map_replace_map_link_js', - "cb_map_timeframes_geo = " . wp_json_encode( $geo_coordinates ) . ";" ); - - wp_enqueue_script( 'cb_map_replace_map_link_js' ); - } - } - /** * load all timeframes from db (that end in the future and it's item's status is 'publish') **/ @@ -118,20 +77,6 @@ public static function get_timeframes() { return $result; } - public static function has_item_valid_status( $item, $item_draft_appearance ): bool { - - if ( $item_draft_appearance == 1 ) { - return $item->post_status == 'publish'; - } - if ( $item_draft_appearance == 2 ) { - return $item->post_status != 'publish'; - } - if ( $item_draft_appearance == 3 ) { - return true; - } - return false; - } - /** * get geo data from location metadata * @@ -290,23 +235,6 @@ function ( $item ) { return $locations; } - public static function get_cb_items_category_groups( $preset_categories ) { - $groups = []; - $category_terms = Item::getTerms(); - - foreach ( $category_terms as $term ) { - if ( in_array( $term->term_id, $preset_categories ) ) { - if ( ! isset( $groups[ $term->parent ] ) ) { - $groups[ $term->parent ] = []; - } - $groups[ $term->parent ][] = $term->term_id; - - } - } - - return $groups; - } - /** * basic check if the given string is valid JSON **/ diff --git a/templates/map-settings-page-template.php b/templates/map-settings-page-template.php deleted file mode 100644 index e26f929d6..000000000 --- a/templates/map-settings-page-template.php +++ /dev/null @@ -1,35 +0,0 @@ - -
- -

- -

- -
- - - - - - - -
- : - - - value="on"> -
- - -
-
From 59d1d09f343b3bef37f78836678e284f0062cdfe Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:48:05 +0200 Subject: [PATCH 02/18] MAP -> CMB2: added tearing down of maps in tests --- tests/php/Wordpress/CustomPostTypeTest.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/php/Wordpress/CustomPostTypeTest.php b/tests/php/Wordpress/CustomPostTypeTest.php index 96ad79f13..2097ac95b 100644 --- a/tests/php/Wordpress/CustomPostTypeTest.php +++ b/tests/php/Wordpress/CustomPostTypeTest.php @@ -49,6 +49,8 @@ abstract class CustomPostTypeTest extends BaseTestCase { protected $itemIds = []; + protected $mapIds = []; + protected $subscriberId; protected int $adminUserID; @@ -436,6 +438,8 @@ protected function createMap($options) { update_post_meta( $mapId, 'cb_map_options', $options ); + $this->mapIds[] = $mapId; + return $mapId; } @@ -543,6 +547,7 @@ protected function tearDown() : void { $this->tearDownAllTimeframes(); $this->tearDownAllBookings(); $this->tearDownAllRestrictions(); + $this->tearDownAllMaps(); $this->tearDownBookingCodesTable(); wp_logout(); @@ -578,6 +583,12 @@ protected function tearDownAllRestrictions() { } } + protected function tearDownAllMaps() { + foreach ( $this->mapIds as $id ) { + wp_delete_post( $id, true ); + } + } + protected function tearDownBookingCodesTable() { global $wpdb; $table_name = $wpdb->prefix . BookingCodes::$tablename; From 9691bb913f0f90bf399f7ad21891f4377533a5ba Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:52:14 +0200 Subject: [PATCH 03/18] MAP -> CMB2: move map logic to map model --- src/Map/MapData.php | 118 +++++------ src/Map/MapShortcode.php | 28 ++- src/Model/Map.php | 257 +++++++++++++++++++++- src/Wordpress/CustomPostType/Map.php | 304 ++------------------------- 4 files changed, 352 insertions(+), 355 deletions(-) diff --git a/src/Map/MapData.php b/src/Map/MapData.php index 535269a9a..0090ae054 100644 --- a/src/Map/MapData.php +++ b/src/Map/MapData.php @@ -3,12 +3,15 @@ namespace CommonsBooking\Map; use CommonsBooking\Helper\Wordpress; -use CommonsBooking\Wordpress\CustomPostType\Map; +use CommonsBooking\Model\Map; class MapData { public static function geo_search() { if ( isset( $_POST['query'] ) && $_POST['cb_map_id'] ) { + $map = new Map( $_POST['cb_map_id'] ); + + $check_capacity = true; $attempts = 0; @@ -41,12 +44,11 @@ public static function geo_search() { 'limit' => 1, ]; - $options = MapAdmin::get_options( sanitize_text_field( $_POST['cb_map_id'] ), true ); + if ( $map->getMeta( 'address_search_bounds_left_bottom_lat' ) && $map->getMeta( 'address_search_bounds_left_bottom_lon' ) && $map->getMeta( 'address_search_bounds_right_top_lat' ) && $map->getMeta( 'address_search_bounds_right_top_lon' ) ) { - if ( $options['address_search_bounds_left_bottom_lat'] && $options['address_search_bounds_left_bottom_lon'] && $options['address_search_bounds_right_top_lat'] && $options['address_search_bounds_right_top_lon'] ) { $params['bounded'] = 1; //viewbox - lon1, lat1, lon2, lat2: 12.856779316446545, 52.379790828551016, 13.948545673868422, 52.79694936237738 - $params['viewbox'] = $options['address_search_bounds_left_bottom_lon'] . ',' . $options['address_search_bounds_left_bottom_lat'] . ',' . $options['address_search_bounds_right_top_lon'] . ',' . $options['address_search_bounds_right_top_lat']; + $params['viewbox'] = $map->getMeta( 'address_search_bounds_left_bottom_lon' ) . ',' . $map->getMeta( 'address_search_bounds_left_bottom_lat' ) . ',' . $map->getMeta( 'address_search_bounds_right_top_lon' ) . ',' . $map->getMeta( 'address_search_bounds_right_top_lat' ); } $url = 'https://nominatim.openstreetmap.org/search?' . http_build_query( $params ); @@ -90,6 +92,7 @@ public static function get_locations() { if ( $post && $post->post_type == 'cb_map' ) { $cb_map_id = $post->ID; + $map = new Map( $cb_map_id ); } else { wp_send_json_error( [ 'error' => 2 ], 400 ); @@ -103,15 +106,16 @@ public static function get_locations() { if ( $post->post_status == 'publish' ) { + $map = new Map( $cb_map_id ); $settings = self::get_settings( $cb_map_id ); $default_date_start = $settings['filter_availability']['date_min']; $default_date_end = $settings['filter_availability']['date_max']; $itemTerms = self::getItemCategoryTerms( $settings ); - $locations = Map::get_locations( $cb_map_id, $itemTerms ); + $locations = $map->get_locations( $itemTerms ); //create availabilities - $show_item_availability = MapAdmin::get_option( $cb_map_id, 'show_item_availability' ); - $show_item_availability_filter = MapAdmin::get_option( $cb_map_id, 'show_item_availability_filter' ); + $show_item_availability = $map->getMeta( 'show_item_availability' ); + $show_item_availability_filter = $map->getMeta( 'show_item_availability_filter' ); if ( $show_item_availability || $show_item_availability_filter ) { $locations = MapItemAvailable::create_items_availabilities( @@ -154,12 +158,13 @@ public static function getItemCategoryTerms( $settings ): array { * get the settings for the frontend of the map with given id **/ public static function get_settings( $cb_map_id ): array { + $map = new Map( $cb_map_id ); $date_min = Wordpress::getUTCDateTime(); $date_min = $date_min->format( 'Y-m-d' ); - $max_days_in_future = MapAdmin::get_option( $cb_map_id, 'availability_max_days_to_show' ); + $max_days_in_future = $map->getMeta( 'availability_max_days_to_show' ); $date_max = Wordpress::getUTCDateTime( $date_min . ' + ' . $max_days_in_future . ' days' ); $date_max = $date_max->format( 'Y-m-d' ); - $maxdays = MapAdmin::get_option( $cb_map_id, 'availability_max_day_count' ); + $maxdays = $map->getMeta( 'availability_max_day_count' ); $settings = [ 'data_url' => get_site_url( null, '', null ) . '/wp-admin/admin-ajax.php', @@ -203,61 +208,54 @@ public static function get_settings( $cb_map_id ): array { 'label_item_category_filter', ]; - foreach ( $options as $key => $value ) { - if ( in_array( $key, $pass_through ) ) { - $settings[ $key ] = $value; - } elseif ( $key == 'custom_marker_media_id' ) { - if ( $value != null ) { - $settings['custom_marker_icon'] = [ - 'iconUrl' => wp_get_attachment_url( $options['custom_marker_media_id'] ), - 'iconSize' => [ $options['marker_icon_width'], $options['marker_icon_height'] ], - 'iconAnchor' => [ $options['marker_icon_anchor_x'], $options['marker_icon_anchor_y'] ], - ]; - } - } elseif ( $key == 'marker_item_draft_media_id' ) { - if ( $value != null ) { - $settings['item_draft_marker_icon'] = [ - 'iconUrl' => wp_get_attachment_url( $options['marker_item_draft_media_id'] ), - 'iconSize' => [ - $options['marker_item_draft_icon_width'], - $options['marker_item_draft_icon_height'], - ], //[27, 35], // size of the icon - 'iconAnchor' => [ - $options['marker_item_draft_icon_anchor_x'], - $options['marker_item_draft_icon_anchor_y'], - ], //[13.5, 0], // point of the icon which will correspond to marker's location + foreach ($pass_through as $key) { + $settings[$key] = $map->getMeta($key); + } + + if ($map->getMeta('custom_marker_media_id')) { + $settings['custom_marker_icon'] = [ + 'iconUrl' => wp_get_attachment_url($map->getMeta('custom_marker_media_id')), + 'iconSize' => [$map->getMeta('marker_icon_width'), $map->getMeta('marker_icon_height')], + 'iconAnchor' => [$map->getMeta('marker_icon_anchor_x'), $map->getMeta('marker_icon_anchor_y')], + ]; + } + + if ($map->getMeta('marker_item_draft_media_id')) { + $settings['item_draft_marker_icon'] = [ + 'iconUrl' => wp_get_attachment_url($map->getMeta('marker_item_draft_media_id')), + 'iconSize' => [$map->getMeta('marker_item_draft_icon_width'), $map->getMeta('marker_item_draft_icon_height')], + 'iconAnchor' => [$map->getMeta('marker_item_draft_icon_anchor_x'), $map->getMeta('marker_item_draft_icon_anchor_y')], + ]; + } + + if ($map->getMeta('custom_marker_cluster_media_id')) { + $settings['marker_cluster_icon'] = [ + 'url' => wp_get_attachment_url($map->getMeta('custom_marker_cluster_media_id')), + 'size' => [ + 'width' => $map->getMeta('marker_cluster_icon_width'), + 'height' => $map->getMeta('marker_cluster_icon_height'), + ], + ]; + } + + //categories are only meant to be shown on local maps + if ($map->getMeta('cb_items_available_categories')) { + $settings['filter_cb_item_categories'] = []; + $current_group_id = null; + foreach ( $map->getMeta('cb_items_available_categories') as $categoryKey => $content ) { + if ( substr( $categoryKey, 0, 1 ) == 'g' ) { + $current_group_id = $categoryKey; + $settings['filter_cb_item_categories'][ $categoryKey ] = [ + 'name' => $content, + 'elements' => [], ]; - } - } elseif ( $key == 'custom_marker_cluster_media_id' ) { - if ( $value != null ) { - $settings['marker_cluster_icon'] = [ - 'url' => wp_get_attachment_url( $options['custom_marker_cluster_media_id'] ), - 'size' => [ - 'width' => $options['marker_cluster_icon_width'], - 'height' => $options['marker_cluster_icon_height'], - ], + } else { + $settings['filter_cb_item_categories'][ $current_group_id ]['elements'][] = [ + 'cat_id' => $categoryKey, + 'markup' => $content, ]; } - } //categories are only meant to be shown on local maps - elseif ( $key == 'cb_items_available_categories' ) { - $settings['filter_cb_item_categories'] = []; - $current_group_id = null; - foreach ( $options['cb_items_available_categories'] as $categoryKey => $content ) { - if ( substr( $categoryKey, 0, 1 ) == 'g' ) { - $current_group_id = $categoryKey; - $settings['filter_cb_item_categories'][ $categoryKey ] = [ - 'name' => $content, - 'elements' => [], - ]; - } else { - $settings['filter_cb_item_categories'][ $current_group_id ]['elements'][] = [ - 'cat_id' => $categoryKey, - 'markup' => $content, - ]; - } - } } - } return $settings; diff --git a/src/Map/MapShortcode.php b/src/Map/MapShortcode.php index 7d70df44e..3a051e258 100644 --- a/src/Map/MapShortcode.php +++ b/src/Map/MapShortcode.php @@ -2,16 +2,21 @@ namespace CommonsBooking\Map; +use CommonsBooking\Model\Map; + class MapShortcode extends BaseShortcode { - protected function create_container($cb_map_id, $attrs, $options, $content) { - $map_height = MapAdmin::get_option( $cb_map_id, 'map_height' ); + protected function create_container( $cb_map_id, $attrs, $options, $content ) { + $map = new Map( $cb_map_id ); + $map_height = $map->getMeta( 'map_height' ); + return '
'; } + protected function parse_attributes( $atts ) { - return shortcode_atts(array('id' => 0), $atts); + return shortcode_atts( array( 'id' => 0 ), $atts ); } - protected function inject_script($cb_map_id) { + protected function inject_script( $cb_map_id ) { wp_add_inline_script( 'cb-map-shortcode', "jQuery(document).ready(function ($) { var cb_map = new CB_Map(); @@ -28,13 +33,14 @@ protected function inject_script($cb_map_id) { * get the translations for the frontend **/ private function get_translation( $cb_map_id ): array { - $label_location_opening_hours = MapAdmin::get_option( $cb_map_id, 'label_location_opening_hours' ); - $label_location_contact = MapAdmin::get_option( $cb_map_id, 'label_location_contact' ); - $custom_no_locations_message = MapAdmin::get_option( $cb_map_id, 'custom_no_locations_message' ); - $custom_filterbutton_label = MapAdmin::get_option( $cb_map_id, 'custom_filterbutton_label' ); - $label_item_availability_filter = MapAdmin::get_option( $cb_map_id, 'label_item_availability_filter' ); - $label_item_category_filter = MapAdmin::get_option( $cb_map_id, 'label_item_category_filter' ); - $label_location_distance_filter = MapAdmin::get_option( $cb_map_id, 'label_location_distance_filter' ); + $map = new Map( $cb_map_id ); + $label_location_opening_hours = $map->getMeta( 'label_location_opening_hours' ); + $label_location_contact = $map->getMeta( 'label_location_contact' ); + $custom_no_locations_message = $map->getMeta( 'custom_no_locations_message' ); + $custom_filterbutton_label = $map->getMeta( 'custom_filterbutton_label' ); + $label_item_availability_filter = $map->getMeta( 'label_item_availability_filter' ); + $label_item_category_filter = $map->getMeta( 'label_item_category_filter' ); + $label_location_distance_filter = $map->getMeta( 'label_location_distance_filter' ); return [ 'OPENING_HOURS' => strlen( $label_location_opening_hours ) > 0 ? $label_location_opening_hours : esc_html__( 'opening hours', 'commonsbooking' ), diff --git a/src/Model/Map.php b/src/Model/Map.php index 9dbd68c27..a19ca5ac3 100644 --- a/src/Model/Map.php +++ b/src/Model/Map.php @@ -2,6 +2,12 @@ namespace CommonsBooking\Model; +use CommonsBooking\Helper\Helper; +use CommonsBooking\Repository\Item; +use CommonsBooking\Repository\Timeframe; +use CommonsBooking\Wordpress\CustomPostType\Location; +use Exception; + /** * This class currently does not have any functionality. * It's just a placeholder for the Map post type. @@ -10,7 +16,254 @@ * * Currently, it's only referenced by the @see \CommonsBooking\Wordpress\CustomPostType\CustomPostType::getModel() method to use the methods from the CustomPost class. */ -class Map extends CustomPost -{ +class Map extends CustomPost { + + /** + * get geo data from location metadata + * + * @param $cb_map_id + * @param $mapItemTerms + * + * @return array + * @throws Exception + */ + public function get_locations( $mapItemTerms ): array { + $locations = []; + + $show_location_contact = $this->getMeta( 'show_location_contact' ); + $show_location_opening_hours = $this->getMeta( 'show_location_opening_hours' ); + + $preset_categories = $this->getMeta( 'cb_items_preset_categories' ); + $preset_location_categories = $this->getMeta( 'cb_locations_preset_categories' ); + + + $args = [ + 'post_type' => Location::$postType, + 'posts_per_page' => - 1, + 'post_status' => 'publish', + 'meta_query' => [ + [ + 'key' => 'geo_longitude', + 'meta_compare' => 'EXISTS', + ], + ], + ]; + + $locationObjects = \CommonsBooking\Repository\Location::get( + $args, + true + ); + + /** @var \CommonsBooking\Model\Location $post */ + foreach ( $locationObjects as $post ) { + $location_meta = get_post_meta( $post->ID, null, true ); + + //set serialized empty array if not set + $closed_days = isset( $location_meta['commons-booking_location_closeddays'] ) ? $location_meta['commons-booking_location_closeddays'][0] : 'a:0:{}'; + + $items = []; + + /** + * filters out not preset location categories, if location categories are set + */ + + if ( $preset_location_categories ) { + if ( ! has_term( $preset_location_categories, 'cb_locations_category', $post->ID ) ) { + continue; //skip to next location in loop + } + } + + foreach ( Item::getByLocation( $post->ID, true ) as $item ) { + + $item_terms = wp_get_post_terms( + $item->ID, + \CommonsBooking\Wordpress\CustomPostType\Item::$postType . 's_category' + ); + if ( is_array( $item_terms ) && count( $item_terms ) ) { + $item_terms = array_map( + function ( $item ) { + return $item->term_id; + }, + $item_terms + ); + } + + /** + * If current item has a category, that isn't in map config, we'll skip it. + */ + if ( count( $mapItemTerms ) && count( $item_terms ) && ! count( array_intersect( $item_terms, $mapItemTerms ) ) ) { + continue; + } + + /** + * Filter items by preset item categories + */ + + if ( $preset_categories ) { + //check if preset category is in items + if ( ! has_term( $preset_categories, 'cb_items_category', $item->ID ) ) { + continue; //skip to next item in loop + } + } + + + $timeframesData = []; + $timeframes = Timeframe::getBookableForCurrentUser( + [ $post->ID ], + [ $item->ID ], + null, + true + ); + + /** @var \CommonsBooking\Model\Timeframe $timeframe */ + foreach ( $timeframes as $timeframe ) { + $startDate = date( 'Y-m-d', $timeframe->getStartDate() ); + $endDate = $timeframe->getEndDate() ?: date( 'Y-m-d', strtotime( '2999-01-01' ) ); + $timeframesData[] = [ + 'date_start' => $startDate, + 'date_end' => $endDate + ]; + } + + $thumbnailID = get_post_thumbnail_id( $item->ID ); + //this thumbnail is kept for backwards compatibility + $thumbnail = wp_get_attachment_image_url( $thumbnailID, 'thumbnail' ); + $images = [ + 'thumbnail' => wp_get_attachment_image_src( $thumbnailID, 'thumbnail' ), + 'medium' => wp_get_attachment_image_src( $thumbnailID, 'medium' ), + 'large' => wp_get_attachment_image_src( $thumbnailID, 'large' ), + 'full' => wp_get_attachment_image_src( $thumbnailID, 'full' ), + ]; + $items[] = [ + 'id' => $item->ID, + 'name' => $item->post_title, + 'short_desc' => has_excerpt( $item->ID ) ? wp_strip_all_tags( get_the_excerpt( $item->ID ) ) : "", + 'status' => $item->post_status, + 'terms' => $item_terms, + 'link' => add_query_arg( 'cb-location', $post->ID, get_permalink( $item->ID ) ), + 'thumbnail' => $thumbnail ?: null, + 'images' => $images, + 'timeframes' => $timeframesData + ]; + } + + if ( count( $items ) ) { + $locations[ $post->ID ] = [ + 'lat' => (float) $location_meta['geo_latitude'][0], + 'lon' => (float) $location_meta['geo_longitude'][0], + 'location_name' => $post->post_title, + 'location_link' => get_permalink( $post->ID ), + 'closed_days' => unserialize( $closed_days ), + 'address' => [ + 'street' => $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_street' ][0], + 'city' => $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_city' ][0], + 'zip' => $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_postcode' ][0], + ], + 'items' => $items, + ]; + + if ( $show_location_contact ) { + $locations[ $post->ID ]['contact'] = $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_contact' ][0]; + } + } + + //@TODO: Check field -> we don't have such a field at the moment. +// if ($show_location_opening_hours) { +// $locations[$post->ID]['opening_hours'] = $location_meta['commons-booking_location_openinghours'][0]; +// } + } + + return $locations; + } + + /** + * recursive clean up of location data entries + * + * @param $value + * @param $linebreak_replacement + * + * @return mixed|string|string[]|null + */ + public static function cleanup_location_data_entry( $value, $linebreak_replacement ) { + + if ( is_string( $value ) ) { + $value = preg_replace( '/(\r\n)|\n|\r/', $linebreak_replacement, $value ); //replace linebreaks + $value = preg_replace( '/<.*(.*?)/', '', $value ); //strip off everything that smell's like HTML + } + + if ( is_array( $value ) ) { + foreach ( $value as &$child_value ) { + //recursive call + $child_value = self::cleanup_location_data_entry( $child_value, $linebreak_replacement ); + } + } + + return $value; + } + + /** + * clean up the location data + * + * @param $locations + * @param $linebreak_replacement + * + * @return mixed + */ + public static function cleanup_location_data( $locations, $linebreak_replacement ) { + foreach ( $locations as &$location ) { + $location = self::cleanup_location_data_entry( $location, $linebreak_replacement ); + } + + return $locations; + } + + /** + * basic check if the given string is valid JSON + **/ + public static function is_json( $string ) { + json_decode( $string ); + + return ( json_last_error() == JSON_ERROR_NONE ); + } + + /** + * load all timeframes from db (that end in the future and it's item's status is 'publish') + **/ + public function get_timeframes() { + $timeframes = Timeframe::getBookableForCurrentUser( + [], + [], + false, + true, + Helper::getLastFullHourTimestamp() + ); + + /** @var \CommonsBooking\Model\Timeframe $timeframe */ + foreach ( $timeframes as $timeframe ) { + //TODO #507 + $item = $timeframe->getItem(); + $location = $timeframe->getLocation(); + + if ( $item && $location ) { + $item_desc = $item->getMeta( COMMONSBOOKING_METABOX_PREFIX . 'location_info' ); + $thumbnail = get_the_post_thumbnail_url( $item, 'thumbnail' ); + + $result[] = [ + 'location_id' => $timeframe->getLocationID(), + 'item' => [ + 'id' => $item->ID, + 'name' => $item->post_title, + 'short_desc' => $item_desc, + 'link' => get_permalink( $item ), + 'thumbnail' => $thumbnail ?: null, + 'status' => $item->post_status, + ], + 'date_start' => $timeframe->getStartDate(), + 'date_end' => $timeframe->getEndDate(), + ]; + } + } + return $result; + } } \ No newline at end of file diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index 2adf154bf..b612d0a62 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -4,13 +4,10 @@ namespace CommonsBooking\Wordpress\CustomPostType; -use CommonsBooking\Helper\Helper; use CommonsBooking\Map\MapAdmin; use CommonsBooking\Map\MapSettings; use CommonsBooking\Map\MapShortcode; -use CommonsBooking\Repository\Item; -use CommonsBooking\Repository\Timeframe; -use Exception; + use function __; class Map extends CustomPostType { @@ -20,6 +17,14 @@ class Map extends CustomPostType { */ public static $postType = 'cb_map'; + /** + * The default coordinates of the map center. + * Is used when no other coordinates are set. + * These are currently the coordinates of Cologne, Germany. + */ + const LATITUDE_DEFAULT = 50.937531; + const LONGITUDE_DEFAULT = 6.960279; + /** * Initiates needed hooks. */ @@ -36,267 +41,19 @@ public static function getView() { return new \CommonsBooking\View\Map(); } - /** - * load all timeframes from db (that end in the future and it's item's status is 'publish') - **/ - public static function get_timeframes() { - $timeframes = Timeframe::getBookableForCurrentUser( - [], - [], - false, - true, - Helper::getLastFullHourTimestamp() - ); - - /** @var \CommonsBooking\Model\Timeframe $timeframe */ - foreach ( $timeframes as $timeframe ) { - //TODO #507 - $item = $timeframe->getItem(); - $location = $timeframe->getLocation(); - - if ( $item && $location ) { - $item_desc = $item->getMeta( COMMONSBOOKING_METABOX_PREFIX . 'location_info' ); - $thumbnail = get_the_post_thumbnail_url( $item, 'thumbnail' ); - - $result[] = [ - 'location_id' => $timeframe->getLocationID(), - 'item' => [ - 'id' => $item->ID, - 'name' => $item->post_title, - 'short_desc' => $item_desc, - 'link' => get_permalink( $item ), - 'thumbnail' => $thumbnail ?: null, - 'status' => $item->post_status, - ], - 'date_start' => $timeframe->getStartDate(), - 'date_end' => $timeframe->getEndDate(), - ]; - } - } - - return $result; - } - - /** - * get geo data from location metadata - * - * @param $cb_map_id - * @param $mapItemTerms - * - * @return array - * @throws Exception - */ - public static function get_locations( $cb_map_id, $mapItemTerms ): array { - $locations = []; - - $show_location_contact = MapAdmin::get_option( $cb_map_id, 'show_location_contact' ); - $show_location_opening_hours = MapAdmin::get_option( $cb_map_id, 'show_location_opening_hours' ); - - $preset_categories = MapAdmin::get_option( $cb_map_id, 'cb_items_preset_categories' ); - $preset_location_categories = MapAdmin::get_option( $cb_map_id, 'cb_locations_preset_categories' ); - - - $args = [ - 'post_type' => Location::$postType, - 'posts_per_page' => - 1, - 'post_status' => 'publish', - 'meta_query' => [ - [ - 'key' => 'geo_longitude', - 'meta_compare' => 'EXISTS', - ], - ], - ]; - - $locationObjects = \CommonsBooking\Repository\Location::get( - $args, - true - ); - - /** @var \CommonsBooking\Model\Location $post */ - foreach ( $locationObjects as $post ) { - $location_meta = get_post_meta( $post->ID, null, true ); - - //set serialized empty array if not set - $closed_days = isset( $location_meta['commons-booking_location_closeddays'] ) ? $location_meta['commons-booking_location_closeddays'][0] : 'a:0:{}'; - - $items = []; - - /** - * filters out not preset location categories, if location categories are set - */ - - if ($preset_location_categories) { - if ( !has_term( $preset_location_categories , 'cb_locations_category' , $post->ID) ) { - continue; //skip to next location in loop - } - } - - foreach ( Item::getByLocation( $post->ID, true ) as $item ) { - - $item_terms = wp_get_post_terms( - $item->ID, - \CommonsBooking\Wordpress\CustomPostType\Item::$postType . 's_category' - ); - if ( is_array( $item_terms ) && count( $item_terms ) ) { - $item_terms = array_map( - function ( $item ) { - return $item->term_id; - }, - $item_terms - ); - } - - /** - * If current item has a category, that isn't in map config, we'll skip it. - */ - if ( count( $mapItemTerms ) && count( $item_terms ) && ! count( array_intersect( $item_terms, $mapItemTerms ) ) ) { - continue; - } - - /** - * Filter items by preset item categories - */ - - if ($preset_categories) { - //check if preset category is in items - if ( !has_term( $preset_categories , 'cb_items_category' , $item->ID) ) { - continue; //skip to next item in loop - } - } - - - $timeframesData = []; - $timeframes = Timeframe::getBookableForCurrentUser( - [ $post->ID ], - [ $item->ID ], - null, - true - ); - - /** @var \CommonsBooking\Model\Timeframe $timeframe */ - foreach ( $timeframes as $timeframe ) { - $startDate = date( 'Y-m-d', $timeframe->getStartDate() ); - $endDate = $timeframe->getEndDate() ?: date( 'Y-m-d', strtotime( '2999-01-01' ) ); - $timeframesData[] = [ - 'date_start' => $startDate, - 'date_end' => $endDate - ]; - } - - $thumbnailID = get_post_thumbnail_id( $item->ID ); - //this thumbnail is kept for backwards compatibility - $thumbnail = wp_get_attachment_image_url( $thumbnailID, 'thumbnail' ); - $images = [ - 'thumbnail' => wp_get_attachment_image_src( $thumbnailID, 'thumbnail' ), - 'medium' => wp_get_attachment_image_src( $thumbnailID, 'medium' ), - 'large' => wp_get_attachment_image_src( $thumbnailID, 'large' ), - 'full' => wp_get_attachment_image_src( $thumbnailID, 'full' ), - ]; - $items[] = [ - 'id' => $item->ID, - 'name' => $item->post_title, - 'short_desc' => has_excerpt( $item->ID ) ? wp_strip_all_tags( get_the_excerpt( $item->ID ) ) : "", - 'status' => $item->post_status, - 'terms' => $item_terms, - 'link' => add_query_arg( 'cb-location', $post->ID, get_permalink( $item->ID ) ), - 'thumbnail' => $thumbnail ?: null, - 'images' => $images, - 'timeframes' => $timeframesData - ]; - } - - if ( count( $items ) ) { - $locations[ $post->ID ] = [ - 'lat' => (float) $location_meta['geo_latitude'][0], - 'lon' => (float) $location_meta['geo_longitude'][0], - 'location_name' => $post->post_title, - 'location_link' => get_permalink($post->ID), - 'closed_days' => unserialize( $closed_days ), - 'address' => [ - 'street' => $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_street' ][0], - 'city' => $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_city' ][0], - 'zip' => $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_postcode' ][0], - ], - 'items' => $items, - ]; - - if ( $show_location_contact ) { - $locations[ $post->ID ]['contact'] = $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_contact' ][0]; - } - } - - //@TODO: Check field -> we don't have such a field at the moment. -// if ($show_location_opening_hours) { -// $locations[$post->ID]['opening_hours'] = $location_meta['commons-booking_location_openinghours'][0]; -// } - } - - return $locations; - } - - /** - * basic check if the given string is valid JSON - **/ - public static function is_json( $string ) { - json_decode( $string ); - - return ( json_last_error() == JSON_ERROR_NONE ); - } - - /** - * clean up the location data - * - * @param $locations - * @param $linebreak_replacement - * - * @return mixed - */ - public static function cleanup_location_data( $locations, $linebreak_replacement ) { - foreach ( $locations as &$location ) { - $location = self::cleanup_location_data_entry( $location, $linebreak_replacement ); - } - - return $locations; - } - - /** - * recursive clean up of location data entries - * - * @param $value - * @param $linebreak_replacement - * - * @return mixed|string|string[]|null - */ - public static function cleanup_location_data_entry( $value, $linebreak_replacement ) { - - if ( is_string( $value ) ) { - $value = preg_replace( '/(\r\n)|\n|\r/', $linebreak_replacement, $value ); //replace linebreaks - $value = preg_replace( '/<.*(.*?)/', '', $value ); //strip off everything that smell's like HTML - } - - if ( is_array( $value ) ) { - foreach ( $value as &$child_value ) { - $child_value = self::cleanup_location_data_entry( $child_value, $linebreak_replacement ); - } - } - - return $value; - } - public function getArgs() { $labels = array( - 'name' => self::__( 'Maps', 'commonsbooking' ), - 'singular_name' => self::__( 'Map', 'commonsbooking' ), - 'add_new' => self::__( 'create CB map', 'commonsbooking' ), - 'add_new_item' => self::__( 'create Commons Booking map', 'commonsbooking' ), - 'edit_item' => self::__( 'edit Commons Booking map', 'commonsbooking' ), - 'new_item' => self::__( 'create CB map', 'commonsbooking' ), - 'view_item' => self::__( 'view CB map', 'commonsbooking' ), - 'search_items' => self::__( 'search CB maps', 'commonsbooking' ), - 'not_found' => self::__( 'no Commons Booking map found', 'commonsbooking' ), - 'not_found_in_trash' => self::__( 'no Commons Booking map found in the trash', 'commonsbooking' ), - 'parent_item_colon' => self::__( 'parent CB maps', 'commonsbooking' ), + 'name' => esc_html__( 'Maps', 'commonsbooking' ), + 'singular_name' => esc_html__( 'Map', 'commonsbooking' ), + 'add_new' => esc_html__( 'create CB map', 'commonsbooking' ), + 'add_new_item' => esc_html__( 'create Commons Booking map', 'commonsbooking' ), + 'edit_item' => esc_html__( 'edit Commons Booking map', 'commonsbooking' ), + 'new_item' => esc_html__( 'create CB map', 'commonsbooking' ), + 'view_item' => esc_html__( 'view CB map', 'commonsbooking' ), + 'search_items' => esc_html__( 'search CB maps', 'commonsbooking' ), + 'not_found' => esc_html__( 'no Commons Booking map found', 'commonsbooking' ), + 'not_found_in_trash' => esc_html__( 'no Commons Booking map found in the trash', 'commonsbooking' ), + 'parent_item_colon' => esc_html__( 'parent CB maps', 'commonsbooking' ), ); $supports = array( @@ -310,7 +67,7 @@ public function getArgs() { // Sichtbarkeit des Post Types 'public' => true, - // Standart Ansicht im Backend aktivieren (Wie Artikel / Seiten) + // Standard Ansicht im Backend aktivieren (Wie Artikel / Seiten) 'show_ui' => true, // Soll es im Backend Menu sichtbar sein? @@ -325,7 +82,7 @@ public function getArgs() { // in den Navigations Menüs sichtbar machen? 'show_in_nav_menus' => true, 'hierarchical' => false, - 'description' => self::__( 'Maps to show Commons Booking Locations and their Items', 'commonsbooking' ), + 'description' => esc_html__( 'Maps to show Commons Booking Locations and their Items', 'commonsbooking' ), 'supports' => $supports, 'menu_icon' => 'dashicons-location', 'publicly_queryable' => false, @@ -338,21 +95,4 @@ public function getArgs() { ); } - /** - * @param $text - * @param string $domain - * @param null $default - * - * @return mixed - */ - public static function __( $text, string $domain = 'default', $default = null ) { - - $translation = __( $text, $domain ); - - if ( $translation == $text && isset( $default ) ) { - $translation = $default; - } - - return $translation; - } } From 115afa02df50a7c51e51ae6692587da00c3196bd Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:53:01 +0200 Subject: [PATCH 04/18] MAP -> CMB2: re-implement map settings in CMB2 --- src/Wordpress/CustomPostType/Map.php | 511 ++++++++++++++++++++++++++- 1 file changed, 509 insertions(+), 2 deletions(-) diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index b612d0a62..51fc11230 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -33,8 +33,515 @@ public function initHooks() { add_shortcode( 'cb_map', array( new MapShortcode(), 'execute' ) ); // Add actions - add_action( 'save_post_' . self::$postType, array( MapAdmin::class, 'validate_options' ), 10, 3 ); - add_action( 'add_meta_boxes_cb_map', array( MapAdmin::class, 'add_meta_boxes' ) ); + add_action( 'cmb2_admin_init', array( $this, 'registerMetabox' ) ); + } + + public function registerMetabox() { + $cmb = new_cmb2_box( + [ + 'id' => static::getPostType() . "-custom-fields", + 'title' => esc_html__( 'Map settings', 'commonsbooking' ), + 'object_types' => array( static::getPostType() ), + ] + ); + + + foreach ( self::getCustomFields() as $customField ) { + $cmb->add_field( $customField ); + } + } + + public static function getCustomFields(): array { + return array( + array( + 'name' => esc_html__( 'These settings help you to configure the usage and appearance of Commons Booking Map', 'commonsbooking' ), + 'id' => 'map_settings_info', + 'type' => 'title', + ), + //Begin group presentation + array( + 'name' => esc_html__( 'Presentation', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'presentation_info' + ), + array( + 'name' => esc_html__( 'Shortcode', 'commonsbooking' ), + 'desc' => '[cb_map_id=999]', //TODO: Render callback + 'id' => 'shortcode', + 'type' => 'title', + ), + array( + 'name' => esc_html__( 'base map', 'commonsbooking' ), + 'desc' => esc_html__( 'the base map defines the rendering style of the map tiles', 'commonsbooking' ), + 'id' => 'base_map', + 'type' => 'select', + 'options' => array( + '1' => esc_html__( 'OSM - mapnik', 'commonsbooking' ), + '2' => esc_html__( 'OSM - german style', 'commonsbooking' ), + '3' => esc_html__( 'OSM - hike and bike', 'commonsbooking' ), + '4' => esc_html__( 'OSM - lokaler (min. zoom: 9)', 'commonsbooking' ), + ) + ), + array( + 'name' => esc_html__( 'show scale', 'commonsbooking' ), + 'desc' => esc_html__( 'show the current scale in the bottom left corner of the map', 'commonsbooking' ), + 'id' => 'show_scale', + 'type' => 'checkbox', + ), + array( + 'name' => esc_html__( 'map height', 'commonsbooking' ), + 'desc' => 'px
' . esc_html__( 'the height the map is rendered with - the width is the same as of the parent element', 'commonsbooking' ), + 'id' => 'map_height', + 'type' => 'text_small', + 'default' => '400', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + ) + ), + array( + 'name' => esc_html__( 'no locations message', 'commonsbooking' ), + 'desc' => esc_html__( 'in case a user filters locations and gets no result, a message is shown - here the text can be customized', 'commonsbooking' ), + 'id' => 'custom_no_locations_message', + 'type' => 'text', + 'default' => esc_html__( 'No locations found', 'commonsbooking' ), + ), + array( + 'name' => esc_html__( 'enable data export', 'commonsbooking' ), + 'desc' => esc_html__( 'activate to enable a button that allows the export of map data (geojson format)', 'commonsbooking' ), + 'id' => 'enable_map_data_export', + 'type' => 'checkbox', + ), + //Begin group Zoom + array( + 'name' => esc_html__( 'Zoom', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'zoom_info' + ), + array( + 'name' => esc_html__( 'min. zoom level', 'commonsbooking' ), + 'desc' => esc_html__( 'the minimal zoom level a user can choose', 'commonsbooking' ), + 'id' => 'zoom_min', + 'type' => 'text_small', + 'default' => '9', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + 'max' => '19', + ) + ), + array( + 'name' => esc_html__( 'max. zoom level', 'commonsbooking' ), + 'desc' => esc_html__( 'the maximal zoom level a user can choose', 'commonsbooking' ), + 'id' => 'zoom_max', + 'type' => 'text_small', + 'default' => '19', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + 'max' => '19', + ) + ), + array( + 'name' => esc_html__( 'start zoom level', 'commonsbooking' ), + 'desc' => esc_html__( 'the zoom level that will be set when the map is loaded', 'commonsbooking' ), + 'id' => 'zoom_start', + 'type' => 'text_small', + 'default' => '9', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + 'max' => '19', + ) + ), + array( + 'name' => esc_html__( 'enable scroll wheel zoom', 'commonsbooking' ), + 'desc' => esc_html__( 'when activated users can zoom the map using the scroll wheel', 'commonsbooking' ), + 'id' => 'scrollWheelZoom', + 'type' => 'checkbox', + 'default_cb' => 'commonsbooking_cmb2_set_checkbox_default_for_new_post', + ), + //End group Zoom + //Begin group Positioning + array( + 'name' => esc_html__( 'Positioning', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'positioning_info' + ), + array( + 'name' => esc_html__( 'start latitude', 'commonsbooking' ), + 'desc' => esc_html__( 'the latitude of the map center when the map is loaded', 'commonsbooking' ), + 'id' => 'lat_start', + 'type' => 'text_small', + 'default' => self::LATITUDE_DEFAULT, + ), + array( + 'name' => esc_html__( 'start longitude', 'commonsbooking' ), + 'desc' => esc_html__( 'the longitude of the map center when the map is loaded', 'commonsbooking' ), + 'id' => 'lon_start', + 'type' => 'text_small', + 'default' => self::LONGITUDE_DEFAULT, + ), + array( + 'name' => esc_html__( 'initial adjustment to marker bounds', 'commonsbooking' ), + 'desc' => esc_html__( 'adjust map section to bounds of shown markers automatically when map is loaded', 'commonsbooking' ), + 'id' => 'marker_map_bounds_initial', + 'type' => 'checkbox', + 'default_cb' => 'commonsbooking_cmb2_set_checkbox_default_for_new_post', + ), + array( + 'name' => esc_html__( 'adjustment to marker bounds on filter', 'commonsbooking' ), + 'desc' => esc_html__( 'adjust map section to bounds of shown markers automatically when filtered by users', 'commonsbooking' ), + 'id' => 'marker_map_bounds_filter', + 'type' => 'checkbox', + 'default_cb' => 'commonsbooking_cmb2_set_checkbox_default_for_new_post', + ), + //End group Positioning + //Begin group Tooltip + array( + 'name' => esc_html__( 'Marker Tooltip', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'marker_tooltip_info' + ), + array( + 'name' => esc_html__( 'Show marker tooltip permanently', 'commonsbooking' ), + 'desc' => esc_html__( 'activate to show the marker tooltips permanently', 'commonsbooking' ), + 'id' => 'marker_tooltip_permanent', + 'type' => 'checkbox', + ), + //End group Tooltip + //Begin group popup + array( + 'name' => esc_html__( 'Marker Popup', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'marker_popup_info' + ), + array( + 'name' => esc_html__( 'show item availability', 'commonsbooking' ), + 'desc' => esc_html__( 'activate to show the item availability in the marker popup', 'commonsbooking' ), + 'id' => 'show_item_availability', + 'type' => 'checkbox' + ), + array( + 'name' => esc_html__( 'Max. available days in popup', 'commonsbooking' ), + 'desc' => esc_html__( 'Set how many days are displayed on the popup (starting from today)', 'commonsbooking' ), + 'id' => 'availability_max_days_to_show', + 'type' => 'text_small', + 'default' => '11', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + ) + ), + array( + 'name' => esc_html__( 'Maximum days to choose in map availabilty filter ', 'commonsbooking' ), + 'desc' => esc_html__( 'Notice: Defines the maximun days a user can choose in the availabilty filter in frontend map', 'commonsbooking' ), + 'id' => 'availability_max_day_count', + 'default' => '14', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + ) + ), + //End group popup + //Begin group custom marker + array( + 'name' => esc_html__( 'Custom Marker', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'custom_marker_info' + ), + array( + 'name' => esc_html__( 'image file', 'commonsbooking' ), + 'desc' => esc_html__( 'the default marker icon can be replaced by a custom image', 'commonsbooking' ), + 'id' => 'custom_marker_media', + 'type' => 'file', + 'options' => array( + 'url' => false, + ), + 'query_args' => array( + 'type' => array( + 'image/png', + ), + ), + ), + array( + 'name' => esc_html__( 'icon width', 'commonsbooking' ), + 'desc' => 'px ' . esc_html__( 'the size of the custom marker icon image as it is shown on the map', 'commonsbooking' ), + 'id' => 'marker_icon_width', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + ), + ), + array( + 'name' => esc_html__( 'icon height', 'commonsbooking' ), + 'desc' => 'px ' . esc_html__( 'the size of the custom marker icon image as it is shown on the map', 'commonsbooking' ), + 'id' => 'marker_icon_height', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + ), + ), + array( + 'name' => esc_html__( 'anchor point', 'commonsbooking' ) . ' x', + 'desc' => 'px ' . esc_html__( 'the position of the anchor point of the icon image, seen from the left top corner of the icon, often it is half of the width and full height of the icon size - this point is used to place the marker on the geo coordinates', 'commonsbooking' ), + 'id' => 'marker_icon_anchor_x', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + ), + ), + array( + 'name' => esc_html__( 'anchor point', 'commonsbooking' ) . ' y', + 'desc' => 'px ' . esc_html__( 'the position of the anchor point of the icon image, seen from the left top corner of the icon, often it is half of the width and full height of the icon size - this point is used to place the marker on the geo coordinates', 'commonsbooking' ), + 'id' => 'marker_icon_anchor_y', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + ), + ), + //End group custom marker + //Begin group cluster + array( + 'name' => esc_html__( 'Cluster', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'cluster_info' + ), + array( + 'name' => esc_html__( 'max. cluster radius', 'commonsbooking' ), + 'desc' => 'px ' . esc_html__( 'combine markers to a cluster within given radius - 0 for deactivation', 'commonsbooking' ), + 'id' => 'max_cluster_radius', + 'type' => 'text_small', + 'default' => '80', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => 0, + 'max' => 1000 + ), + ), + array( + 'name' => esc_html__( 'Custom Cluster Marker', 'commonsbooking' ), + 'desc' => esc_html__( 'the default marker icon can be replaced by a custom image', 'commonsbooking' ), + 'id' => 'custom_marker_cluster_media', + 'type' => 'file', + 'options' => array( + 'url' => false, + ), + 'query_args' => array( + 'type' => array( + 'image/png', + ), + ), + ), + array( + 'name' => esc_html__( 'icon width', 'commonsbooking' ), + 'desc' => 'px ' . esc_html__( 'the size of the custom marker icon image as it is shown on the map', 'commonsbooking' ), + 'id' => 'marker_cluster_icon_width', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + ), + ), + array( + 'name' => esc_html__( 'icon height', 'commonsbooking' ), + 'desc' => 'px ' . esc_html__( 'the size of the custom marker icon image as it is shown on the map', 'commonsbooking' ), + 'id' => 'marker_cluster_icon_height', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + ), + ), + //End group cluster + //Begin group Appearance + array( + 'name' => esc_html__( 'Appearance by Item Status', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'item_status_appearance_info' + ), + array( + 'name' => esc_html__( 'appearance', 'commonsbooking' ), + 'desc' => esc_html__( 'how locations with items that are in draft status should be handled', 'commonsbooking' ), + 'id' => 'item_draft_appearance', + 'type' => 'radio', + 'options' => array( + '1' => esc_html__( "don't show drafts", 'commonsbooking' ), + '2' => esc_html__( 'show only drafts', 'commonsbooking' ), + '3' => esc_html__( 'show all together', 'commonsbooking' ), + ), + 'default' => '1', + ), + array( + 'name' => esc_html__( 'Custom Item Draft Marker', 'commonsbooking' ), + 'desc' => esc_html__( 'the default marker icon can be replaced by a custom image', 'commonsbooking' ), + 'id' => 'marker_item_draft_media', + 'type' => 'file', + 'options' => array( + 'url' => false, + ), + 'query_args' => array( + 'type' => array( + 'image/png', + ), + ), + ), + array( + 'name' => esc_html__( 'icon width', 'commonsbooking' ), + 'desc' => 'px ' . esc_html__( 'the size of the custom marker icon image as it is shown on the map', 'commonsbooking' ), + 'id' => 'marker_item_draft_icon_width', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + ), + ), + array( + 'name' => esc_html__( 'icon height', 'commonsbooking' ), + 'desc' => 'px ' . esc_html__( 'the size of the custom marker icon image as it is shown on the map', 'commonsbooking' ), + 'id' => 'marker_item_draft_icon_height', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + 'min' => '1', + ), + ), + array( + 'name' => esc_html__( 'anchor point', 'commonsbooking' ) . ' x', + 'desc' => 'px ' . esc_html__( 'the position of the anchor point of the icon image, seen from the left top corner of the icon, often it is half of the width and full height of the icon size - this point is used to place the marker on the geo coordinates', 'commonsbooking' ), + 'id' => 'marker_item_draft_icon_anchor_x', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + ), + ), + array( + 'name' => esc_html__( 'anchor point', 'commonsbooking' ) . ' y', + 'desc' => 'px ' . esc_html__( 'the position of the anchor point of the icon image, seen from the left top corner of the icon, often it is half of the width and full height of the icon size - this point is used to place the marker on the geo coordinates', 'commonsbooking' ), + 'id' => 'marker_item_draft_icon_anchor_y', + 'type' => 'text_small', + 'attributes' => array( + 'type' => 'number', + 'pattern' => '\d*', + ), + ), + //End group Appearance + //Begin group Filters + array( + 'name' => esc_html__( 'Filter for Users', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'filter_info' + ), + array( + 'name' => esc_html__( 'show location distance filter', 'commonsbooking' ), + 'desc' => esc_html__( 'activate to show the location distance filter', 'commonsbooking' ), + 'id' => 'show_location_distance_filter', + 'type' => 'checkbox', + ), + array( + 'name' => esc_html__( 'label for location distance filter', 'commonsbooking' ), + 'desc' => esc_html__( 'alternative label for the location distance filter', 'commonsbooking' ), + 'id' => 'label_location_distance_filter', + 'type' => 'text', + 'attributes' => array( + 'placeholder' => esc_html__( 'distance', 'commonsbooking' ), + ) + ), + array( + 'name' => esc_html__( 'address search bounds - left bottom', 'commonsbooking' ) . ' ' . esc_html__( 'longitude', 'commonsbooking' ), + 'desc' => esc_html__( 'defines the bounds of the address search - set the longitude of the left bottom corner of the bounding box', 'commonsbooking' ), + 'id' => 'address_search_bounds_left_bottom_lon', + 'type' => 'text_small', + ), + array( + 'name' => esc_html__( 'address search bounds - left bottom', 'commonsbooking' ) . ' ' . esc_html__( 'latitude', 'commonsbooking' ), + 'desc' => esc_html__( 'defines the bounds of the address search - set the bottom left corner of the bounding box', 'commonsbooking' ), + 'id' => 'address_search_bounds_left_bottom_lat', + 'type' => 'text_small', + ), + array( + 'name' => esc_html__( 'address search bounds - right top', 'commonsbooking' ) . ' ' . esc_html__( 'longitude', 'commonsbooking' ), + 'desc' => esc_html__( 'defines the bounds of the address search - set the longitude of the right top corner of the bounding box', 'commonsbooking' ), + 'id' => 'address_search_bounds_right_top_lon', + 'type' => 'text_small', + ), + array( + 'name' => esc_html__( 'address search bounds - right top', 'commonsbooking' ) . ' ' . esc_html__( 'latitude', 'commonsbooking' ), + 'desc' => esc_html__( 'defines the bounds of the address search - set the latitude of the right top corner of the bounding box', 'commonsbooking' ), + 'id' => 'address_search_bounds_right_top_lat', + 'type' => 'text_small', + ), + array( + 'name' => esc_html__( 'show item availability filter', 'commonsbooking' ), + 'desc' => esc_html__( 'activate to show the item availability filter', 'commonsbooking' ), + 'id' => 'show_item_availability_filter', + 'type' => 'checkbox', + ), + array( + 'name' => esc_html__( 'label for item availability filter', 'commonsbooking' ), + 'desc' => esc_html__( 'alternative label for the item availability filter', 'commonsbooking' ), + 'id' => 'label_item_availability_filter', + 'type' => 'text', + 'attributes' => array( + 'placeholder' => esc_html__( 'availability', 'commonsbooking' ), + ) + ), + array( + 'name' => esc_html__( 'label for item category filter', 'commonsbooking' ), + 'desc' => esc_html__( 'alternative label for the item category filter', 'commonsbooking' ), + 'id' => 'label_item_category_filter', + 'type' => 'text', + 'attributes' => array( + 'placeholder' => esc_html__( 'categories', 'commonsbooking' ), + ) + ), + array( + 'name' => esc_html__( 'custom text for filter button', 'commonsbooking' ), + 'desc' => esc_html__( 'the text for the button used for filtering', 'commonsbooking' ), + 'id' => 'custom_filterbutton_label', + 'type' => 'text', + 'attributes' => array( + 'placeholder' => esc_html__( 'filter', 'commonsbooking' ), + ) + ), + //TODO: Add available categories & filtergroups + //End group Filters + //Begin group Presets + array( + 'name' => esc_html__( 'Filter Item Presets', 'commonsbooking' ), + 'desc' => esc_html__( 'select the categories that are used to prefilter the items that are shown on the map - none for all items', 'commonsbooking' ), + 'id' => 'cb_items_preset_categories', + 'type' => 'multicheck', + 'options' => CustomPostType::sanitizeOptions( Item::getTerms() ), + 'select_all_button' => false, + ), + array( + 'name' => esc_html__( 'Filter Location Presets', 'commonsbooking' ), + 'desc' => esc_html__( 'select the categories that are used to prefilter the locations that are shown on the map - none for all locations', 'commonsbooking' ), + 'id' => 'cb_locations_preset_categories', + 'type' => 'multicheck', + 'options' => CustomPostType::sanitizeOptions( Location::getTerms() ), + 'select_all_button' => false, + ), + //End group Presets + ); } public static function getView() { From b20cef19314fd1bcaa57e588675e9f949c981149 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:53:18 +0200 Subject: [PATCH 05/18] MAP -> CMB2: remove now redundant classes --- assets/map/js/cb-map-marker-upload.js | 169 ------ src/Map/MapAdmin.php | 550 ------------------ src/Map/MapSettings.php | 114 ---- src/View/Map.php | 5 +- templates/map-admin-page-template.php | 789 -------------------------- 5 files changed, 2 insertions(+), 1625 deletions(-) delete mode 100644 assets/map/js/cb-map-marker-upload.js delete mode 100644 src/Map/MapAdmin.php delete mode 100644 src/Map/MapSettings.php delete mode 100644 templates/map-admin-page-template.php diff --git a/assets/map/js/cb-map-marker-upload.js b/assets/map/js/cb-map-marker-upload.js deleted file mode 100644 index 4aa92e5e6..000000000 --- a/assets/map/js/cb-map-marker-upload.js +++ /dev/null @@ -1,169 +0,0 @@ -var cb_map_marker_upload = { - translation: {}, - - //based on: https://jeroensormani.com/how-to-include-the-wordpress-media-selector-in-your-plugin/ - init: function($, data) { - // uploading files - var file_frame; - var wp_media_post_id = wp.media.model.settings.post.id; // Store the old id - var set_to_post_id = data.$custom_marker_media_id.val(); - - data.$remove_image_button.on('click', function(event) { - event.preventDefault(); - - data.$custom_marker_media_id.val(''); - data.$image_preview.attr('src', ''); - - data.$marker_icon_width.val(0); - data.$marker_icon_height.val(0); - data.$marker_icon_anchor_x.val(0); - data.$marker_icon_anchor_y.val(0); - - data.$image_preview_settings.hide(); - data.$image_preview_measurements.text(''); - data.$marker_icon_size.hide(); - data.$marker_icon_anchor.hide(); - - }); - - data.$select_image_button.on('click', function(event) { - - event.preventDefault(); - // if the media frame already exists, reopen it. - if ( file_frame ) { - // Set the post ID to what we want - file_frame.uploader.uploader.param( 'post_id', set_to_post_id ); - // Open frame - file_frame.open(); - return; - - } else { - // set the wp.media post id so the uploader grabs the ID we want when initialised - wp.media.model.settings.post.id = set_to_post_id; - } - - // create the media frame - file_frame = wp.media.frames.file_frame = wp.media({ - title: cb_map_marker_upload.translation.SELECT_IMAGE, - button: { - text: cb_map_marker_upload.translation.SAVE, - }, - multiple: false - }); - - // image select callback - file_frame.on( 'select', function() { - var attachment = file_frame.state().get('selection').first().toJSON(); - - // Do something with attachment.id and/or attachment.url here - data.$image_preview.attr( 'src', attachment.url ).css( 'width', 'auto' ); - data.$custom_marker_media_id.val( attachment.id ); - // restore the main post ID - wp.media.model.settings.post.id = wp_media_post_id; - - data.$marker_icon_width.val(0); - data.$marker_icon_height.val(0); - data.$marker_icon_anchor_x.val(0); - data.$marker_icon_anchor_y.val(0); - }); - - // finally, open the modal - file_frame.open(); - }); - - // restore the main ID when the add media button is pressed - $( 'a.add_media' ).on( 'click', function() { - wp.media.model.settings.post.id = wp_media_post_id; - }); - - data.$image_preview.on('load', function() { - - data.$image_preview_settings.show(); - data.$image_preview_measurements.text(cb_map_marker_upload.translation.MARKER_IMAGE_MEASUREMENTS + ': ' + data.$image_preview.width() + ' x ' + data.$image_preview.height() + ' px'); - data.$marker_icon_size.show(); - data.$marker_icon_anchor.show(); - - if(data.$marker_icon_width.val() == 0) { - data.$marker_icon_width.val(data.$image_preview.width()); - } - - if(data.$marker_icon_height.val() == 0) { - data.$marker_icon_height.val(data.$image_preview.height()); - } - - if(data.$marker_icon_anchor_x.val() == 0) { - data.$marker_icon_anchor_x.val(data.$image_preview.width() / 2); - } - - if(data.$marker_icon_anchor_y.val() == 0) { - data.$marker_icon_anchor_y.val(data.$image_preview.height()); - } - - }); - - //if parent details got opened, trigger load for cached images - var $parent_details = data.$image_preview.closest('details'); - $parent_details.on('toggle', function() { - var src = data.$image_preview.attr('src'); - if($parent_details.prop('open') == true && src.length > 0) { - setTimeout(function() { - data.$image_preview.load(); - }, 0); - } - }); - } -} - -jQuery(document).ready(function($) { - - var marker_data = { - $select_image_button: $('#select-marker-image-button'), - $remove_image_button: $('#remove-marker-image-button'), - $custom_marker_media_id: $('input[name="cb_map_options[custom_marker_media_id]"'), - $image_preview: $('#marker-image-preview'), - $marker_icon_width: $('input[name="cb_map_options[marker_icon_width]"'), - $marker_icon_height: $('input[name="cb_map_options[marker_icon_height]"'), - $marker_icon_anchor_x: $('input[name="cb_map_options[marker_icon_anchor_x]"'), - $marker_icon_anchor_y: $('input[name="cb_map_options[marker_icon_anchor_y]"'), - $image_preview_settings: $('#marker-image-preview-settings'), - $image_preview_measurements: $('#marker-image-preview-measurements'), - $marker_icon_size: $('#marker-icon-size'), - $marker_icon_anchor: $('#marker-icon-anchor') - }; - - cb_map_marker_upload.init($, marker_data); - - var marker_cluster_data = { - $select_image_button: $('#select-marker-cluster-image-button'), - $remove_image_button: $('#remove-marker-cluster-image-button'), - $custom_marker_media_id: $('input[name="cb_map_options[custom_marker_cluster_media_id]"'), - $image_preview: $('#marker-cluster-image-preview'), - $marker_icon_width: $('input[name="cb_map_options[marker_cluster_icon_width]"'), - $marker_icon_height: $('input[name="cb_map_options[marker_cluster_icon_height]"'), - $marker_icon_anchor_x: $('input[name="cb_map_options[marker_cluster_icon_anchor_x]"'), - $marker_icon_anchor_y: $('input[name="cb_map_options[marker_cluster_icon_anchor_y]"'), - $image_preview_settings: $('#marker-cluster-image-preview-settings'), - $image_preview_measurements: $('#marker-cluster-image-preview-measurements'), - $marker_icon_size: $('#marker-cluster-icon-size'), - $marker_icon_anchor: $('#marker-cluster-icon-anchor') - }; - - cb_map_marker_upload.init($, marker_cluster_data); - - var marker_item_draft_data = { - $select_image_button: $('#select-marker-item-draft-image-button'), - $remove_image_button: $('#remove-marker-item-draft-image-button'), - $custom_marker_media_id: $('input[name="cb_map_options[marker_item_draft_media_id]"'), - $image_preview: $('#marker-item-draft-image-preview'), - $marker_icon_width: $('input[name="cb_map_options[marker_item_draft_icon_width]"'), - $marker_icon_height: $('input[name="cb_map_options[marker_item_draft_icon_height]"'), - $marker_icon_anchor_x: $('input[name="cb_map_options[marker_item_draft_icon_anchor_x]"'), - $marker_icon_anchor_y: $('input[name="cb_map_options[marker_item_draft_icon_anchor_y]"'), - $image_preview_settings: $('#marker-item-draft-image-preview-settings'), - $image_preview_measurements: $('#marker-item-draft-image-preview-measurements'), - $marker_icon_size: $('#marker-item-draft-icon-size'), - $marker_icon_anchor: $('#marker-item-draft-icon-anchor') - }; - - cb_map_marker_upload.init($, marker_item_draft_data); -}); diff --git a/src/Map/MapAdmin.php b/src/Map/MapAdmin.php deleted file mode 100644 index a8404aeb1..000000000 --- a/src/Map/MapAdmin.php +++ /dev/null @@ -1,550 +0,0 @@ -' + location.location_name + '
' + location.address.street + '
' + location.address.zip + ' ' + location.address.city + '

' + location.opening_hours + '

'"; - - public static $options; - - public static function add_meta_boxes() { - self::add_settings_meta_box( - 'cb_map_admin', - esc_html__( 'Map Configuration', 'commonsbooking' ) ); - } - - public static function add_settings_meta_box( $meta_box_id, $meta_box_title ) { - $plugin_prefix = 'cb_map_post_type_'; - - $html_id_attribute = $plugin_prefix . $meta_box_id . '_meta_box'; - $callback = array( MapAdmin::class, 'render_options_page' ); - $show_on_post_type = 'cb_map'; - $box_placement = 'normal'; - $box_priority = 'high'; - - add_meta_box( - $html_id_attribute, - $meta_box_title, - $callback, - $show_on_post_type, - $box_placement, - $box_priority - ); - } - - /** - * - **/ - public static function get_options( $cb_map_id = null, $force_reload = false ) { - self::load_options( $cb_map_id, $force_reload ); - - return self::$options; - } - - public static function load_options( $cb_map_id = null, $force_reload = false ) { - if ( ! isset( self::$options ) || $force_reload ) { - if ( $cb_map_id ) { - $options = get_post_meta( $cb_map_id, 'cb_map_options', true ); - - if ( ! is_array( $options ) ) { - $options = []; - } - } else { - $options = []; - } - - self::$options = self::populate_option_defaults( $options ); - } - } - - public static function populate_option_defaults( $options ) { - foreach ( self::OPTION_KEYS as $key ) { - if ( ! isset( $options[ $key ] ) ) { - $options[ $key ] = self::get_option_default( $key ); - } - } - - return $options; - } - - private static function get_option_default( $option_name ) { - $default_name = strtoupper( $option_name ) . '_DEFAULT'; - $const_value = constant( "self::$default_name" ); - - return $const_value ?? null; - } - - /** - * sanitize and validate the options provided by input array - **/ - public static function validate_options( $cb_map_id ) { - self::load_options( $cb_map_id ); - - $validated_input = self::populate_option_defaults( [] ); - - $input = []; - if ( isset( $_POST['cb_map_options'] ) ) { - $input = commonsbooking_sanitizeArrayorString( $_POST['cb_map_options'] ); - } - - //base_map - if ( isset( $input['base_map'] ) && $input['base_map'] >= 1 && $input['base_map'] <= 4 ) { - $validated_input['base_map'] = (int) $input['base_map']; - } - - //map_height - if ( isset( $input['map_height'] ) && (int) $input['map_height'] >= self::MAP_HEIGHT_VALUE_MIN && $input['map_height'] <= self::MAP_HEIGHT_VALUE_MAX ) { - $validated_input['map_height'] = (int) $input['map_height']; - } - - //custom_no_locations_message - if ( isset( $input['custom_no_locations_message'] ) ) { - $validated_input['custom_no_locations_message'] = sanitize_text_field( $input['custom_no_locations_message'] ); - } - - //zoom_min - if ( isset( $input['zoom_min'] ) && (int) $input['zoom_min'] >= self::ZOOM_VALUE_MIN && $input['zoom_min'] <= self::ZOOM_VALUE_MAX ) { - $validated_input['zoom_min'] = (int) $input['zoom_min']; - } - - //zoom_max - if ( isset( $input['zoom_max'] ) && (int) $input['zoom_max'] >= self::ZOOM_VALUE_MIN && $input['zoom_max'] <= self::ZOOM_VALUE_MAX ) { - if ( (int) $input['zoom_max'] >= $validated_input['zoom_min'] ) { - $validated_input['zoom_max'] = (int) $input['zoom_max']; - } else { - $validated_input['zoom_max'] = $validated_input['zoom_min']; - } - } - - //zoom_start - if ( isset( $input['zoom_start'] ) && (int) $input['zoom_start'] >= self::ZOOM_VALUE_MIN && $input['zoom_start'] <= self::ZOOM_VALUE_MAX ) { - if ( (int) $input['zoom_start'] >= $validated_input['zoom_min'] && (int) $input['zoom_start'] <= $validated_input['zoom_max'] ) { - $validated_input['zoom_start'] = (int) $input['zoom_start']; - } else { - $validated_input['zoom_start'] = $validated_input['zoom_min']; - } - } - - //lat_start - if ( self::validateStringInput( $input, 'lat_start' ) && (float) $input['lat_start'] >= self::LAT_VALUE_MIN && (float) $input['lat_start'] <= self::LAT_VALUE_MAX ) { - $validated_input['lat_start'] = (float) $input['lat_start']; - } - - //lon_start - if ( self::validateStringInput( $input, 'lon_start' ) && (float) $input['lon_start'] >= self::LON_VALUE_MIN && (float) $input['lon_start'] <= self::LON_VALUE_MAX ) { - $validated_input['lon_start'] = (float) $input['lon_start']; - } - - //max_cluster_radius - if ( isset( $input['max_cluster_radius'] ) && (int) $input['max_cluster_radius'] >= self::MAX_CLUSTER_RADIUS_VALUE_MIN && $input['max_cluster_radius'] <= self::MAX_CLUSTER_RADIUS_VALUE_MAX ) { - $validated_input['max_cluster_radius'] = (int) $input['max_cluster_radius']; - } - - $checkboxInputs = [ - 'show_scale', - 'marker_map_bounds_initial', - 'marker_map_bounds_filter', - 'marker_tooltip_permanent', - 'show_location_contact', - 'show_location_opening_hours', - 'show_item_availability', - 'show_location_distance_filter', - 'scrollWheelZoom' - ]; - - foreach ( $checkboxInputs as $checkboxInput ) { - $validated_input[ $checkboxInput ] = self::validateCheckboxInput( $input, $checkboxInput ); - } - - $integerInputs = [ - 'custom_marker_media_id', - 'custom_marker_cluster_media_id', - 'marker_item_draft_media_id', - 'availability_max_days_to_show', - 'availability_max_day_count', - ]; - - foreach ( $integerInputs as $integerInput ) { - if ( isset( $input[ $integerInput ] ) ) { - $validated_input[ $integerInput ] = abs( (int) $input[ $integerInput ] ); - } - } - - $floatInputs = [ - 'marker_icon_width', - 'marker_icon_height', - 'marker_icon_anchor_x', - 'marker_icon_anchor_y', - 'marker_cluster_icon_width', - 'marker_cluster_icon_height', - 'marker_item_draft_icon_width', - 'marker_item_draft_icon_height', - 'marker_item_draft_icon_anchor_x', - 'marker_item_draft_icon_anchor_y' - ]; - - foreach ( $floatInputs as $floatInput ) { - if ( isset( $input[ $floatInput ] ) ) { - $validated_input[ $floatInput ] = (float) $input[ $floatInput ]; - } - } - - //label_location_opening_hours - if ( self::validateStringInput( $input, 'label_location_opening_hours' ) ) { - $validated_input['label_location_opening_hours'] = sanitize_text_field( $input['label_location_opening_hours'] ); - } - - - //label_location_contact - if ( self::validateStringInput( $input, 'label_location_contact' ) ) { - $validated_input['label_location_contact'] = sanitize_text_field( $input['label_location_contact'] ); - } - - - //item_draft_appearance - if ( isset( $input['item_draft_appearance'] ) && $input['item_draft_appearance'] >= 1 && $input['item_draft_appearance'] <= 3 ) { - $validated_input['item_draft_appearance'] = $input['item_draft_appearance']; - } - - - //address_search_bounds_left_bottom_lat - if ( self::validateStringInput( $input, 'address_search_bounds_left_bottom_lat' ) && (float) $input['address_search_bounds_left_bottom_lat'] >= self::LAT_VALUE_MIN && (float) $input['address_search_bounds_left_bottom_lat'] <= self::LAT_VALUE_MAX ) { - $validated_input['address_search_bounds_left_bottom_lat'] = (float) $input['address_search_bounds_left_bottom_lat']; - } - - if ( self::validateStringInput( $input, 'address_search_bounds_left_bottom_lon' ) && (float) $input['address_search_bounds_left_bottom_lon'] >= self::LON_VALUE_MIN && (float) $input['address_search_bounds_left_bottom_lon'] <= self::LON_VALUE_MAX ) { - $validated_input['address_search_bounds_left_bottom_lon'] = (float) $input['address_search_bounds_left_bottom_lon']; - } - - //address_search_bounds_right_top_lat - if ( self::validateStringInput( $input, 'address_search_bounds_right_top_lat' ) && (float) $input['address_search_bounds_right_top_lat'] >= self::LAT_VALUE_MIN && (float) $input['address_search_bounds_right_top_lat'] <= self::LAT_VALUE_MAX ) { - $validated_input['address_search_bounds_right_top_lat'] = (float) $input['address_search_bounds_right_top_lat']; - } - - //address_search_bounds_right_top_lon - if ( self::validateStringInput( $input, 'address_search_bounds_right_top_lon' ) && (float) $input['address_search_bounds_right_top_lon'] >= self::LON_VALUE_MIN && (float) $input['address_search_bounds_right_top_lon'] <= self::LON_VALUE_MAX ) { - $validated_input['address_search_bounds_right_top_lon'] = (float) $input['address_search_bounds_right_top_lon']; - } - - //label_location_distance_filter - if ( self::validateStringInput( $input, 'label_location_distance_filter' ) ) { - $validated_input['label_location_distance_filter'] = sanitize_text_field( $input['label_location_distance_filter'] ); - } - - //show_item_availability_filter - if ( isset( $input['show_item_availability_filter'] ) ) { - $validated_input['show_item_availability_filter'] = true; - } else { - $validated_input['show_item_availability_filter'] = false; - } - - //label_item_availability_filter - if ( self::validateStringInput( $input, 'label_item_availability_filter' ) ) { - $validated_input['label_item_availability_filter'] = sanitize_text_field( $input['label_item_availability_filter'] ); - } - - //label_item_category_filter - if ( self::validateStringInput( $input, 'label_item_category_filter' ) ) { - $validated_input['label_item_category_filter'] = sanitize_text_field( $input['label_item_category_filter'] ); - } - - - //custom_filterbutton_label - if ( isset( $input['custom_filterbutton_label'] ) ) { - $validated_input['custom_filterbutton_label'] = sanitize_text_field( $input['custom_filterbutton_label'] ); - } - - //cb_items_available_categories - $category_terms = \CommonsBooking\Repository\Item::getTerms(); - $valid_term_ids = []; - foreach ( $category_terms as $category_term ) { - $valid_term_ids[] = $category_term->term_id; - } - - $loc_category_terms = \CommonsBooking\Repository\Item::getTerms(); - - $valid_loc_term_ids = []; - foreach ( $loc_category_terms as $loc_category_term ) { - $valid_loc_term_ids[] = $loc_category_term->term_id; - } - - if ( isset( $input['cb_items_available_categories'] ) ) { - //first element has to be a filter group and has to contain at least one category - $array_keys = array_keys( $input['cb_items_available_categories'] ); - if ( count( $input['cb_items_available_categories'] ) > 1 && substr( $array_keys[0], 0, - 1 ) == 'g' && substr( $array_keys[1], 0, 1 ) != 'g' ) { - foreach ( $input['cb_items_available_categories'] as $key => $value ) { - //filter group - if ( substr( $key, 0, 1 ) == 'g' ) { - $validated_input['cb_items_available_categories'][ $key ] = sanitize_text_field( $value ); - } //custom markup for category - else { - if ( in_array( (int) $key, $valid_term_ids ) ) { - $validated_input['cb_items_available_categories'][ $key ] = self::strip_script_tags( $value ); - } - } - } - } - } - - //cb_items_preset_categories - if ( isset( $input['cb_items_preset_categories'] ) ) { - foreach ( $input['cb_items_preset_categories'] as $cb_items_category_id ) { - if ( in_array( (int) $cb_items_category_id, $valid_term_ids ) ) { - $validated_input['cb_items_preset_categories'][] = $cb_items_category_id; - } - } - } - - if ( isset( $input['cb_locations_preset_categories'] ) ) { - foreach ( $input['cb_locations_preset_categories'] as $cb_locations_category_id ) { - if ( in_array( (int) $cb_locations_category_id, $valid_loc_term_ids ) ) { - $validated_input['cb_locations_preset_categories'][] = $cb_locations_category_id; - } - } - } - - - update_post_meta( $cb_map_id, 'cb_map_options', $validated_input ); - - return $validated_input; - } - - /** - * @param $input - * @param $key - * - * @return bool - */ - protected static function validateStringInput( $input, $key ): bool { - return isset( $input[ $key ] ) && strlen( $input[ $key ] ) > 0; - } - - /** - * @param $input - * @param $key - * - * @return bool - */ - protected static function validateCheckboxInput( $input, $key ): bool { - return isset( $input[ $key ] ); - } - - public static function strip_script_tags( $input ) { - return preg_replace( '/]*>(.*?)<\/script>/is', '', $input ); - } - - - public static function render_options_page( $post ) { - $cb_map_id = $post->ID; - - wp_enqueue_media(); - - // info: upload script is enqueued in includes/Admin.php - - //map translation - $translation = [ - 'SELECT_IMAGE' => esc_html__( 'Select an image', 'commonsbooking' ), - 'SAVE' => esc_html__( 'save', 'commonsbooking' ), - 'MARKER_IMAGE_MEASUREMENTS' => esc_html__( 'measurements', 'commonsbooking' ), - ]; - echo ''; - - //available categories - $available_categories_args = [ - 'taxonomy' => 'cb_items_category', - 'echo' => false, - 'checked_ontop' => false, - 'selected_cats' => array_keys( self::get_option( $cb_map_id, 'cb_items_available_categories' ) ), - ]; - $available_categories_checklist_markup = wp_terms_checklist( 0, $available_categories_args ); - $available_categories_checklist_markup = str_replace( 'name="tax_input[cb_items_category][]"', - 'class="cb_items_available_category_choice"', $available_categories_checklist_markup ); - $available_categories_checklist_markup = str_replace( 'id="in-cb_items_category-', - 'id="cb_items_available_category-', $available_categories_checklist_markup ); - - //rearrange to nummeric array, because object property order isn't stable in js - $cb_items_available_categories = self::get_option( $cb_map_id, 'cb_items_available_categories' ); - $available_categories = []; - foreach ( $cb_items_available_categories as $id => $content ) { - $available_categories[] = [ - 'id' => (string) $id, - 'content' => $content, - ]; - } - - //preset item categories - $preset_categories_args = [ - 'taxonomy' => 'cb_items_category', - 'echo' => false, - 'checked_ontop' => false, - 'selected_cats' => self::get_option( $cb_map_id, 'cb_items_preset_categories' ), - ]; - $preset_categories_checklist_markup = wp_terms_checklist( 0, $preset_categories_args ); - $preset_categories_checklist_markup = str_replace( 'name="tax_input[cb_items_category]', - 'name="cb_map_options[cb_items_preset_categories]', $preset_categories_checklist_markup ); - $preset_categories_checklist_markup = str_replace( 'id="in-cb_items_category-', 'id="cb_items_preset_category-', - $preset_categories_checklist_markup ); - - //preset location categories - $preset_location_categories_args = [ - 'taxonomy' => 'cb_locations_category', - 'echo' => false, - 'checked_ontop' => false, - 'selected_cats' => self::get_option( $cb_map_id, 'cb_locations_preset_categories' ), - ]; - $preset_location_categories_checklist_markup = wp_terms_checklist( 0, $preset_location_categories_args ); - $preset_location_categories_checklist_markup = str_replace( 'name="tax_input[cb_locations_category]', - 'name="cb_map_options[cb_locations_preset_categories]', $preset_location_categories_checklist_markup ); - $preset_location_categories_checklist_markup = str_replace( 'id="in-cb_locations_category-', 'id="cb_locations_preset_category-', - $preset_location_categories_checklist_markup ); - - wp_enqueue_style( 'cb_map_admin_css', COMMONSBOOKING_MAP_ASSETS_URL . 'css/cb-map-admin.css' ); - - include_once( COMMONSBOOKING_MAP_PATH . 'templates/map-admin-page-template.php' ); - } - - /** - * option getter - * - * @param $cb_map_id - * @param $key - * - * @return mixed - */ - public static function get_option( $cb_map_id, $key ) { - self::load_options( $cb_map_id ); - - if ( array_key_exists( $key, self::$options ) ) { - return is_array((self::$options[ $key ])) ? self::$options[ $key ] : commonsbooking_sanitizeHTML(self::$options[ $key ]); - } else { - return is_array(self::get_option_default( $key )) ? self::get_option_default( $key ) : commonsbooking_sanitizeHTML(self::get_option_default( $key )); - } - } - -} diff --git a/src/Map/MapSettings.php b/src/Map/MapSettings.php deleted file mode 100644 index c37690d45..000000000 --- a/src/Map/MapSettings.php +++ /dev/null @@ -1,114 +0,0 @@ -' . __( 'Settings' ) . ''; - array_unshift( $links, $settings_link ); - - return $links; - } - - /** - * render the settings page - **/ - public function render_settings_page() { - wp_enqueue_style( 'cb_map_admin_css', COMMONSBOOKING_MAP_ASSETS_URL . 'css/cb-map-admin.css' ); - - include_once( COMMONSBOOKING_MAP_PATH . 'templates/map-settings-page-template.php' ); - } -} \ No newline at end of file diff --git a/src/View/Map.php b/src/View/Map.php index 132e2809d..aecb669ce 100644 --- a/src/View/Map.php +++ b/src/View/Map.php @@ -22,10 +22,9 @@ public static function render_cb_map( $field, $escaped_value, $object_id, $objec wp_enqueue_script( 'cb-map-positioning_js', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-positioning.js' ); //map defaults - $options = MapAdmin::get_options(); $defaults = [ - 'latitude' => $options['lat_start'], - 'longitude' => $options['lon_start'], + 'latitude' => \CommonsBooking\Wordpress\CustomPostType\Map::LATITUDE_DEFAULT, + 'longitude' => \CommonsBooking\Wordpress\CustomPostType\Map::LONGITUDE_DEFAULT, ]; wp_add_inline_script('cb-map-positioning_js','cb_map_positioning.defaults =' . wp_json_encode($defaults) ); } diff --git a/templates/map-admin-page-template.php b/templates/map-admin-page-template.php deleted file mode 100644 index e6ec47863..000000000 --- a/templates/map-admin-page-template.php +++ /dev/null @@ -1,789 +0,0 @@ - -
- -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- : - - [cb_map id=]
- : - - - - -
- : - - - value="on"> -
- : - - px -
- : - -
- : - - value="on">
-
-
- -
-
- - - - - - - - - - - - - - - - - - -
- : - -
- : - -
- : - -
- : - - value="on">
-
-
- -
-
- - - - - - - - - - - -
- : - -
- : - -
-
-
- -
-
- - - - - - - - - - -
- : - - - value="on"> -
- : - - - value="on"> -
-
-
- -
-
- - - - - - - -
- : - - value="on">
-
-
-
-
- - - - - - - - - - - - - - - -
- : - - - value="on"> -
- : - - - -
- : - - - -
-
-
- -
-
- - - - - - - - - - - - - - - - - - - -
- : - - - - -
-
-
- -
-
- - - - - - -
- : - - - px -
-
- -
- - - - - - - - - - - - - - - - -
- : - - - - -
-
-
- -
-
- - - - - - - -
- : - - - - -
-
-
- -
-
- - - - - - - - - - - - - - - - - - -
- : - - - - -
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- : - - value="on">
- : - -
- : - - - / - -
- : - - - / - -
- : - - value="on">
- : - -
- : - -
- : - -
- : - - -
    -
    - -
    -
-
- - - - - - -
- -
-
-
- -
-
- - - - - - -
- : - - -
    -
    - -
    -
-
-
-
- -
-
- - - - - - -
- : - - -
    -
    - -
    -
-
-
-
- -
- - From 6ee244b1ada01609f9b2b352a475a4b14eba6fe3 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:53:30 +0200 Subject: [PATCH 06/18] MAP -> CMB2: create upgrade function --- src/Service/Upgrade.php | 71 ++++++++++++++++++++++++++++-- tests/php/Service/UpgradeTest.php | 73 +++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index 1692022b8..54053f00c 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -6,6 +6,7 @@ use CommonsBooking\Model\Timeframe; use CommonsBooking\Plugin; use CommonsBooking\Settings\Settings; +use CommonsBooking\Wordpress\CustomPostType\Map; use CommonsBooking\Wordpress\Options\AdminOptions; use Psr\Cache\InvalidArgumentException; @@ -49,7 +50,10 @@ class Upgrade { [ self::class, 'fixBrokenICalTitle' ] ], '2.9.2' => [ - [self::class, 'enableLocationBookingNotification'] + [ self::class, 'enableLocationBookingNotification' ] + ], + '2.10' => [ + [ self::class, 'migrateMapSettings' ] ] ]; @@ -94,6 +98,11 @@ private function runEveryUpgrade(): void { // update version number in options update_option( self::VERSION_OPTION, $this->currentVersion ); + //TODO: REMOVE THIS BEFORE MERGING, WE JUST USE THIS SO WE CAN TEST THE MIGRATION FUNCTION + // BEFORE MERGING AND WE DO NOT HAVE TO TOUCH THE content-example.xml file! + self::migrateMapSettings(); + //TODO: REMOVE THIS BEFORE MERGING!!! + // Clear cache try { Plugin::clearCache(); @@ -461,14 +470,68 @@ public static function setMultiSelectTimeFrameDefault( int $page = 1 ) { * Previously, if a location email was set that meant that they also receive a copy of each booking / cancellation email. * Now we have a separate checkbox to enable that which should be enabled for existing locations so that they will still receive emails after upgrade. * - * @since 2.9.2 * @return void + * @since 2.9.2 */ public static function enableLocationBookingNotification() { $locations = \CommonsBooking\Repository\Location::get(); - foreach ($locations as $location) { - update_post_meta($location->ID, COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', 'on'); + foreach ( $locations as $location ) { + update_post_meta( $location->ID, COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', 'on' ); + } + } + + + + /** + * Migrate Map Settings from old options to new CMB2 options + * + * @since 2.10 + * @return void + */ + public static function migrateMapSettings() : void { + $maps = get_posts( [ + 'post_type' => \CommonsBooking\Wordpress\CustomPostType\Map::$postType, + 'numberposts' => -1 + ] ); + foreach ($maps as $map) { + $options = get_post_meta( $map->ID, 'cb_map_options', true ); + if ( empty($options) ) { + continue; + } + //will map to an associative array with key being the option name and the value the default value + $defaultValues = array_reduce( + Map::getCustomFields(), + function ( $result, $option ) { + if ( isset( $option['default'] ) ) { + $result[$option['id']] = $option['default']; + } + return $result; + }, + array() + ); + foreach ($options as $key => $value) { + if ( empty($value) && isset($defaultValues[$key]) ) { + //fetch from default values when key happens to be empty + $value = $defaultValues[$key]; + } + update_post_meta( $map->ID, $key, $value ); + } + if ( ! empty($options['custom_marker_media_id'] ) ){ + // write the image url to the metabox, this way CMB2 can properly display it + $image = wp_get_attachment_image_src( intval( $options['custom_marker_media_id'] ) ); + update_post_meta( $map->ID, 'custom_marker_media', reset( $image ) ); + } + if (! empty($options['custom_marker_cluster_id'] ) ){ + // write the image url to the metabox, this way CMB2 can properly display it + $image = wp_get_attachment_image_src( intval( $options['custom_marker_cluster_id'] ) ); + update_post_meta( $map->ID, 'custom_marker_cluster', reset( $image ) ); + } + if (! empty($options['marker_item_draft_media'] ) ){ + // write the image url to the metabox, this way CMB2 can properly display it + $image = wp_get_attachment_image_src( intval( $options['marker_item_draft_media'] ) ); + update_post_meta( $map->ID, 'marker_item_draft', reset( $image ) ); + } } } } diff --git a/tests/php/Service/UpgradeTest.php b/tests/php/Service/UpgradeTest.php index f4c764cf2..fa201ece8 100644 --- a/tests/php/Service/UpgradeTest.php +++ b/tests/php/Service/UpgradeTest.php @@ -202,6 +202,79 @@ protected function setUpAJAX(): void { ); } + public function testMigrateMapSettings() { + $mapOptions = array ( + 'base_map' => 1, + 'show_scale' => true, + 'map_height' => 400, + 'custom_no_locations_message' => 'No locations found', + 'custom_filterbutton_label' => '', + 'zoom_min' => 9, + 'zoom_max' => 19, + 'scrollWheelZoom' => true, + 'zoom_start' => 9, + 'lat_start' => 50.937531, + 'lon_start' => 6.960279, + 'marker_map_bounds_initial' => true, + 'marker_map_bounds_filter' => true, + 'max_cluster_radius' => 80, + 'marker_tooltip_permanent' => false, + 'custom_marker_media_id' => 0, + 'marker_icon_width' => 0.0, + 'marker_icon_height' => 0.0, + 'marker_icon_anchor_x' => 0.0, + 'marker_icon_anchor_y' => 0.0, + 'show_location_contact' => false, + 'label_location_contact' => '', + 'show_location_opening_hours' => false, + 'label_location_opening_hours' => '', + 'show_item_availability' => false, + 'custom_marker_cluster_media_id' => 0, + 'marker_cluster_icon_width' => 0.0, + 'marker_cluster_icon_height' => 0.0, + 'address_search_bounds_left_bottom_lon' => NULL, + 'address_search_bounds_left_bottom_lat' => NULL, + 'address_search_bounds_right_top_lon' => NULL, + 'address_search_bounds_right_top_lat' => NULL, + 'show_location_distance_filter' => false, + 'label_location_distance_filter' => '', + 'show_item_availability_filter' => false, + 'label_item_availability_filter' => '', + 'label_item_category_filter' => '', + 'item_draft_appearance' => '1', + 'marker_item_draft_media_id' => 0, + 'marker_item_draft_icon_width' => 0.0, + 'marker_item_draft_icon_height' => 0.0, + 'marker_item_draft_icon_anchor_x' => 0.0, + 'marker_item_draft_icon_anchor_y' => 0.0, + 'cb_items_available_categories' => + array ( + ), + 'cb_items_preset_categories' => + array ( + ), + 'cb_locations_preset_categories' => + array ( + ), + 'availability_max_days_to_show' => 11, + 'availability_max_day_count' => 14, + ); + $oldMapId = wp_insert_post( [ + 'post_title' => 'Map', + 'post_type' => Map::$postType, + 'post_status' => 'publish' + ] ); + + update_post_meta( $oldMapId, 'cb_map_options', $mapOptions ); + + Upgrade::migrateMapSettings(); + //each option should now have it's own meta entry + foreach ($mapOptions as $key => $value) { + $this->assertEquals($value, get_post_meta($oldMapId, $key, true)); + } + wp_delete_post($oldMapId, true); + } + protected function setUp(): void { parent::setUp(); //This replaces the original update tasks with a internal test function that just sets a variable to true From 748e32ef52432f49a445347d749c2dbb66758bd6 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 5 Jun 2024 17:42:32 +0200 Subject: [PATCH 07/18] MAP -> CMB2: implement filters as repeatable group --- src/Map/MapData.php | 29 +++++++++------ src/Plugin.php | 30 +++++++++++++++ src/Service/Upgrade.php | 6 +++ src/Wordpress/CustomPostType/Map.php | 55 +++++++++++++++++++++++++++- tests/php/Service/UpgradeTest.php | 1 + 5 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/Map/MapData.php b/src/Map/MapData.php index 0090ae054..b2bd6b020 100644 --- a/src/Map/MapData.php +++ b/src/Map/MapData.php @@ -239,22 +239,27 @@ public static function get_settings( $cb_map_id ): array { } //categories are only meant to be shown on local maps + //TODO: Evaluate if it makes sense to only show them when categories are imported if ($map->getMeta('cb_items_available_categories')) { $settings['filter_cb_item_categories'] = []; - $current_group_id = null; - foreach ( $map->getMeta('cb_items_available_categories') as $categoryKey => $content ) { - if ( substr( $categoryKey, 0, 1 ) == 'g' ) { - $current_group_id = $categoryKey; - $settings['filter_cb_item_categories'][ $categoryKey ] = [ - 'name' => $content, - 'elements' => [], - ]; - } else { - $settings['filter_cb_item_categories'][ $current_group_id ]['elements'][] = [ - 'cat_id' => $categoryKey, - 'markup' => $content, + + foreach ($map->getMeta('filtergroups') as $groupID => $group) { + $elements = []; + foreach ($group['categories'] as $termID) { + $term = get_term( $termID ); + $customMarkup = get_term_meta( $termID, COMMONSBOOKING_METABOX_PREFIX . 'markup', true ); + $termName = empty($customMarkup) ? $term->name : $customMarkup; + + $elements[] = [ + 'cat_id' => intval( $termID ), + 'markup' => $termName, ]; } + $settings['filter_cb_item_categories'][ $groupID ] = [ + 'name' => $group['name'], + 'elements' => $elements, + 'isExclusive' => $group['isExclusive'] == 'on', + ]; } } diff --git a/src/Plugin.php b/src/Plugin.php index 7cb243acf..6a78944b2 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -434,6 +434,36 @@ public static function registerItemTaxonomy() { //hook the term updates to the item post type function. This only runs when a term is updated but that is enough. When a term is added, the post is saved and therefore the other hook is triggered which also runs the same function. add_action( 'saved_' . $taxonomy, array( 'CommonsBooking\Wordpress\CustomPostType\Item', 'termChange' ), 10, 3 ); add_action( 'delete_' . $taxonomy, array( 'CommonsBooking\Wordpress\CustomPostType\Item', 'termChange' ), 10, 3 ); + + //hook this for later, if we run it now, it would fail + add_action( 'cmb2_admin_init', array( self::class, 'registerItemTaxonomyMetaboxes' ) ); + } + + /** + * Add custom label for item categories that will be displayed in the map filter groups. + * @return void + */ + public static function registerItemTaxonomyMetaboxes() { + $taxonomy = Item::getPostType() . 's_category'; + + $cmb_taxonomy = new_cmb2_box( + array( + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'edit', + 'title' => esc_html__( 'Item Category', 'commonsbooking' ), + 'object_types' => array( 'term' ), + 'taxonomies' => array( 'category', $taxonomy ), + 'context' => 'side', + ) + ); + + $cmb_taxonomy->add_field( + array( + 'name' => __( 'Add custom title for filter', 'commonsbooking' ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'markup', + 'type' => 'textarea_small', + 'desc' => __( 'Define name that should be used for the category if it is displayed in the map as a filter group. You can also use this to add custom HTML to the category name. When left empty, the defined name of the category will be used.', 'commonsbooking' ), + ) + ); } /** diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index 54053f00c..881711d7b 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -532,6 +532,12 @@ function ( $result, $option ) { $image = wp_get_attachment_image_src( intval( $options['marker_item_draft_media'] ) ); update_post_meta( $map->ID, 'marker_item_draft', reset( $image ) ); } + if (! empty($options['filter_cb_item_categories'] ) ){ + $oldCategories = $options['filter_cb_item_categories']; + foreach ($oldCategories as $groupID => $group) { + //TODO: Write migration function for filters + } + } } } } diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index 51fc11230..59d54d72d 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -4,9 +4,9 @@ namespace CommonsBooking\Wordpress\CustomPostType; -use CommonsBooking\Map\MapAdmin; -use CommonsBooking\Map\MapSettings; use CommonsBooking\Map\MapShortcode; +use CommonsBooking\Repository\Item; +use CommonsBooking\Repository\Location; use function __; @@ -521,6 +521,57 @@ public static function getCustomFields(): array { 'placeholder' => esc_html__( 'filter', 'commonsbooking' ), ) ), + array( + 'name' => commonsbooking_sanitizeHTML( __( 'Filter groups', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Filter groups can group item or location categories together to allow for filtering in the map.', 'commonsbooking' ) ), + 'id' => 'filtergroups', + 'type' => 'group', + 'repeatable' => true, + 'options' => array( + 'group_title' => commonsbooking_sanitizeHTML( __( 'Filter group {#}', 'commonsbooking' ) ), + 'add_button' => commonsbooking_sanitizeHTML( __( 'Add another filter group', 'commonsbooking' ) ), + 'remove_button' => commonsbooking_sanitizeHTML( __( 'Remove filter group', 'commonsbooking' ) ), + 'sortable' => false, + ), + 'fields' => array( + array( + 'name' => commonsbooking_sanitizeHTML( __( 'Name', 'commonsbooking' ) ), + 'id' => 'name', + 'type' => 'text', + 'desc' => commonsbooking_sanitizeHTML( __( 'The name of the filter group', 'commonsbooking' ) ), + 'default' => '', + ), + array( + 'name' => commonsbooking_sanitizeHTML( __( 'Type', 'commonsbooking' ) ), + 'id' => 'type', + 'type' => 'select', + 'desc' => commonsbooking_sanitizeHTML( __( 'This is not available yet. Which data source should be used for the filter group. Taxonomy stands for the assigned categories, post-meta can be individually configured custom fields for item posts. When this item field contains data, it will be included. If it does not contain data or does not exist, the item will be excluded.', 'commonsbooking' ) ), + 'options' => array( + 'taxonomy' => commonsbooking_sanitizeHTML( __( 'Taxonomy', 'commonsbooking' ) ), + 'postmeta' => commonsbooking_sanitizeHTML( __( 'Post-meta', 'commonsbooking' ) ), + ), + 'default' => 'taxonomy', + //TODO: disabled until postmeta is implemented + 'attributes' => array( + 'disabled' => true + ), + ), + array( + 'name' => commonsbooking_sanitizeHTML( __( 'Exclusive selection', 'commonsbooking' ) ), + 'id' => 'isExclusive', + 'type' => 'checkbox', + 'desc' => commonsbooking_sanitizeHTML( __( 'WARNING: This feature is only available for the cb_search shortcode, not for cb_map. If checked, only one category can be selected in this filter group. If unchecked, multiple categories can be selected.', 'commonsbooking' ) ), + ), + array( + 'name' => commonsbooking_sanitizeHTML( __( 'Categories', 'commonsbooking' ) ), + 'id' => 'categories', + 'type' => 'multicheck', + 'desc' => commonsbooking_sanitizeHTML( __( 'The categories to be included in the filter group', 'commonsbooking' ) ), + 'options' => \CommonsBooking\Wordpress\CustomPostType\CustomPostType::sanitizeOptions ( Item::getTerms() ), + 'select_all_button' => false, + ), + ), + ), //TODO: Add available categories & filtergroups //End group Filters //Begin group Presets diff --git a/tests/php/Service/UpgradeTest.php b/tests/php/Service/UpgradeTest.php index fa201ece8..edbad8953 100644 --- a/tests/php/Service/UpgradeTest.php +++ b/tests/php/Service/UpgradeTest.php @@ -5,6 +5,7 @@ use CommonsBooking\Model\Timeframe; use CommonsBooking\Service\Upgrade; use CommonsBooking\Tests\Wordpress\CustomPostTypeTest; +use CommonsBooking\Wordpress\CustomPostType\Map; use SlopeIt\ClockMock\ClockMock; class UpgradeTest extends CustomPostTypeTest From 44203ba88b396db355c8c9690d382db0158e3b69 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:09:19 +0200 Subject: [PATCH 08/18] MAP -> CMB2: implement filter group migration --- src/Service/Upgrade.php | 52 +++-- tests/php/Service/UpgradeTest.php | 356 ++++++++++++++++++------------ 2 files changed, 250 insertions(+), 158 deletions(-) diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index 881711d7b..9a411d48e 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -482,21 +482,20 @@ public static function enableLocationBookingNotification() { } - /** * Migrate Map Settings from old options to new CMB2 options * - * @since 2.10 * @return void + * @since 2.10 */ - public static function migrateMapSettings() : void { + public static function migrateMapSettings(): void { $maps = get_posts( [ - 'post_type' => \CommonsBooking\Wordpress\CustomPostType\Map::$postType, - 'numberposts' => -1 + 'post_type' => \CommonsBooking\Wordpress\CustomPostType\Map::$postType, + 'numberposts' => - 1 ] ); - foreach ($maps as $map) { + foreach ( $maps as $map ) { $options = get_post_meta( $map->ID, 'cb_map_options', true ); - if ( empty($options) ) { + if ( empty( $options ) ) { continue; } //will map to an associative array with key being the option name and the value the default value @@ -504,39 +503,56 @@ public static function migrateMapSettings() : void { Map::getCustomFields(), function ( $result, $option ) { if ( isset( $option['default'] ) ) { - $result[$option['id']] = $option['default']; + $result[ $option['id'] ] = $option['default']; } + return $result; }, array() ); - foreach ($options as $key => $value) { - if ( empty($value) && isset($defaultValues[$key]) ) { + foreach ( $options as $key => $value ) { + if ( empty( $value ) && isset( $defaultValues[ $key ] ) ) { //fetch from default values when key happens to be empty - $value = $defaultValues[$key]; + $value = $defaultValues[ $key ]; } update_post_meta( $map->ID, $key, $value ); } - if ( ! empty($options['custom_marker_media_id'] ) ){ + if ( ! empty( $options['custom_marker_media_id'] ) ) { // write the image url to the metabox, this way CMB2 can properly display it $image = wp_get_attachment_image_src( intval( $options['custom_marker_media_id'] ) ); update_post_meta( $map->ID, 'custom_marker_media', reset( $image ) ); } - if (! empty($options['custom_marker_cluster_id'] ) ){ + if ( ! empty( $options['custom_marker_cluster_id'] ) ) { // write the image url to the metabox, this way CMB2 can properly display it $image = wp_get_attachment_image_src( intval( $options['custom_marker_cluster_id'] ) ); update_post_meta( $map->ID, 'custom_marker_cluster', reset( $image ) ); } - if (! empty($options['marker_item_draft_media'] ) ){ + if ( ! empty( $options['marker_item_draft_media'] ) ) { // write the image url to the metabox, this way CMB2 can properly display it $image = wp_get_attachment_image_src( intval( $options['marker_item_draft_media'] ) ); update_post_meta( $map->ID, 'marker_item_draft', reset( $image ) ); } - if (! empty($options['filter_cb_item_categories'] ) ){ - $oldCategories = $options['filter_cb_item_categories']; - foreach ($oldCategories as $groupID => $group) { - //TODO: Write migration function for filters + if ( ! empty( $options['cb_items_available_categories'] ) ) { + $newCategoryArray = []; + $currentCategoryIndex = -1; //start with -1 so we can increment to 0 + foreach ( $options['cb_items_available_categories'] as $key => $value ) { + if ( substr( $key, 0, 1 ) == 'g' ) { + $currentCategoryIndex ++; + $newCategoryArray[ $currentCategoryIndex ] = [ + 'name' => $value, + 'type' => '', + 'isExclusive' => false, + 'categories' => [] + ]; + } else { + $newCategoryArray[ $currentCategoryIndex ]['categories'][] = $key; + //see if specified name is different from taxonomy name, save differing name in taxonomy meta + if ( get_term( $key )->name != $value ) { + update_term_meta( $key, COMMONSBOOKING_METABOX_PREFIX . 'markup', [ $value ] ); + } + } } + update_post_meta( $map->ID, 'cb_items_available_categories', [ $newCategoryArray ] ); } } } diff --git a/tests/php/Service/UpgradeTest.php b/tests/php/Service/UpgradeTest.php index edbad8953..7f7dc092d 100644 --- a/tests/php/Service/UpgradeTest.php +++ b/tests/php/Service/UpgradeTest.php @@ -8,20 +8,18 @@ use CommonsBooking\Wordpress\CustomPostType\Map; use SlopeIt\ClockMock\ClockMock; -class UpgradeTest extends CustomPostTypeTest -{ +class UpgradeTest extends CustomPostTypeTest { - private static bool $functionAHasRun = false; + private static bool $functionAHasRun = false; private static bool $functionBHasRun = false; private $testTasks; private $ajaxTasks; - public function testFixBrokenICalTitle() - { + public function testFixBrokenICalTitle() { \CommonsBooking\Settings\Settings::updateOption( 'commonsbooking_options_templates', 'emailtemplates_mail-booking_ics_event-title', - 'Booking for {{item:post_name}}' + 'Booking for {{item:post_name}}' ); \CommonsBooking\Settings\Settings::updateOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', @@ -29,21 +27,20 @@ public function testFixBrokenICalTitle() 'Booking for {{item:post_name}}' ); Upgrade::fixBrokenICalTitle(); - $this->assertEquals('Booking for {{item:post_title}}', \CommonsBooking\Settings\Settings::getOption('commonsbooking_options_templates', 'emailtemplates_mail-booking_ics_event-title')); - $this->assertEquals('Booking for {{item:post_title}}', \CommonsBooking\Settings\Settings::getOption(COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'event_title')); - } - - public function testIsMajorUpdate() - { - $majorUpdate = new Upgrade('2.5.0', '2.6.0'); - $this->assertTrue($majorUpdate->isMajorUpdate()); - $minorUpdate = new Upgrade('2.5.0', '2.5.1'); - $this->assertFalse($minorUpdate->isMajorUpdate()); - $majorestUpdate = new Upgrade('2.5.0', '3.0.0'); - $this->assertTrue($majorestUpdate->isMajorUpdate()); - $downgrade = new Upgrade('2.6.0', '2.5.0'); - $this->assertFalse($downgrade->isMajorUpdate()); - } + $this->assertEquals( 'Booking for {{item:post_title}}', \CommonsBooking\Settings\Settings::getOption( 'commonsbooking_options_templates', 'emailtemplates_mail-booking_ics_event-title' ) ); + $this->assertEquals( 'Booking for {{item:post_title}}', \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'event_title' ) ); + } + + public function testIsMajorUpdate() { + $majorUpdate = new Upgrade( '2.5.0', '2.6.0' ); + $this->assertTrue( $majorUpdate->isMajorUpdate() ); + $minorUpdate = new Upgrade( '2.5.0', '2.5.1' ); + $this->assertFalse( $minorUpdate->isMajorUpdate() ); + $majorestUpdate = new Upgrade( '2.5.0', '3.0.0' ); + $this->assertTrue( $majorestUpdate->isMajorUpdate() ); + $downgrade = new Upgrade( '2.6.0', '2.5.0' ); + $this->assertFalse( $downgrade->isMajorUpdate() ); + } /** * This will test if the upgrade tasks are run correctly. @@ -52,11 +49,11 @@ public function testIsMajorUpdate() * * @dataProvider provideUpgradeConditions */ - public function testRunUpgradeTasks($previousVersion, $currentVersion, $shouldRunFunction) { - $upgrade = new Upgrade($previousVersion, $currentVersion); + public function testRunUpgradeTasks( $previousVersion, $currentVersion, $shouldRunFunction ) { + $upgrade = new Upgrade( $previousVersion, $currentVersion ); $upgrade->runUpgradeTasks(); - $this->assertEquals($shouldRunFunction, self::$functionAHasRun); - $this->assertEquals($shouldRunFunction, self::$functionBHasRun); + $this->assertEquals( $shouldRunFunction, self::$functionAHasRun ); + $this->assertEquals( $shouldRunFunction, self::$functionBHasRun ); } /** @@ -68,117 +65,116 @@ public function testRunUpgradeTasks($previousVersion, $currentVersion, $shouldRu */ public function provideUpgradeConditions() { return array( - "Upgrade directly on version with new function (major)" => ["2.4.0", "2.5.2", true], - "Upgrade past version with new function (major)" => ["2.4.0", "2.6.0", true], - "Direct minor upgrade on same version" => ["2.5.1", "2.5.2", true], - "Direct minor upgrade on version without new function" => ["2.5.0", "2.5.1", false], //This is a weird case that should not happen, usually the function would not be added before it is needed - "Direct minor upgrade past version with new function" => ["2.5.2", "2.5.3", false], - "Direct minor upgrade past version with new function (major)" => ["2.5.2", "2.6.0", false], - "Downgrade from previous versions" => ["2.5.3", "2.5.2", false], + "Upgrade directly on version with new function (major)" => [ "2.4.0", "2.5.2", true ], + "Upgrade past version with new function (major)" => [ "2.4.0", "2.6.0", true ], + "Direct minor upgrade on same version" => [ "2.5.1", "2.5.2", true ], + "Direct minor upgrade on version without new function" => [ "2.5.0", "2.5.1", false ], + //This is a weird case that should not happen, usually the function would not be added before it is needed + "Direct minor upgrade past version with new function" => [ "2.5.2", "2.5.3", false ], + "Direct minor upgrade past version with new function (major)" => [ "2.5.2", "2.6.0", false ], + "Downgrade from previous versions" => [ "2.5.3", "2.5.2", false ], ); } - public static function fakeUpdateFunctionA() - { + public static function fakeUpdateFunctionA() { self::$functionAHasRun = true; } - public static function fakeUpdateFunctionB() - { + public static function fakeUpdateFunctionB() { self::$functionBHasRun = true; } public function testRunTasksAfterUpdate() { $olderVersion = '2.5.0'; - update_option(Upgrade::VERSION_OPTION, $olderVersion); + update_option( Upgrade::VERSION_OPTION, $olderVersion ); Upgrade::runTasksAfterUpdate(); - $this->assertEquals(COMMONSBOOKING_VERSION, get_option(Upgrade::VERSION_OPTION)); + $this->assertEquals( COMMONSBOOKING_VERSION, get_option( Upgrade::VERSION_OPTION ) ); } public function testRun() { - $upgrade = new Upgrade('2.5.0', '2.6.0'); - $this->assertTrue($upgrade->run()); - $this->assertEquals('2.6.0', get_option(Upgrade::VERSION_OPTION)); + $upgrade = new Upgrade( '2.5.0', '2.6.0' ); + $this->assertTrue( $upgrade->run() ); + $this->assertEquals( '2.6.0', get_option( Upgrade::VERSION_OPTION ) ); - $upgrade = new Upgrade('2.5.0', '2.5.1'); - $this->assertTrue($upgrade->run()); - $this->assertEquals('2.5.1', get_option(Upgrade::VERSION_OPTION)); + $upgrade = new Upgrade( '2.5.0', '2.5.1' ); + $this->assertTrue( $upgrade->run() ); + $this->assertEquals( '2.5.1', get_option( Upgrade::VERSION_OPTION ) ); //new installation - $upgrade = new Upgrade('', '2.5.0'); - $this->assertTrue($upgrade->run()); - $this->assertEquals('2.5.0', get_option(Upgrade::VERSION_OPTION)); + $upgrade = new Upgrade( '', '2.5.0' ); + $this->assertTrue( $upgrade->run() ); + $this->assertEquals( '2.5.0', get_option( Upgrade::VERSION_OPTION ) ); //no version change - $upgrade = new Upgrade('2.5.0', '2.5.0'); - $this->assertFalse($upgrade->run()); + $upgrade = new Upgrade( '2.5.0', '2.5.0' ); + $this->assertFalse( $upgrade->run() ); //AJAX tasks present -> should not be run $this->setUpAJAX(); - $upgrade = new Upgrade('2.5.1', '2.5.2'); - $this->assertFalse($upgrade->run()); + $upgrade = new Upgrade( '2.5.1', '2.5.2' ); + $this->assertFalse( $upgrade->run() ); //AJAX tasks should be ignored on new installation - $upgrade = new Upgrade('', '2.5.2'); - $this->assertTrue($upgrade->run()); + $upgrade = new Upgrade( '', '2.5.2' ); + $this->assertTrue( $upgrade->run() ); } public function testSetAdvanceBookingDaysDefault() { //create timeframe without advance booking days $timeframeId = $this->createBookableTimeFrameIncludingCurrentDay(); - update_post_meta($timeframeId, \CommonsBooking\Model\Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS, ''); + update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS, '' ); Upgrade::setAdvanceBookingDaysDefault(); - $this->assertEquals(\CommonsBooking\Wordpress\CustomPostType\Timeframe::ADVANCE_BOOKING_DAYS, get_post_meta($timeframeId, \CommonsBooking\Model\Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS, true)); + $this->assertEquals( \CommonsBooking\Wordpress\CustomPostType\Timeframe::ADVANCE_BOOKING_DAYS, get_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS, true ) ); } public function testRemoveBreakingPostmeta() { - ClockMock::freeze(new \DateTime(self::CURRENT_DATE)); + ClockMock::freeze( new \DateTime( self::CURRENT_DATE ) ); //Create timeframe that should still be valid after the cleanup - $validTF = new Timeframe($this->createBookableTimeFrameStartingInAWeek()); - $this->assertTrue($validTF->isValid()); + $validTF = new Timeframe( $this->createBookableTimeFrameStartingInAWeek() ); + $this->assertTrue( $validTF->isValid() ); //create holiday with ADVANCE_BOOKING_DAYS setting (the function does this by default) $holiday = $this->createTimeframe( $this->locationId, $this->itemId, - strtotime('+1 week', strtotime(self::CURRENT_DATE)), - strtotime('+2 weeks', strtotime(self::CURRENT_DATE)), + strtotime( '+1 week', strtotime( self::CURRENT_DATE ) ), + strtotime( '+2 weeks', strtotime( self::CURRENT_DATE ) ), ); $this->assertTrue( Upgrade::removeBreakingPostmeta() ); - $this->assertEmpty(get_post_meta($holiday, 'advance_booking_days', true)); + $this->assertEmpty( get_post_meta( $holiday, 'advance_booking_days', true ) ); } public function testSetMultiSelectTimeFrameDefault() { $tf = $this->createBookableTimeFrameIncludingCurrentDay(); - update_post_meta($tf, Timeframe::META_ITEM_SELECTION_TYPE, ''); - update_post_meta($tf, Timeframe::META_LOCATION_SELECTION_TYPE, ''); - $this->assertTrue ( Upgrade::setMultiSelectTimeFrameDefault() ); - $this->assertEquals(Timeframe::SELECTION_MANUAL_ID, get_post_meta($tf, Timeframe::META_ITEM_SELECTION_TYPE, true)); - $this->assertEquals(Timeframe::SELECTION_MANUAL_ID, get_post_meta($tf, Timeframe::META_LOCATION_SELECTION_TYPE, true)); + update_post_meta( $tf, Timeframe::META_ITEM_SELECTION_TYPE, '' ); + update_post_meta( $tf, Timeframe::META_LOCATION_SELECTION_TYPE, '' ); + $this->assertTrue( Upgrade::setMultiSelectTimeFrameDefault() ); + $this->assertEquals( Timeframe::SELECTION_MANUAL_ID, get_post_meta( $tf, Timeframe::META_ITEM_SELECTION_TYPE, true ) ); + $this->assertEquals( Timeframe::SELECTION_MANUAL_ID, get_post_meta( $tf, Timeframe::META_LOCATION_SELECTION_TYPE, true ) ); } public function testEnableLocationBookingNotification() { Upgrade::enableLocationBookingNotification(); - $this->assertEquals('on', get_post_meta($this->locationId, COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', true) ); + $this->assertEquals( 'on', get_post_meta( $this->locationId, COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', true ) ); } public function testIsAJAXUpgrade() { //2.5.0 -> COMMONSBOOKING_VERSION - update_option(Upgrade::VERSION_OPTION, '2.5.0'); - $this->assertFalse(Upgrade::isAJAXUpgrade()); + update_option( Upgrade::VERSION_OPTION, '2.5.0' ); + $this->assertFalse( Upgrade::isAJAXUpgrade() ); $this->setUpAJAX(); //2.5.0 -> COMMONSBOOKING_VERSION - $this->assertTrue(Upgrade::isAJAXUpgrade()); + $this->assertTrue( Upgrade::isAJAXUpgrade() ); //2.6.0 -> COMMONSBOOKING_VERSION - update_option(Upgrade::VERSION_OPTION, '2.6.0'); - $this->assertFalse(Upgrade::isAJAXUpgrade()); + update_option( Upgrade::VERSION_OPTION, '2.6.0' ); + $this->assertFalse( Upgrade::isAJAXUpgrade() ); //fresh install - update_option(Upgrade::VERSION_OPTION, ''); - $this->assertFalse(Upgrade::isAJAXUpgrade()); + update_option( Upgrade::VERSION_OPTION, '' ); + $this->assertFalse( Upgrade::isAJAXUpgrade() ); } /** @@ -189,7 +185,7 @@ protected function setUpAJAX(): void { $this->testTasks->setValue( [ '2.5.2' => [ - [self::class, 'fakeUpdateFunctionA' ], + [ self::class, 'fakeUpdateFunctionA' ], ] ] ); @@ -197,70 +193,91 @@ protected function setUpAJAX(): void { $this->ajaxTasks->setValue( [ '2.5.2' => [ - [self::class, 'fakeUpdateFunctionB' ] + [ self::class, 'fakeUpdateFunctionB' ] ] ] ); } public function testMigrateMapSettings() { - $mapOptions = array ( - 'base_map' => 1, - 'show_scale' => true, - 'map_height' => 400, - 'custom_no_locations_message' => 'No locations found', - 'custom_filterbutton_label' => '', - 'zoom_min' => 9, - 'zoom_max' => 19, - 'scrollWheelZoom' => true, - 'zoom_start' => 9, - 'lat_start' => 50.937531, - 'lon_start' => 6.960279, - 'marker_map_bounds_initial' => true, - 'marker_map_bounds_filter' => true, - 'max_cluster_radius' => 80, - 'marker_tooltip_permanent' => false, - 'custom_marker_media_id' => 0, - 'marker_icon_width' => 0.0, - 'marker_icon_height' => 0.0, - 'marker_icon_anchor_x' => 0.0, - 'marker_icon_anchor_y' => 0.0, - 'show_location_contact' => false, - 'label_location_contact' => '', - 'show_location_opening_hours' => false, - 'label_location_opening_hours' => '', - 'show_item_availability' => false, - 'custom_marker_cluster_media_id' => 0, - 'marker_cluster_icon_width' => 0.0, - 'marker_cluster_icon_height' => 0.0, - 'address_search_bounds_left_bottom_lon' => NULL, - 'address_search_bounds_left_bottom_lat' => NULL, - 'address_search_bounds_right_top_lon' => NULL, - 'address_search_bounds_right_top_lat' => NULL, - 'show_location_distance_filter' => false, - 'label_location_distance_filter' => '', - 'show_item_availability_filter' => false, - 'label_item_availability_filter' => '', - 'label_item_category_filter' => '', - 'item_draft_appearance' => '1', - 'marker_item_draft_media_id' => 0, - 'marker_item_draft_icon_width' => 0.0, - 'marker_item_draft_icon_height' => 0.0, - 'marker_item_draft_icon_anchor_x' => 0.0, - 'marker_item_draft_icon_anchor_y' => 0.0, - 'cb_items_available_categories' => - array ( - ), - 'cb_items_preset_categories' => - array ( - ), - 'cb_locations_preset_categories' => - array ( + + + //create taxonomies for test + $twowheelsCat = wp_insert_term( '2 Räder', 'cb_items_category' )['term_id']; + $threewheelsCat = wp_insert_term( '3 Räder', 'cb_items_category' )['term_id']; + $comboCat = wp_insert_term( 'Gespann', 'cb_items_category' )['term_id']; + $childTransportCat = wp_insert_term( 'Kindertransport', 'cb_items_category' )['term_id']; + $chestCat = wp_insert_term( 'Kiste mit Schloss', 'cb_items_category' )['term_id']; + $rainCoverCat = wp_insert_term( 'Regenverdeck', 'cb_items_category' )['term_id']; + $withMotorCat = wp_insert_term( 'mit Elektro', 'cb_items_category' )['term_id']; + $manualPowerCat = wp_insert_term( 'Reine Muskelkraft', 'cb_items_category' )['term_id']; + $mapOptions = array( + 'base_map' => 1, + 'show_scale' => true, + 'map_height' => 400, + 'custom_no_locations_message' => 'No locations found', + 'custom_filterbutton_label' => '', + 'zoom_min' => 9, + 'zoom_max' => 19, + 'scrollWheelZoom' => true, + 'zoom_start' => 9, + 'lat_start' => 50.937531, + 'lon_start' => 6.960279, + 'marker_map_bounds_initial' => true, + 'marker_map_bounds_filter' => true, + 'max_cluster_radius' => 80, + 'marker_tooltip_permanent' => false, + 'custom_marker_media_id' => 0, + 'marker_icon_width' => 0.0, + 'marker_icon_height' => 0.0, + 'marker_icon_anchor_x' => 0.0, + 'marker_icon_anchor_y' => 0.0, + 'show_location_contact' => false, + 'label_location_contact' => '', + 'show_location_opening_hours' => false, + 'label_location_opening_hours' => '', + 'show_item_availability' => false, + 'custom_marker_cluster_media_id' => 0, + 'marker_cluster_icon_width' => 0.0, + 'marker_cluster_icon_height' => 0.0, + 'address_search_bounds_left_bottom_lon' => null, + 'address_search_bounds_left_bottom_lat' => null, + 'address_search_bounds_right_top_lon' => null, + 'address_search_bounds_right_top_lat' => null, + 'show_location_distance_filter' => false, + 'label_location_distance_filter' => '', + 'show_item_availability_filter' => false, + 'label_item_availability_filter' => '', + 'label_item_category_filter' => '', + 'item_draft_appearance' => '1', + 'marker_item_draft_media_id' => 0, + 'marker_item_draft_icon_width' => 0.0, + 'marker_item_draft_icon_height' => 0.0, + 'marker_item_draft_icon_anchor_x' => 0.0, + 'marker_item_draft_icon_anchor_y' => 0.0, + 'cb_items_available_categories' => + array( + 'g1723473456166-602276' => 'Radzahl', + $twowheelsCat => '2 Räder', + $threewheelsCat => '3 Räder', + $comboCat => 'Gespann', + 'g1723473486911-550535' => '', + $childTransportCat => 'Kindertransport', + $chestCat => 'Kiste mit Schloss', + $rainCoverCat => 'Regenverdeck', + 'g1723473495758-257563' => '', + $withMotorCat => 'mit Elektro', + $manualPowerCat => 'Zum Strampeln', + //this is changed markup for that category, should be moved to term meta (_cb_markup) ), - 'availability_max_days_to_show' => 11, - 'availability_max_day_count' => 14, + 'cb_items_preset_categories' => + array(), + 'cb_locations_preset_categories' => + array(), + 'availability_max_days_to_show' => 11, + 'availability_max_day_count' => 14, ); - $oldMapId = wp_insert_post( [ + $oldMapId = wp_insert_post( [ 'post_title' => 'Map', 'post_type' => Map::$postType, 'post_status' => 'publish' @@ -270,30 +287,89 @@ public function testMigrateMapSettings() { Upgrade::migrateMapSettings(); //each option should now have it's own meta entry - foreach ($mapOptions as $key => $value) { - $this->assertEquals($value, get_post_meta($oldMapId, $key, true)); + foreach ( $mapOptions as $key => $value ) { + if ( $key === 'cb_items_available_categories' ) { + continue; + } + $this->assertEquals( $value, get_post_meta( $oldMapId, $key, true ) ); } - wp_delete_post($oldMapId, true); + + $expectedFilterCategories = + array( + 0 => + array( + 0 => + array( + 'name' => 'Radzahl', + 'type' => '', + 'isExclusive' => false, + 'categories' => + array( + 0 => $twowheelsCat, + 1 => $threewheelsCat, + 2 => $comboCat + ), + ), + 1 => + array( + 'name' => '', + 'type' => '', + 'isExclusive' => false, + 'categories' => + array( + 0 => $childTransportCat, + 1 => $chestCat, + 2 => $rainCoverCat + ), + ), + 2 => + array( + 'name' => '', + 'type' => '', + 'isExclusive' => false, + 'categories' => + array( + 0 => $withMotorCat, + 1 => $manualPowerCat + ), + ), + ), + ); + + $this->assertEquals( $expectedFilterCategories, get_post_meta( $oldMapId, 'cb_items_available_categories', true ) ); + //assert, that custom markup has been moved + $expectedMarkup = [ 'Zum Strampeln' ]; + $this->assertEquals( $expectedMarkup, get_term_meta( $manualPowerCat, COMMONSBOOKING_METABOX_PREFIX . 'markup', true ) ); + + wp_delete_post( $oldMapId, true ); + wp_delete_term( $twowheelsCat, 'cb_items_category' ); + wp_delete_term( $threewheelsCat, 'cb_items_category' ); + wp_delete_term( $comboCat, 'cb_items_category' ); + wp_delete_term( $childTransportCat, 'cb_items_category' ); + wp_delete_term( $chestCat, 'cb_items_category' ); + wp_delete_term( $rainCoverCat, 'cb_items_category' ); + wp_delete_term( $withMotorCat, 'cb_items_category' ); + wp_delete_term( $manualPowerCat, 'cb_items_category' ); } protected function setUp(): void { parent::setUp(); //This replaces the original update tasks with a internal test function that just sets a variable to true $this->testTasks = new \ReflectionProperty( '\CommonsBooking\Service\Upgrade', 'upgradeTasks' ); - $this->testTasks->setAccessible(true); + $this->testTasks->setAccessible( true ); $this->testTasks->setValue( [ '2.5.2' => [ - [self::class, 'fakeUpdateFunctionA' ], - [self::class, 'fakeUpdateFunctionB' ] + [ self::class, 'fakeUpdateFunctionA' ], + [ self::class, 'fakeUpdateFunctionB' ] ] ] ); //empty AJAX tasks $this->ajaxTasks = new \ReflectionProperty( '\CommonsBooking\Service\Upgrade', 'ajaxUpgradeTasks' ); - $this->ajaxTasks->setAccessible(true); - $this->ajaxTasks->setValue([]); + $this->ajaxTasks->setAccessible( true ); + $this->ajaxTasks->setValue( [] ); } @@ -301,7 +377,7 @@ protected function tearDown(): void { self::$functionAHasRun = false; self::$functionBHasRun = false; //resets version back to current version - update_option(\CommonsBooking\Service\Upgrade::VERSION_OPTION, COMMONSBOOKING_VERSION); + update_option( \CommonsBooking\Service\Upgrade::VERSION_OPTION, COMMONSBOOKING_VERSION ); parent::tearDown(); } } From 44015a8f934b9e1b55d16d0cdc8cd5599350b756 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:17:26 +0200 Subject: [PATCH 09/18] MAP -> CMB2: removed unnecessary array casting --- src/Service/Upgrade.php | 4 +-- tests/php/Service/UpgradeTest.php | 57 +++++++++++++++---------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index 9a411d48e..1e57b8511 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -548,11 +548,11 @@ function ( $result, $option ) { $newCategoryArray[ $currentCategoryIndex ]['categories'][] = $key; //see if specified name is different from taxonomy name, save differing name in taxonomy meta if ( get_term( $key )->name != $value ) { - update_term_meta( $key, COMMONSBOOKING_METABOX_PREFIX . 'markup', [ $value ] ); + update_term_meta( $key, COMMONSBOOKING_METABOX_PREFIX . 'markup', $value ); } } } - update_post_meta( $map->ID, 'cb_items_available_categories', [ $newCategoryArray ] ); + update_post_meta( $map->ID, 'cb_items_available_categories', $newCategoryArray ); } } } diff --git a/tests/php/Service/UpgradeTest.php b/tests/php/Service/UpgradeTest.php index 7f7dc092d..012017fff 100644 --- a/tests/php/Service/UpgradeTest.php +++ b/tests/php/Service/UpgradeTest.php @@ -298,47 +298,44 @@ public function testMigrateMapSettings() { array( 0 => array( - 0 => + 'name' => 'Radzahl', + 'type' => '', + 'isExclusive' => false, + 'categories' => array( - 'name' => 'Radzahl', - 'type' => '', - 'isExclusive' => false, - 'categories' => - array( - 0 => $twowheelsCat, - 1 => $threewheelsCat, - 2 => $comboCat - ), + 0 => $twowheelsCat, + 1 => $threewheelsCat, + 2 => $comboCat ), - 1 => + ), + 1 => + array( + 'name' => '', + 'type' => '', + 'isExclusive' => false, + 'categories' => array( - 'name' => '', - 'type' => '', - 'isExclusive' => false, - 'categories' => - array( - 0 => $childTransportCat, - 1 => $chestCat, - 2 => $rainCoverCat - ), + 0 => $childTransportCat, + 1 => $chestCat, + 2 => $rainCoverCat ), - 2 => + ), + 2 => + array( + 'name' => '', + 'type' => '', + 'isExclusive' => false, + 'categories' => array( - 'name' => '', - 'type' => '', - 'isExclusive' => false, - 'categories' => - array( - 0 => $withMotorCat, - 1 => $manualPowerCat - ), + 0 => $withMotorCat, + 1 => $manualPowerCat ), ), ); $this->assertEquals( $expectedFilterCategories, get_post_meta( $oldMapId, 'cb_items_available_categories', true ) ); //assert, that custom markup has been moved - $expectedMarkup = [ 'Zum Strampeln' ]; + $expectedMarkup = 'Zum Strampeln'; $this->assertEquals( $expectedMarkup, get_term_meta( $manualPowerCat, COMMONSBOOKING_METABOX_PREFIX . 'markup', true ) ); wp_delete_post( $oldMapId, true ); From 7a5393cf88f58694c370e58e5524d821b1824ca9 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:46:15 +0200 Subject: [PATCH 10/18] MAP->CMB2: fix migration issues --- src/Map/MapData.php | 2 -- src/Service/Upgrade.php | 5 +++-- tests/php/Service/UpgradeTest.php | 16 ++++++++-------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Map/MapData.php b/src/Map/MapData.php index b2bd6b020..6342a50a6 100644 --- a/src/Map/MapData.php +++ b/src/Map/MapData.php @@ -183,8 +183,6 @@ public static function get_settings( $cb_map_id ): array { 'asset_path' => COMMONSBOOKING_MAP_ASSETS_URL, ]; - $options = MapAdmin::get_options( $cb_map_id, true ); - $pass_through = [ 'base_map', 'show_scale', diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index 1e57b8511..ad2e16401 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -121,6 +121,7 @@ private function runEveryUpgrade(): void { public function __construct( string $previousVersion, string $currentVersion ) { $this->previousVersion = $previousVersion; $this->currentVersion = $currentVersion; + self::migrateMapSettings(); } /** @@ -545,14 +546,14 @@ function ( $result, $option ) { 'categories' => [] ]; } else { - $newCategoryArray[ $currentCategoryIndex ]['categories'][] = $key; + $newCategoryArray[ $currentCategoryIndex ]['categories'][] = (string) $key; //see if specified name is different from taxonomy name, save differing name in taxonomy meta if ( get_term( $key )->name != $value ) { update_term_meta( $key, COMMONSBOOKING_METABOX_PREFIX . 'markup', $value ); } } } - update_post_meta( $map->ID, 'cb_items_available_categories', $newCategoryArray ); + update_post_meta( $map->ID, 'filtergroups', $newCategoryArray ); } } } diff --git a/tests/php/Service/UpgradeTest.php b/tests/php/Service/UpgradeTest.php index 012017fff..e2b935e1f 100644 --- a/tests/php/Service/UpgradeTest.php +++ b/tests/php/Service/UpgradeTest.php @@ -303,9 +303,9 @@ public function testMigrateMapSettings() { 'isExclusive' => false, 'categories' => array( - 0 => $twowheelsCat, - 1 => $threewheelsCat, - 2 => $comboCat + 0 => (string) $twowheelsCat, + 1 => (string) $threewheelsCat, + 2 => (string) $comboCat ), ), 1 => @@ -315,9 +315,9 @@ public function testMigrateMapSettings() { 'isExclusive' => false, 'categories' => array( - 0 => $childTransportCat, - 1 => $chestCat, - 2 => $rainCoverCat + 0 => (string) $childTransportCat, + 1 => (string) $chestCat, + 2 => (string) $rainCoverCat ), ), 2 => @@ -327,8 +327,8 @@ public function testMigrateMapSettings() { 'isExclusive' => false, 'categories' => array( - 0 => $withMotorCat, - 1 => $manualPowerCat + 0 => (string) $withMotorCat, + 1 => (string) $manualPowerCat ), ), ); From f230ceff184cd851434f267ac3573e25e202f316 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:46:52 +0200 Subject: [PATCH 11/18] added warnings --- src/Service/Upgrade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index ad2e16401..4c973104b 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -121,7 +121,7 @@ private function runEveryUpgrade(): void { public function __construct( string $previousVersion, string $currentVersion ) { $this->previousVersion = $previousVersion; $this->currentVersion = $currentVersion; - self::migrateMapSettings(); + self::migrateMapSettings(); //TODO: REMOVE BEFORE PUSHING TO MASTER } /** From ff80c8995c1f3f03733c57066499b2a8c9e3641a Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 14 Aug 2024 09:53:48 +0200 Subject: [PATCH 12/18] MAP-> CMB2: Add styling --- Gruntfile.js | 5 +- assets/admin/js/src/map.js | 92 ++++++++++++++++++++++ assets/admin/sass/partials/_form-map.scss | 41 ++++++++++ src/Wordpress/CustomPostType/Map.php | 96 ++++++++++++++--------- 4 files changed, 198 insertions(+), 36 deletions(-) create mode 100644 assets/admin/js/src/map.js create mode 100644 assets/admin/sass/partials/_form-map.scss diff --git a/Gruntfile.js b/Gruntfile.js index 499399d5e..277e75aff 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -170,7 +170,10 @@ module.exports = function (grunt) { ], tasks: [ 'dart-sass:adminDev', 'dart-sass:publicDev' - ] + ], + options: { + livereload: true + } }, js: { files: [ diff --git a/assets/admin/js/src/map.js b/assets/admin/js/src/map.js new file mode 100644 index 000000000..3cbba92f1 --- /dev/null +++ b/assets/admin/js/src/map.js @@ -0,0 +1,92 @@ +(function ($) { + 'use strict'; + $(function () { + const mapSettingsForm = $("#cmb2-metabox-cb_map-custom-fields"); + + const hideFieldset = function (set) { + $.each(set, function () { + $(this).parents('.cmb-row').hide(); + }); + }; + + /** + * Show set-elements. + * @param set + */ + const showFieldset = function (set) { + $.each(set, function () { + $(this).parents('.cmb-row').show(); + }); + }; + + const copyToClipboard = function (element) { + let code = $(element).find('code')[0]; + let text = code.innerText; + navigator.clipboard.writeText(text).then(function () { + let button = $(element).find('.button'); + let buttonText = button.text(); + button.text('✓'); + button.disabled = true; + setTimeout(function () { + button.text(buttonText); + button.disabled = false; + }, 2000); + }); + } + + const copyToClipboardButton = $('#shortcode-field').find('.button'); + copyToClipboardButton.on('click', function () { + debugger; + copyToClipboard($('#shortcode-field')); + }); + + function handleCustomFileInput(fileSelectorID, fileInputFields) { + const markerFileSelect = document.querySelector(fileSelectorID); + const handleSelectCustomMarker = function () { + showFieldset(fileInputFields); + if (markerFileSelect.value === '') { + hideFieldset(fileInputFields); + } + }; + + handleSelectCustomMarker(); + + const observerConfig = {attributes: true, childList: false, subtree: false}; + const observer = new MutationObserver(function (mutations) { + mutations.forEach(function (mutation) { + if (mutation.attributeName === 'value') { + handleSelectCustomMarker(); + } + }); + }); + observer.observe(markerFileSelect, observerConfig); + } + + if (mapSettingsForm.length) { + handleCustomFileInput( + '#custom_marker_media', + [ + $('#marker_icon_width'), + $('#marker_icon_height'), + $('#marker_icon_anchor_x'), + $('#marker_icon_anchor_y') + ]); + handleCustomFileInput( + '#custom_marker_cluster_media', + [ + $('#marker_cluster_icon_width'), + $('#marker_cluster_icon_height') + ] + ); + handleCustomFileInput( + '#marker_item_draft_media', + [ + $('#marker_item_draft_icon_width'), + $('#marker_item_draft_icon_height'), + $('#marker_item_draft_icon_anchor_x'), + $('#marker_item_draft_icon_anchor_y') + ] + ); + } + }); +})(jQuery); diff --git a/assets/admin/sass/partials/_form-map.scss b/assets/admin/sass/partials/_form-map.scss new file mode 100644 index 000000000..79a9a727f --- /dev/null +++ b/assets/admin/sass/partials/_form-map.scss @@ -0,0 +1,41 @@ +/* +* The CPT creation form map + */ + +#cmb2-metabox-cb_map-custom-fields { + .map-organizer { + .cmb2-metabox-title { + font-size: x-large; + } + .cmb2-metabox-title:before { + /* arrow to right */ + content: "\2192 "; + } + } + + .cmb-group-name { + font-size: x-large; + font-weight: bold; + } + + .cmb-group-name:before { + content: "\2192 "; + } + + #shortcode-field { + display: flex; + align-items: center; + flex-wrap: nowrap; + gap: 10px; + } + + #shortcode-field code { + white-space: nowrap; + margin-right: 10px; + } + + #shortcode-field .button { + padding: 5px 10px; + line-height: 1.5; + } +} \ No newline at end of file diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index 59d54d72d..b9ee48906 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -6,6 +6,7 @@ use CommonsBooking\Map\MapShortcode; use CommonsBooking\Repository\Item; +use CMB2_Field; use CommonsBooking\Repository\Location; use function __; @@ -58,17 +59,17 @@ public static function getCustomFields(): array { 'id' => 'map_settings_info', 'type' => 'title', ), - //Begin group presentation array( - 'name' => esc_html__( 'Presentation', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'presentation_info' + 'render_row_cb' => array( self::class, 'getShortcode' ), + 'type' => 'text', + 'id' => 'shortcode', ), + //Begin group presentation array( - 'name' => esc_html__( 'Shortcode', 'commonsbooking' ), - 'desc' => '[cb_map_id=999]', //TODO: Render callback - 'id' => 'shortcode', - 'type' => 'title', + 'name' => esc_html__( 'Presentation', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'presentation_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'base map', 'commonsbooking' ), @@ -80,7 +81,8 @@ public static function getCustomFields(): array { '2' => esc_html__( 'OSM - german style', 'commonsbooking' ), '3' => esc_html__( 'OSM - hike and bike', 'commonsbooking' ), '4' => esc_html__( 'OSM - lokaler (min. zoom: 9)', 'commonsbooking' ), - ) + ), + 'classes' => 'presentation_option', ), array( 'name' => esc_html__( 'show scale', 'commonsbooking' ), @@ -97,7 +99,7 @@ public static function getCustomFields(): array { 'attributes' => array( 'type' => 'number', 'pattern' => '\d*', - ) + ), ), array( 'name' => esc_html__( 'no locations message', 'commonsbooking' ), @@ -114,9 +116,10 @@ public static function getCustomFields(): array { ), //Begin group Zoom array( - 'name' => esc_html__( 'Zoom', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'zoom_info' + 'name' => esc_html__( 'Zoom', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'zoom_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'min. zoom level', 'commonsbooking' ), @@ -167,9 +170,10 @@ public static function getCustomFields(): array { //End group Zoom //Begin group Positioning array( - 'name' => esc_html__( 'Positioning', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'positioning_info' + 'name' => esc_html__( 'Positioning', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'positioning_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'start latitude', 'commonsbooking' ), @@ -202,9 +206,10 @@ public static function getCustomFields(): array { //End group Positioning //Begin group Tooltip array( - 'name' => esc_html__( 'Marker Tooltip', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'marker_tooltip_info' + 'name' => esc_html__( 'Marker Tooltip', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'marker_tooltip_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'Show marker tooltip permanently', 'commonsbooking' ), @@ -215,9 +220,10 @@ public static function getCustomFields(): array { //End group Tooltip //Begin group popup array( - 'name' => esc_html__( 'Marker Popup', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'marker_popup_info' + 'name' => esc_html__( 'Marker Popup', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'marker_popup_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'show item availability', 'commonsbooking' ), @@ -251,9 +257,10 @@ public static function getCustomFields(): array { //End group popup //Begin group custom marker array( - 'name' => esc_html__( 'Custom Marker', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'custom_marker_info' + 'name' => esc_html__( 'Custom Marker', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'custom_marker_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'image file', 'commonsbooking' ), @@ -314,9 +321,10 @@ public static function getCustomFields(): array { //End group custom marker //Begin group cluster array( - 'name' => esc_html__( 'Cluster', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'cluster_info' + 'name' => esc_html__( 'Cluster', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'cluster_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'max. cluster radius', 'commonsbooking' ), @@ -370,9 +378,10 @@ public static function getCustomFields(): array { //End group cluster //Begin group Appearance array( - 'name' => esc_html__( 'Appearance by Item Status', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'item_status_appearance_info' + 'name' => esc_html__( 'Appearance by Item Status', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'item_status_appearance_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'appearance', 'commonsbooking' ), @@ -445,9 +454,10 @@ public static function getCustomFields(): array { //End group Appearance //Begin group Filters array( - 'name' => esc_html__( 'Filter for Users', 'commonsbooking' ), - 'type' => 'title', - 'id' => 'filter_info' + 'name' => esc_html__( 'Filter for Users', 'commonsbooking' ), + 'type' => 'title', + 'id' => 'filter_info', + 'classes' => 'map-organizer' ), array( 'name' => esc_html__( 'show location distance filter', 'commonsbooking' ), @@ -567,7 +577,7 @@ public static function getCustomFields(): array { 'id' => 'categories', 'type' => 'multicheck', 'desc' => commonsbooking_sanitizeHTML( __( 'The categories to be included in the filter group', 'commonsbooking' ) ), - 'options' => \CommonsBooking\Wordpress\CustomPostType\CustomPostType::sanitizeOptions ( Item::getTerms() ), + 'options' => \CommonsBooking\Wordpress\CustomPostType\CustomPostType::sanitizeOptions( Item::getTerms() ), 'select_all_button' => false, ), ), @@ -653,4 +663,20 @@ public function getArgs() { ); } + /** + * Renders the shortcode for the map + * + * TODO: Copy to clipboard button + */ + public static function getShortcode( array $field_args, CMB2_Field $field ) { + $id = get_the_ID(); + ?> + Shortcode: +
+ [cb_map id=] + +
+ Date: Wed, 14 Aug 2024 10:43:39 +0200 Subject: [PATCH 13/18] MAP-> CMB2: Fix tests & migration --- src/Service/Upgrade.php | 6 ++++-- src/Wordpress/CustomPostType/Map.php | 1 - tests/php/Service/UpgradeTest.php | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index 4c973104b..e648876bf 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -512,11 +512,13 @@ function ( $result, $option ) { array() ); foreach ( $options as $key => $value ) { - if ( empty( $value ) && isset( $defaultValues[ $key ] ) ) { + if ( empty( $value ) && ! empty( $defaultValues[ $key ] ) ) { //fetch from default values when key happens to be empty $value = $defaultValues[ $key ]; } - update_post_meta( $map->ID, $key, $value ); + if ( ! empty( $value ) ) { + update_post_meta( $map->ID, $key, $value ); + } } if ( ! empty( $options['custom_marker_media_id'] ) ) { // write the image url to the metabox, this way CMB2 can properly display it diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index b9ee48906..8ef6b25c1 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -666,7 +666,6 @@ public function getArgs() { /** * Renders the shortcode for the map * - * TODO: Copy to clipboard button */ public static function getShortcode( array $field_args, CMB2_Field $field ) { $id = get_the_ID(); diff --git a/tests/php/Service/UpgradeTest.php b/tests/php/Service/UpgradeTest.php index e2b935e1f..4ae1e75fe 100644 --- a/tests/php/Service/UpgradeTest.php +++ b/tests/php/Service/UpgradeTest.php @@ -288,7 +288,7 @@ public function testMigrateMapSettings() { Upgrade::migrateMapSettings(); //each option should now have it's own meta entry foreach ( $mapOptions as $key => $value ) { - if ( $key === 'cb_items_available_categories' ) { + if ( $key === 'cb_items_available_categories' || empty($value)) { continue; } $this->assertEquals( $value, get_post_meta( $oldMapId, $key, true ) ); @@ -333,7 +333,7 @@ public function testMigrateMapSettings() { ), ); - $this->assertEquals( $expectedFilterCategories, get_post_meta( $oldMapId, 'cb_items_available_categories', true ) ); + $this->assertEquals( $expectedFilterCategories, get_post_meta( $oldMapId, 'filtergroups', true ) ); //assert, that custom markup has been moved $expectedMarkup = 'Zum Strampeln'; $this->assertEquals( $expectedMarkup, get_term_meta( $manualPowerCat, COMMONSBOOKING_METABOX_PREFIX . 'markup', true ) ); From 13d416c744bee8a0acc62d9ba9e594dbfa0218c3 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:13:46 +0200 Subject: [PATCH 14/18] MAP-> CMB2: cleanup & tests --- src/Model/Map.php | 68 ++--------- tests/php/Model/MapTest.php | 64 +++++++++++ tests/php/Wordpress/CustomPostTypeTest.php | 126 ++++++++++++--------- 3 files changed, 146 insertions(+), 112 deletions(-) create mode 100644 tests/php/Model/MapTest.php diff --git a/src/Model/Map.php b/src/Model/Map.php index a19ca5ac3..6aefd5b21 100644 --- a/src/Model/Map.php +++ b/src/Model/Map.php @@ -2,36 +2,30 @@ namespace CommonsBooking\Model; -use CommonsBooking\Helper\Helper; use CommonsBooking\Repository\Item; use CommonsBooking\Repository\Timeframe; use CommonsBooking\Wordpress\CustomPostType\Location; use Exception; /** - * This class currently does not have any functionality. - * It's just a placeholder for the Map post type. - * Because the map feature was taken from another plugin, it is not yet adapted to the structure of this plugin. - * This class will be used to adapt the map feature to the structure of this plugin. + * This class does the heavy lifting for the map shortcode + * Code style differs because it has been taken from the fLotte Map shortcode plugin * - * Currently, it's only referenced by the @see \CommonsBooking\Wordpress\CustomPostType\CustomPostType::getModel() method to use the methods from the CustomPost class. */ class Map extends CustomPost { /** * get geo data from location metadata * - * @param $cb_map_id - * @param $mapItemTerms + * @param $mapItemTerms array of term ids * - * @return array + * @return array with postIDs as keys for an array with location data relevant for the map * @throws Exception */ - public function get_locations( $mapItemTerms ): array { + public function get_locations( array $mapItemTerms ): array { $locations = []; - $show_location_contact = $this->getMeta( 'show_location_contact' ); - $show_location_opening_hours = $this->getMeta( 'show_location_opening_hours' ); + $show_location_contact = $this->getMeta( 'show_location_contact' ); $preset_categories = $this->getMeta( 'cb_items_preset_categories' ); $preset_location_categories = $this->getMeta( 'cb_locations_preset_categories' ); @@ -166,11 +160,6 @@ function ( $item ) { $locations[ $post->ID ]['contact'] = $location_meta[ COMMONSBOOKING_METABOX_PREFIX . 'location_contact' ][0]; } } - - //@TODO: Check field -> we don't have such a field at the moment. -// if ($show_location_opening_hours) { -// $locations[$post->ID]['opening_hours'] = $location_meta['commons-booking_location_openinghours'][0]; -// } } return $locations; @@ -187,8 +176,8 @@ function ( $item ) { public static function cleanup_location_data_entry( $value, $linebreak_replacement ) { if ( is_string( $value ) ) { + $value = wp_strip_all_tags( $value ); //strip all tags $value = preg_replace( '/(\r\n)|\n|\r/', $linebreak_replacement, $value ); //replace linebreaks - $value = preg_replace( '/<.*(.*?)/', '', $value ); //strip off everything that smell's like HTML } if ( is_array( $value ) ) { @@ -220,50 +209,9 @@ public static function cleanup_location_data( $locations, $linebreak_replacement /** * basic check if the given string is valid JSON **/ - public static function is_json( $string ) { + public static function is_json( $string ): bool { json_decode( $string ); return ( json_last_error() == JSON_ERROR_NONE ); } - - /** - * load all timeframes from db (that end in the future and it's item's status is 'publish') - **/ - public function get_timeframes() { - $timeframes = Timeframe::getBookableForCurrentUser( - [], - [], - false, - true, - Helper::getLastFullHourTimestamp() - ); - - /** @var \CommonsBooking\Model\Timeframe $timeframe */ - foreach ( $timeframes as $timeframe ) { - //TODO #507 - $item = $timeframe->getItem(); - $location = $timeframe->getLocation(); - - if ( $item && $location ) { - $item_desc = $item->getMeta( COMMONSBOOKING_METABOX_PREFIX . 'location_info' ); - $thumbnail = get_the_post_thumbnail_url( $item, 'thumbnail' ); - - $result[] = [ - 'location_id' => $timeframe->getLocationID(), - 'item' => [ - 'id' => $item->ID, - 'name' => $item->post_title, - 'short_desc' => $item_desc, - 'link' => get_permalink( $item ), - 'thumbnail' => $thumbnail ?: null, - 'status' => $item->post_status, - ], - 'date_start' => $timeframe->getStartDate(), - 'date_end' => $timeframe->getEndDate(), - ]; - } - } - - return $result; - } } \ No newline at end of file diff --git a/tests/php/Model/MapTest.php b/tests/php/Model/MapTest.php new file mode 100644 index 000000000..ba8d586dd --- /dev/null +++ b/tests/php/Model/MapTest.php @@ -0,0 +1,64 @@ +map->get_locations( [] ); + $this->assertIsArray( $locations ); + $this->assertNotEmpty( $locations ); + $this->assertArrayHasKey( $this->geoLocation->ID, $locations ); + $this->assertEquals( 50.9413035, $locations[ $this->geoLocation->ID ]['lat'] ); + $this->assertEquals( 6.9581379978318, $locations[ $this->geoLocation->ID ]['lon'] ); + $this->assertEquals( "Location with Geo", $locations[ $this->geoLocation->ID ]['location_name'] ); + $this->assertEquals( "Domkloster 4", $locations[ $this->geoLocation->ID ]['address']['street'] ); + $this->assertEquals( "Köln", $locations[ $this->geoLocation->ID ]['address']['city'] ); + $this->assertEquals( "50667", $locations[ $this->geoLocation->ID ]['address']['zip'] ); + + $this->assertEquals( $this->itemId, $locations[ $this->geoLocation->ID ]['items'][0]['id'] ); + } + + public function testIs_json() { + //valid JSON string + $this->assertTrue( Map::is_json( '{"key":"value"}' ) ); + //invalid JSON string + $this->assertFalse( Map::is_json( '{"key":"value"' ) ); + + } + + public function testCleanup_location_data() { + ClockMock::freeze( new \DateTime( self::CURRENT_DATE ) ); + update_post_meta( $this->geoLocation->ID, COMMONSBOOKING_METABOX_PREFIX . 'location_contact', "Contact with HTML and \n linebreaks" ); + update_post_meta( $this->map->ID, 'show_location_contact', 'on' ); + $locations = $this->map->get_locations( [] ); + $this->assertNotEmpty( $locations ); + $locations = Map::cleanup_location_data( $locations, '
' ); + $this->assertEquals( "Contact with HTML and
linebreaks", $locations[ $this->geoLocation->ID ]['contact'] ); + } + + protected function setUp(): void { + parent::setUp(); + $this->map = new Map ( $this->createMap() ); + $this->geoLocation = new Location ( $this->createLocation( "Location with Geo" ) ); + update_post_meta( $this->geoLocation->ID, 'geo_latitude', 50.9413035 ); + update_post_meta( $this->geoLocation->ID, 'geo_longitude', 6.9581379978318 ); + update_post_meta( $this->geoLocation->ID, COMMONSBOOKING_METABOX_PREFIX . 'location_city', 'Köln' ); + update_post_meta( $this->geoLocation->ID, COMMONSBOOKING_METABOX_PREFIX . 'location_country', 'Deutschland' ); + update_post_meta( $this->geoLocation->ID, COMMONSBOOKING_METABOX_PREFIX . 'location_street', 'Domkloster 4' ); + update_post_meta( $this->geoLocation->ID, COMMONSBOOKING_METABOX_PREFIX . 'location_postcode', '50667' ); + $this->createBookableTimeFrameIncludingCurrentDay( $this->geoLocation->ID ); + } + + +} diff --git a/tests/php/Wordpress/CustomPostTypeTest.php b/tests/php/Wordpress/CustomPostTypeTest.php index 2097ac95b..f3c9ccd25 100644 --- a/tests/php/Wordpress/CustomPostTypeTest.php +++ b/tests/php/Wordpress/CustomPostTypeTest.php @@ -90,22 +90,20 @@ protected function createTimeframe( update_post_meta( $timeframeId, 'type', $type ); // we need to map the multi-location array and multi-item array on a string array because that is the way it is also saved from the WP-backend - if ( is_array($locationId) ) { + if ( is_array( $locationId ) ) { update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_LOCATION_ID_LIST, - array_map('strval',$locationId )); - } - else { + array_map( 'strval', $locationId ) ); + } else { update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_LOCATION_ID, $locationId ); } - if (is_array($itemId)) { + if ( is_array( $itemId ) ) { update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_ITEM_ID_LIST, - array_map('strval', $itemId )); - } - else { + array_map( 'strval', $itemId ) ); + } else { update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_ITEM_ID, $itemId ); @@ -125,11 +123,11 @@ protected function createTimeframe( update_post_meta( $timeframeId, 'end-time', $endTime ); update_post_meta( $timeframeId, 'grid', $grid ); update_post_meta( $timeframeId, 'weekdays', $weekdays ); - update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_MANUAL_SELECTION, $manualSelectionDays); + update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_MANUAL_SELECTION, $manualSelectionDays ); update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_SHOW_BOOKING_CODES, $showBookingCodes ); update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_CREATE_BOOKING_CODES, $createBookingCodes ); //TODO: Make this value configurable - update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_ITEM_SELECTION_TYPE, \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID); + update_post_meta( $timeframeId, \CommonsBooking\Model\Timeframe::META_ITEM_SELECTION_TYPE, \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID ); $this->timeframeIds[] = $timeframeId; @@ -193,7 +191,7 @@ protected function createUnconfirmedBookingEndingTomorrow() { $this->locationId, $this->itemId, strtotime( '-1 day', strtotime( self::CURRENT_DATE ) ), - strtotime( '+2 days midnight', strtotime( self::CURRENT_DATE ) ) - 1, + strtotime( '+2 days midnight', strtotime( self::CURRENT_DATE ) ) - 1, null, null, 'unconfirmed' @@ -242,6 +240,7 @@ protected function createBooking( /** * This method is Unit Test specific. Because we need to flush the cache after cancelling. + * * @param \CommonsBooking\Model\Booking $b * * @return void @@ -258,18 +257,20 @@ protected function getEndOfDayTimestamp( $date ) { /** * Creates booking from midnight -> +2 days (relative to self::CURRENT_DATE) + * * @param $locationId * @param $itemId * * @return int|\WP_Error */ - protected function createConfirmedBookingStartingToday($locationId = null, $itemId = null) { + protected function createConfirmedBookingStartingToday( $locationId = null, $itemId = null ) { if ( $locationId === null ) { $locationId = $this->locationId; } if ( $itemId === null ) { $itemId = $this->itemId; } + return $this->createBooking( $locationId, $itemId, @@ -280,18 +281,20 @@ protected function createConfirmedBookingStartingToday($locationId = null, $item /** * Creates timeframe from -1 day -> +1 day (relative to self::CURRENT_DATE) + * * @param $locationId * @param $itemId * * @return int|\WP_Error */ - protected function createBookableTimeFrameIncludingCurrentDay($locationId = null, $itemId = null) { + protected function createBookableTimeFrameIncludingCurrentDay( $locationId = null, $itemId = null ) { if ( $locationId === null ) { $locationId = $this->locationId; } if ( $itemId === null ) { $itemId = $this->itemId; } + return $this->createTimeframe( $locationId, $itemId, @@ -301,7 +304,7 @@ protected function createBookableTimeFrameIncludingCurrentDay($locationId = null } protected function createHolidayTimeframeForAllItemsAndLocations() { - $timeframe = $this->createTimeframe( + $timeframe = $this->createTimeframe( $this->locationId, "", strtotime( '-1 day', strtotime( self::CURRENT_DATE ) ), @@ -319,7 +322,8 @@ protected function createHolidayTimeframeForAllItemsAndLocations() { \CommonsBooking\Model\Timeframe::SELECTION_ALL_ID ); //and run our function to update the information - \CommonsBooking\Wordpress\CustomPostType\Timeframe::manageTimeframeMeta($timeframe); + \CommonsBooking\Wordpress\CustomPostType\Timeframe::manageTimeframeMeta( $timeframe ); + return $timeframe; } @@ -333,7 +337,7 @@ protected function createHolidayTimeframeForAllItemsAndLocations() { * * @return array An array where the first element is the 10:00-15:00 timeframe and the second is the 15:00 - 18:00 timeframe. */ - protected function createTwoBookableTimeframeSlotsIncludingCurrentDay( $locationId = null, $itemId = null): array { + protected function createTwoBookableTimeframeSlotsIncludingCurrentDay( $locationId = null, $itemId = null ): array { if ( $locationId === null ) { $locationId = $this->locationId; } @@ -368,23 +372,26 @@ protected function createTwoBookableTimeframeSlotsIncludingCurrentDay( $location "publish", '', ); + return [ $tf1, $tf2 ]; } /** * Creates timeframe from +7 days -> +30 days (relative to self::CURRENT_DATE) + * * @param $locationId * @param $itemId * * @return int|\WP_Error */ - protected function createBookableTimeFrameStartingInAWeek($locationId = null, $itemId = null) { + protected function createBookableTimeFrameStartingInAWeek( $locationId = null, $itemId = null ) { if ( $locationId === null ) { $locationId = $this->locationId; } if ( $itemId === null ) { $itemId = $this->itemId; } + return $this->createTimeframe( $locationId, $itemId, @@ -394,7 +401,7 @@ protected function createBookableTimeFrameStartingInAWeek($locationId = null, $i } // Create Item - protected function createItem($title, $postStatus = 'publish', $admins = [], $postAuthor = self::USER_ID) { + protected function createItem( $title, $postStatus = 'publish', $admins = [], $postAuthor = self::USER_ID ) { $itemId = wp_insert_post( [ 'post_title' => $title, 'post_type' => Item::$postType, @@ -404,7 +411,7 @@ protected function createItem($title, $postStatus = 'publish', $admins = [], $po $this->itemIds[] = $itemId; - if (! empty($admins)) { + if ( ! empty( $admins ) ) { update_post_meta( $itemId, COMMONSBOOKING_METABOX_PREFIX . 'item_admins', $admins ); } @@ -412,7 +419,7 @@ protected function createItem($title, $postStatus = 'publish', $admins = [], $po } // Create Location - protected function createLocation($title, $postStatus = 'publish', $admins = [], $postAuthor = self::USER_ID) { + protected function createLocation( $title, $postStatus = 'publish', $admins = [], $postAuthor = self::USER_ID ) { $locationId = wp_insert_post( [ 'post_title' => $title, 'post_type' => Location::$postType, @@ -422,21 +429,40 @@ protected function createLocation($title, $postStatus = 'publish', $admins = [], $this->locationIds[] = $locationId; - if (! empty($admins)) { + if ( ! empty( $admins ) ) { update_post_meta( $locationId, COMMONSBOOKING_METABOX_PREFIX . 'location_admins', $admins ); } return $locationId; } - protected function createMap($options) { + protected function createMap( $options = null ) { $mapId = wp_insert_post( [ 'post_title' => 'Map', 'post_type' => Map::$postType, 'post_status' => 'publish' ] ); - update_post_meta( $mapId, 'cb_map_options', $options ); + //TODO: This is the old map format, remove old tests that are dependent on it + if ( $options != null ) { + update_post_meta( $mapId, 'cb_map_options', $options ); + } else { + //setup map in new format + $defaultValues = array_reduce( + Map::getCustomFields(), + function ( $result, $option ) { + if ( isset( $option['default'] ) ) { + $result[ $option['id'] ] = $option['default']; + } + + return $result; + }, + array() + ); + foreach ( $defaultValues as $key => $value ) { + update_post_meta( $mapId, $key, $value ); + } + } $this->mapIds[] = $mapId; @@ -448,12 +474,11 @@ protected function createMap($options) { * In that case, the unit tests would fail, because there is already the user with this ID in the database. * @return void */ - protected function createSubscriber(){ - $wp_user = get_user_by('email',"a@a.de"); - if (! $wp_user){ - $this->subscriberId = wp_create_user("normaluser","normal","a@a.de"); - } - else { + protected function createSubscriber() { + $wp_user = get_user_by( 'email', "a@a.de" ); + if ( ! $wp_user ) { + $this->subscriberId = wp_create_user( "normaluser", "normal", "a@a.de" ); + } else { $this->subscriberId = $wp_user->ID; } } @@ -463,14 +488,13 @@ protected function createSubscriber(){ * In that case, the unit tests would fail, because there is already the user with this ID in the database. * @return void */ - public function createAdministrator(){ - $wp_user = get_user_by('email',"admin@admin.de"); - if (! $wp_user) { + public function createAdministrator() { + $wp_user = get_user_by( 'email', "admin@admin.de" ); + if ( ! $wp_user ) { $this->adminUserID = wp_create_user( "adminuser", "admin", "admin@admin.de" ); - $user = new \WP_User( $this->adminUserID ); + $user = new \WP_User( $this->adminUserID ); $user->set_role( 'administrator' ); - } - else { + } else { $this->adminUserID = $wp_user->ID; } } @@ -479,47 +503,45 @@ public function createAdministrator(){ * We use this role to test assigning capabilities to other roles than the CBManager. * @return void */ - protected function createEditor(){ - $wp_user = get_user_by('email',"editor@editor.de"); - if (! $wp_user) { + protected function createEditor() { + $wp_user = get_user_by( 'email', "editor@editor.de" ); + if ( ! $wp_user ) { $this->editorUserID = wp_create_user( "editoruser", "editor", "editor@editor.de" ); $user = new \WP_User( $this->editorUserID ); $user->set_role( 'editor' ); - } - else { + } else { $this->editorUserID = $wp_user->ID; } } - public function createCBManager(){ + public function createCBManager() { //we need to run the functions that add the custom user role and assign it to the user Plugin::addCustomUserRoles(); //and add the caps for each of our custom post types Plugin::addCPTRoleCaps(); - $wp_user = get_user_by('email',"cbmanager@cbmanager.de"); - if (! $wp_user) { + $wp_user = get_user_by( 'email', "cbmanager@cbmanager.de" ); + if ( ! $wp_user ) { $this->cbManagerUserID = wp_create_user( "cbmanager", "cbmanager", "cbmanager@cbmanager.de" ); - $user = new \WP_User( $this->cbManagerUserID ); + $user = new \WP_User( $this->cbManagerUserID ); $user->set_role( Plugin::$CB_MANAGER_ID ); - } - else { + } else { $this->cbManagerUserID = $wp_user->ID; } } - protected function setUp() : void { + protected function setUp(): void { parent::setUp(); - $this->dateFormatted = date( 'Y-m-d', strtotime( self::CURRENT_DATE ) ); + $this->dateFormatted = date( 'Y-m-d', strtotime( self::CURRENT_DATE ) ); - $this->setUpBookingCodesTable(); + $this->setUpBookingCodesTable(); // Create location - $this->locationId = self::createLocation('Testlocation', 'publish'); + $this->locationId = self::createLocation( 'Testlocation', 'publish' ); // Create Item - $this->itemId = self::createItem('TestItem', 'publish'); + $this->itemId = self::createItem( 'TestItem', 'publish' ); } protected function setUpBookingCodesTable() { @@ -538,7 +560,7 @@ protected function setUpBookingCodesTable() { $wpdb->query( $sql ); } - protected function tearDown() : void { + protected function tearDown(): void { parent::tearDown(); ClockMock::reset(); From e817f1ff2e84ffa508cd421a22bec0b87e74a090 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:20:49 +0200 Subject: [PATCH 15/18] e2e tests: fix issue with doubled array key --- tests/cypress/wordpress-files/content-example.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/cypress/wordpress-files/content-example.xml b/tests/cypress/wordpress-files/content-example.xml index ddbd89965..a78695c13 100644 --- a/tests/cypress/wordpress-files/content-example.xml +++ b/tests/cypress/wordpress-files/content-example.xml @@ -1987,10 +1987,6 @@ 0 - - - - From bdb95549c7b4c25edd8d4a8f97a908be55f8c424 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:24:09 +0200 Subject: [PATCH 16/18] added styles --- assets/admin/sass/admin.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/assets/admin/sass/admin.scss b/assets/admin/sass/admin.scss index b8d5a5771..ce4951815 100644 --- a/assets/admin/sass/admin.scss +++ b/assets/admin/sass/admin.scss @@ -27,7 +27,10 @@ /* Booking form */ @import "./partials/form-booking"; -/* Booking form */ +/* Map creation */ +@import "./partials/form-map"; + +/* Plugin update page */ @import "./partials/plugin_update"; /* Edit Screens Backend */ From d916d85c530c52364d9716e271ebc5f11bca8968 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:21:58 +0200 Subject: [PATCH 17/18] MAP->CMB2: Correctly pass conditionals --- src/Map/MapData.php | 82 ++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/Map/MapData.php b/src/Map/MapData.php index 6342a50a6..d306b7a7a 100644 --- a/src/Map/MapData.php +++ b/src/Map/MapData.php @@ -185,68 +185,96 @@ public static function get_settings( $cb_map_id ): array { $pass_through = [ 'base_map', - 'show_scale', 'zoom_min', 'zoom_max', - 'scrollWheelZoom', 'zoom_start', 'lat_start', 'lon_start', + 'max_cluster_radius', + 'label_location_distance_filter', + 'label_item_availability_filter', + 'label_item_category_filter', + ]; + + $pass_through_conditional = [ + 'show_scale', + 'scrollWheelZoom', 'marker_map_bounds_initial', 'marker_map_bounds_filter', - 'max_cluster_radius', 'marker_tooltip_permanent', 'show_location_contact', 'show_location_opening_hours', 'show_item_availability', 'show_location_distance_filter', - 'label_location_distance_filter', 'show_item_availability_filter', - 'label_item_availability_filter', - 'label_item_category_filter', ]; - foreach ($pass_through as $key) { - $settings[$key] = $map->getMeta($key); + foreach ( $pass_through as $key ) { + $meta = $map->getMeta( $key ); + if ( is_numeric( $meta ) ) { + $meta = floatval( $meta ); + } + $settings[ $key ] = $meta; } - if ($map->getMeta('custom_marker_media_id')) { + foreach ( $pass_through_conditional as $key ) { + $meta = $map->getMeta( $key ); + if ( $meta == 'off' ) { + $settings[ $key ] = false; + } else { + $settings[ $key ] = boolval( $meta ); + } + } + + if ( $map->getMeta( 'custom_marker_media_id' ) ) { $settings['custom_marker_icon'] = [ - 'iconUrl' => wp_get_attachment_url($map->getMeta('custom_marker_media_id')), - 'iconSize' => [$map->getMeta('marker_icon_width'), $map->getMeta('marker_icon_height')], - 'iconAnchor' => [$map->getMeta('marker_icon_anchor_x'), $map->getMeta('marker_icon_anchor_y')], + 'iconUrl' => wp_get_attachment_url( $map->getMeta( 'custom_marker_media_id' ) ), + 'iconSize' => [ + intval( $map->getMeta( 'marker_icon_width' ) ), + intval( $map->getMeta( 'marker_icon_height' ) ) + ], + 'iconAnchor' => [ + intval( $map->getMeta( 'marker_icon_anchor_x' ) ), + intval( $map->getMeta( 'marker_icon_anchor_y' ) ) + ], ]; } - if ($map->getMeta('marker_item_draft_media_id')) { + if ( $map->getMeta( 'marker_item_draft_media_id' ) ) { $settings['item_draft_marker_icon'] = [ - 'iconUrl' => wp_get_attachment_url($map->getMeta('marker_item_draft_media_id')), - 'iconSize' => [$map->getMeta('marker_item_draft_icon_width'), $map->getMeta('marker_item_draft_icon_height')], - 'iconAnchor' => [$map->getMeta('marker_item_draft_icon_anchor_x'), $map->getMeta('marker_item_draft_icon_anchor_y')], + 'iconUrl' => wp_get_attachment_url( $map->getMeta( 'marker_item_draft_media_id' ) ), + 'iconSize' => [ + intval( $map->getMeta( 'marker_item_draft_icon_width' ) ), + intval( $map->getMeta( 'marker_item_draft_icon_height' ) ) + ], + 'iconAnchor' => [ + intval( $map->getMeta( 'marker_item_draft_icon_anchor_x' ) ), + intval( $map->getMeta( 'marker_item_draft_icon_anchor_y' ) ) + ], ]; } - if ($map->getMeta('custom_marker_cluster_media_id')) { + if ( $map->getMeta( 'custom_marker_cluster_media_id' ) ) { $settings['marker_cluster_icon'] = [ - 'url' => wp_get_attachment_url($map->getMeta('custom_marker_cluster_media_id')), + 'url' => wp_get_attachment_url( $map->getMeta( 'custom_marker_cluster_media_id' ) ), 'size' => [ - 'width' => $map->getMeta('marker_cluster_icon_width'), - 'height' => $map->getMeta('marker_cluster_icon_height'), + 'width' => intval( $map->getMeta( 'marker_cluster_icon_width' ) ), + 'height' => intval( $map->getMeta( 'marker_cluster_icon_height' ) ), ], ]; } //categories are only meant to be shown on local maps //TODO: Evaluate if it makes sense to only show them when categories are imported - if ($map->getMeta('cb_items_available_categories')) { + if ( $map->getMeta( 'cb_items_available_categories' ) ) { $settings['filter_cb_item_categories'] = []; - foreach ($map->getMeta('filtergroups') as $groupID => $group) { + foreach ( $map->getMeta( 'filtergroups' ) as $groupID => $group ) { $elements = []; - foreach ($group['categories'] as $termID) { - $term = get_term( $termID ); + foreach ( $group['categories'] as $termID ) { + $term = get_term( $termID ); $customMarkup = get_term_meta( $termID, COMMONSBOOKING_METABOX_PREFIX . 'markup', true ); - $termName = empty($customMarkup) ? $term->name : $customMarkup; + $termName = empty( $customMarkup ) ? $term->name : $customMarkup; $elements[] = [ 'cat_id' => intval( $termID ), @@ -254,8 +282,8 @@ public static function get_settings( $cb_map_id ): array { ]; } $settings['filter_cb_item_categories'][ $groupID ] = [ - 'name' => $group['name'], - 'elements' => $elements, + 'name' => $group['name'], + 'elements' => $elements, 'isExclusive' => $group['isExclusive'] == 'on', ]; } From 644d2bc41f4b589969cb508b6b9158150588ebf6 Mon Sep 17 00:00:00 2001 From: Hans Morbach <6433480+hansmorb@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:26:57 +0200 Subject: [PATCH 18/18] MAP->CMB2: Fix button submission issue --- src/Wordpress/CustomPostType/Map.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index 8ef6b25c1..4ff74e3fb 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -673,7 +673,7 @@ public static function getShortcode( array $field_args, CMB2_Field $field ) { Shortcode:
[cb_map id=] - +