8889841cPK[A/ý¯î%î%Base.phpnu„[µü¤ => [ 'match' => ] ] * * @see Tribe__Duplicate__Strategy_Factory for supported strategies * * @since TDB */ abstract protected function get_duplicate_post_fields(); /** * Returns an array of post custom fields that should be used to spot possible duplicates. * * @return array An array of post fields to matching strategy in the format * [ => [ 'match' => ] ] * * @see Tribe__Duplicate__Strategy_Factory for supported strategies * * @since TDB */ abstract protected function get_duplicate_custom_fields(); /** * Finds posts of the type managed by the class that contain the search string. * * The method will search in the post and custom fields defined by the class. * * @param string $search * * @return array|bool An array of post IDs or `false` if nothing was found. * * @see get_duplicate_post_fields() * @see get_duplicate_custom_fields() * * @since TDB */ public function find_like( $search ) { /** @var Tribe__Cache $cache */ $cache = tribe( 'cache' ); $components = [ __CLASS__, __FUNCTION__, $search ]; $cache_key = $cache->make_key( $components ); if ( $cached = $cache[ $cache_key ] ) { return $cached; } $post_fields = $this->get_duplicate_post_fields(); $post_fields = array_combine( array_keys( $post_fields ), array_fill( 0, count( $post_fields ), [ 'match' => 'like' ] ) ); $custom_fields = $this->get_duplicate_custom_fields(); $custom_fields = array_combine( array_keys( $custom_fields ), array_fill( 0, count( $custom_fields ), [ 'match' => 'like' ] ) ); /** @var Tribe__Duplicate__Post $duplicates */ $duplicates = tribe( 'post-duplicate' ); $duplicates->set_post_type( $this->post_type ); $duplicates->use_post_fields( $post_fields ); $duplicates->use_custom_fields( $custom_fields ); $duplicates->set_where_operator( 'OR' ); $merged = array_merge( $post_fields, $custom_fields ); $data = array_combine( array_keys( $merged ), array_fill( 0, count( $merged ), $search ) ); $found = $duplicates->find_all_for( $data ); $cache[ $cache_key ] = $found; return $found; } /** * Returns posts linked to the specified event. * * @param int|WP_Post $event_id * * @return array An array of matching post IDs. * * @since 4.6 */ public function find_for_event( $event_id ) { /** @var Tribe__Cache $cache */ $cache = tribe( 'cache' ); $components = [ __CLASS__, __FUNCTION__, $event_id ]; $cache_key = $cache->make_key( $components ); if ( $cached = $cache[ $cache_key ] ) { return $cached; } /** @var wpdb $wpdb */ global $wpdb; $event_id = Tribe__Main::post_id_helper( $event_id ); if ( empty( $event_id ) ) { return []; } $query = "SELECT pm.meta_value FROM {$wpdb-> posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = %s AND pm.post_id = %d AND meta_key = %s"; $prepared = $wpdb->prepare( $query, Tribe__Events__Main::POSTTYPE, $event_id, $this->event_meta_key ); $results = $wpdb->get_col( $prepared ); if ( empty( $results ) ) { return []; } $found = array_map( 'intval', $results ); $cache[ $cache_key ] = $found; return $found; } /** * Returns an array of posts that have events, past or future, linked to them. * * @param bool $has_events Whether to look for posts with linked events or not. * @param array $excluded_post_stati An array of post stati that should not be * considered for the purpose of marking a post * as "with events". * * @return array An array of matching post IDs. * * @since 4.6 */ public function find_with_events( $has_events = true, $excluded_post_stati = null ) { /** @var Tribe__Cache $cache */ $cache = tribe( 'cache' ); $function_args = func_get_args(); $components = array_merge( [ __CLASS__, __FUNCTION__ ], $function_args ); $cache_key = $cache->make_key( $components ); if ( $cached = $cache[ $cache_key ] ) { return $cached; } $has_events = tribe_is_truthy( $has_events ); if ( null === $excluded_post_stati ) { $excluded_post_stati = [ 'pending', 'draft' ]; } /** * Filters the post stati that should be excluded when looking for venues with events. * * By default if an event is linked to a venue but in "pending" or "draft" status that venue * will not be marked as having events. * * @param array $excluded_post_stati * * * @since 4.6 */ $excluded_post_stati = apply_filters( "tribe_{$this->post_type}_has_events_excluded_post_stati", $excluded_post_stati ); /** @var wpdb $wpdb */ global $wpdb; $post_status_clause = ''; if ( ! empty( $excluded_post_stati ) ) { $excluded_post_stati_in = []; foreach ( $excluded_post_stati as $status ) { $excluded_post_stati_in[] = $wpdb->prepare( '%s', $status ); } $excluded_post_stati_in = implode( ',', $excluded_post_stati_in ); $post_status_clause = "AND p.post_status NOT IN ({$excluded_post_stati_in})"; } $has_events_query = "SELECT DISTINCT pm.meta_value FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = %s {$post_status_clause} AND meta_key = %s"; $prepared_has_events_query = $wpdb->prepare( $has_events_query, Tribe__Events__Main::POSTTYPE, $this->event_meta_key ); $results = $wpdb->get_col( $prepared_has_events_query ); if ( ! $has_events ) { $query = "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s"; $prepared = $wpdb->prepare( $query, $this->post_type ); $venues = $wpdb->get_col( $prepared ); if ( empty( $venues ) ) { $cache[ $cache_key ] = []; return []; } $found = array_diff( $venues, $results ); if ( empty( $found ) ) { $cache[ $cache_key ] = []; return []; } } else { $found = $results; } $found = array_map( 'intval', array_values( $found ) ); $cache[ $cache_key ] = $found; return $found; } /** * Finds posts of the type managed by the class that are related to upcoming events. * * @param bool $only_with_upcoming * @param null|string|array $event_post_status Only fetch events with the defined post status or stati; * will default to the post status set according to the current * user capabilities if not provided. * * @return array|bool An array of post IDs or `false` if nothing was found. * * @since TDB */ public function find_with_upcoming_events( $only_with_upcoming = true, $event_post_status = null ) { /** @var Tribe__Cache $cache */ $cache = tribe( 'cache' ); $components = [ __CLASS__, __FUNCTION__, $only_with_upcoming ]; $cache_key = $cache->make_key( $components ); if ( $cached = $cache[ $cache_key ] ) { return $cached; } $only_with_upcoming = tribe_is_truthy( $only_with_upcoming ); $args = [ 'fields' => 'ids', 'start_date' => date( Tribe__Date_Utils::DBDATETIMEFORMAT, time() ), ]; if ( null !== $event_post_status ) { $args['post_status'] = $event_post_status; } $events = tribe_get_events( $args ); if ( empty( $events ) ) { $cache[ $cache_key ] = []; return []; } /** @var wpdb $wpdb */ global $wpdb; $events_in = implode( ',', $events ); $in_clause = $only_with_upcoming ? "WHERE p.ID IN ({$events_in})" : "WHERE p.ID NOT IN ({$events_in})"; $query = "SELECT pm.meta_value FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id {$in_clause} AND pm.meta_key = %s"; $prepared = $wpdb->prepare( $query, $this->event_meta_key ); $found = $wpdb->get_col( $prepared ); if ( ! $only_with_upcoming ) { $without_events = $this->find_with_events( false ); $found = array_unique( array_merge( $found, $without_events ) ); } if ( empty( $found ) ) { $cache[ $cache_key ] = []; return []; } $found = array_map( 'intval', $found ); $cache[ $cache_key ] = $found; return $found; } /** * Prefixes a key with the correct meta key prefix if needed. * * @param string $key * * @return string * * @since TDB */ protected function prefix_key( $key ) { if ( 0 !== strpos( $key, $this->meta_prefix ) && in_array( $key, static::$meta_keys, true ) ) { return $this->meta_prefix . $key; } return $key; } /** * Builds and returns a closure to lazily fetch an Event linked posts. * * @since 4.9.7 * * @param int $event The event post ID or object. * * @return callable A closure that will fetch an Event linked posts; the default implementation will return a * closure returning an empty array. */ public static function get_fetch_callback( $event ){ return '__return_empty_array'; } } PK['{…+…+Chooser_Meta_Box.phpnu„[µü¤tribe = Tribe__Events__Main::instance(); $this->linked_posts = Tribe__Events__Linked_Posts::instance(); $this->post_type = $post_type; $this->singular_name = $this->linked_posts->linked_post_types[ $this->post_type ]['singular_name']; $this->singular_name_lowercase = $this->linked_posts->linked_post_types[ $this->post_type ]['singular_name_lowercase']; $this->get_event( $event ); add_action( 'wp', [ $this, 'sticky_form_data' ], 50 ); // Later than events-admin.js itself is enqueued } /** * Work with the specified event object or else use a placeholder if in the middle of creating a new event. * * @param mixed $event */ protected function get_event( $event = null ) { if ( is_null( $event ) ) { $event = $GLOBALS['post']; } if ( is_numeric( $event ) ) { $event = WP_Post::get_instance( $event ); } if ( $event instanceof stdClass || is_array( $event ) ) { $event = new WP_Post( (object) $event ); } if ( ! $event instanceof WP_Post ) { $event = new WP_Post( (object) [ 'ID' => 0 ] ); } $this->event = $event; } /** * Render the chooser section for the events meta box */ public function render() { $this->render_dropdowns(); $this->render_add_post_button(); /** * Make this Template filterable, used for Community Facing templates. * * @param string $file_path */ include apply_filters( 'tribe_events_multiple_linked_post_template', $this->tribe->pluginPath . 'src/admin-views/linked-post-meta-box.php' ); } /** * Displays the saved linked post dropdown in the event metabox. * * @since 3.0 * @since 4.5.11 Genericized to work for all linked posts, not just organizers like it was originally. */ public function render_dropdowns() { $post_id = $this->event->ID; $current_linked_post_meta_key = $this->linked_posts->get_meta_key( $this->post_type ); $current_linked_posts = get_post_meta( $post_id, $current_linked_post_meta_key, false ); if ( $this->post_type === Tribe__Events__Organizer::POSTTYPE ) { $current_linked_posts = tribe_get_organizer_ids( $post_id ); } /** * Allows for filtering the array of values retrieved for a specific linked post meta field. * * Name of filter is assembled as tribe_events_linked_post_meta_values_{$current_linked_post_meta_key}, where * $current_linked_post_meta_key is just literally the name of the current meta key. So when the _EventOrganizerID * is being filtered, for example, the filter name would be tribe_events_linked_post_meta_values__EventOrganizerID * * @since 4.5.11 * * @param array $current_linked_posts The array of the current meta field's values. * @param int $post_id The current event's post ID. */ $current_linked_posts = apply_filters( "tribe_events_linked_post_meta_values_{$current_linked_post_meta_key}", $current_linked_posts, $post_id ); if ( $this->use_default_post( $current_linked_posts ) ) { /** * Filters the default selected post for the linked post * * @param array $default Default post array * @param string $post_type Linked post post type */ $current_linked_posts = apply_filters( 'tribe_events_linked_post_default', [], $this->post_type ); } /** * Filters the default selected post for the linked post. * * @param array $current_linked_posts Array of currently linked posts * @param string $post_type Linked post post type */ $current_linked_posts = (array) apply_filters( 'tribe_display_event_linked_post_dropdown_id', $current_linked_posts, $this->post_type ); /* if the user can't create posts of the linked type, then remove any empty values from the $current_linked_posts array. This prevents the automatic selection of a post every time the event is edited. */ $linked_post_pto = get_post_type_object( $this->post_type ); if ( ! current_user_can( $linked_post_pto->cap->create_posts ) ) { $current_linked_posts = array_filter( $current_linked_posts ); } ?>maybe_parse_candidate_linked_posts( $current_linked_posts ); $current_linked_posts = array_values( $current_linked_posts ); $i = 0; $num_records = count( $current_linked_posts ); do { echo ''; $this->single_post_dropdown( isset( $current_linked_posts[ $i ] ) ? $current_linked_posts[ $i ] : 0 ); echo ''; $i++; } while ( $i < $num_records ); } /** * Render a single row of the linked post's table * * @since 3.0 * * @param int $linked_post_id */ protected function single_post_dropdown( $linked_post_id ) { $linked_post_type_container = $this->linked_posts->get_post_type_container( $this->post_type ); ?> move_handle(); ?> linked_posts->saved_linked_post_dropdown( $this->post_type, $linked_post_id ); $this->edit_post_link( $linked_post_id ); if ( ! empty( $this->linked_posts->linked_post_types[ $this->post_type ]['allow_multiple'] ) ) { $this->delete_handle(); } ?> post_type ); // Bail if the user is unable to edit the type of post. if ( empty( $linked_post_pto->cap->edit_others_posts ) || ! current_user_can( $linked_post_pto->cap->edit_others_posts ) ) { return; } $edit_link = get_edit_post_link( $linked_post_id ); // Bail if $edit_link is empty. if ( empty( $edit_link ) ) { return; } printf( '
%3$s
', esc_attr( empty( $linked_post_id ) ? 'display: none;' : 'display: inline-block;' ), esc_url( $edit_link ), sprintf( esc_html__( 'Edit %s', 'the-events-calendar' ), esc_html( $this->singular_name ) ) ); } /** * Determine if the event can use the default setting * * @param array $current_posts * @return bool */ protected function use_default_post( $current_posts ) { if ( ! empty( $current_posts ) ) { return false; // the event already has linked post(s) } if ( ! empty( $this->event->ID ) && get_post_status( $this->event->ID ) != 'auto-draft' ) { return false; // the event has already been saved } if ( is_admin() ) { return Tribe__Admin__Helpers::instance()->is_action( 'add' ); } return true; // a front-end submission form (e.g., community) } /** * Renders the "Add Another Organizer" button */ protected function render_add_post_button() { if ( empty( $this->linked_posts->linked_post_types[ $this->post_type ]['allow_multiple'] ) ) { return; } $classes = [ 'tribe-add-post' ]; if ( is_admin() ) { $classes[] = 'button'; } else { $classes[] = 'tribe-button'; $classes[] = 'tribe-button-secondary'; } ?> singular_name_lowercase ) ); ?> '; } /** * Renders the handle for deleting a linked post * * @since 3.0 */ protected function delete_handle() { ?> get_post_type_container( $this->post_type ); if ( empty( $_POST[ $container ] ) || ! is_array( $_POST[ $container ] ) ) { return; } foreach ( $_POST[ $container ] as $field => $set_of_values ) { if ( ! is_array( $set_of_values ) ) { continue; } foreach ( $set_of_values as $index => $value ) { if ( ! isset( $submitted_data[ $index ] ) ) { $submitted_data[ $index ] = []; } $submitted_data[ $index ][ $field ] = esc_attr( $value ); } } wp_localize_script( 'tribe-events-admin', 'tribe_sticky_' . $this->post_type . '_fields', $submitted_data ); } /** * Parse candidate linked posts. * * @param $current_linked_posts * @return mixed */ private function maybe_parse_candidate_linked_posts( array $current_linked_posts = [] ) { $linked_post_type_container = $this->linked_posts->get_post_type_container( $this->post_type ); // filter out any non-truthy values $current_linked_posts = array_filter( $current_linked_posts ); // We don't have any items $has_no_current_linked_posts = empty( $current_linked_posts ); $submitted_data_contains_candidate_linked_posts = ! empty( $_POST[ $linked_post_type_container ] ); if ( $has_no_current_linked_posts && $submitted_data_contains_candidate_linked_posts ) { $candidate_linked_posts = $_POST[ $linked_post_type_container ]; $linked_post_type_id_field = $this->linked_posts->get_post_type_id_field_index( $this->post_type ); if ( ! empty( $candidate_linked_posts[ $linked_post_type_id_field ] ) ) { $candidate_linked_posts = $candidate_linked_posts[ $linked_post_type_id_field ]; return $candidate_linked_posts; } return $current_linked_posts; } return $current_linked_posts; } } PK[A/ý¯î%î%Base.phpnu„[µü¤PK['{…+…+&&Chooser_Meta_Box.phpnu„[µü¤PKœïQ