editor_script_handles ) ) { foreach ( $type->editor_script_handles as $handle ) { wp_set_script_translations( $handle, 'blockmason-core', DIR . 'languages' ); } } } } /** * Filters the "Projects of this service" Query Loop so it only shows the * projects linked to the service being viewed. * * @param array $query Query vars. * @param \WP_Block $block The Post Template block. * @return array */ function service_projects_query( $query, $block ) { if ( empty( $block->context['query']['bmRelatedToService'] ) ) { return $query; } $service_id = 0; if ( isset( $block->context['postType'], $block->context['postId'] ) && 'bm_service' === $block->context['postType'] ) { $service_id = (int) $block->context['postId']; } elseif ( is_singular( 'bm_service' ) ) { $service_id = (int) get_queried_object_id(); } if ( ! $service_id ) { // Not on a service: show nothing rather than unrelated projects. $query['post__in'] = array( 0 ); return $query; } $query['post_type'] = 'bm_project'; $query['meta_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Indexed meta key, small result set. array( 'key' => 'bm_services', 'value' => $service_id, 'type' => 'NUMERIC', ), ); return $query; } /** * Leaves the current post out of a Query Loop that sets "bmExcludeCurrent", * e.g. "More projects" under a single project. * * @param array $query Query vars. * @param WP_Block $block Query Loop block. * @return array */ function exclude_current_query( $query, $block ) { if ( empty( $block->context['query']['bmExcludeCurrent'] ) || ! is_singular() ) { return $query; } $exclude = isset( $query['post__not_in'] ) ? (array) $query['post__not_in'] : array(); $exclude[] = (int) get_queried_object_id(); $query['post__not_in'] = array_values( array_unique( array_filter( array_map( 'intval', $exclude ) ) ) ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- One ID, three results. $query['orderby'] = 'rand'; $query['no_found_rows'] = true; return $query; } /** * Formats a project area for display, e.g. "1,250 m²". * * @param float $area Area in square metres. * @return string */ function format_area( $area ) { $area = (float) $area; $decimals = floor( $area ) === $area ? 0 : 1; /* translators: %s: area in square metres. */ return sprintf( __( '%s m²', 'blockmason-core' ), number_format_i18n( $area, $decimals ) ); } /** * Resolves the post a block should read its fields from. * * @param \WP_Block $block Block instance. * @param string $post_type Expected post type. * @return int Post ID, or 0. */ function context_post_id( $block, $post_type ) { $post_id = isset( $block->context['postId'] ) ? (int) $block->context['postId'] : (int) get_the_ID(); return $post_id && get_post_type( $post_id ) === $post_type ? $post_id : 0; } /** * Hides a section with the class "blockmason-service-projects" on a service * that has no linked projects, so the page does not show an empty heading. * * @param string $block_content Rendered block. * @param array $block Parsed block. * @return string */ function hide_empty_service_projects( $block_content, $block ) { if ( empty( $block['attrs']['className'] ) || ! str_contains( $block['attrs']['className'], 'blockmason-service-projects' ) || ! is_singular( 'bm_service' ) ) { return $block_content; } $linked = get_posts( array( 'post_type' => 'bm_project', 'posts_per_page' => 1, 'fields' => 'ids', 'no_found_rows' => true, 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- One small lookup per service page. array( 'key' => 'bm_services', 'value' => (int) get_queried_object_id(), 'type' => 'NUMERIC', ), ), ) ); return $linked ? $block_content : ''; }