4 ], $atts, 'acc_recent_projects' ); $limit = max( 1, min( 12, (int) $atts['limit'] ) ); $projects = $this->get_recent_active_projects( $limit ); if ( empty( $projects ) ) { return '

' . esc_html__( 'No active projects found.', 'academiccrew' ) . '

'; } ob_start(); echo '
'; foreach ( $projects as $p ) { $this->render_row( $p ); } echo '
'; return ob_get_clean(); } // ------------------------------------------------------------------------- // Data // ------------------------------------------------------------------------- /** Active projects (no end date, or one still in the future), most recently started first. */ private function get_recent_active_projects( int $limit ): array { $all = get_posts( [ 'post_type' => 'acc_collaboration', 'post_status' => 'publish', 'posts_per_page' => -1, 'no_found_rows' => true, ] ); $today = current_time( 'Y-m-d' ); $active = array_values( array_filter( $all, static function ( \WP_Post $post ) use ( $today ) { $end = (string) get_post_meta( $post->ID, '_acc_end_date', true ); return '' === $end || $end >= $today; } ) ); usort( $active, static function ( \WP_Post $a, \WP_Post $b ) { $start_of = static fn( \WP_Post $p ): string => (string) get_post_meta( $p->ID, '_acc_start_date', true ) ?: '0000-00-00'; return strcmp( $start_of( $b ), $start_of( $a ) ) ?: strcasecmp( $a->post_title, $b->post_title ); } ); return array_map( [ $this, 'prepare' ], array_slice( $active, 0, $limit ) ); } private function prepare( \WP_Post $post ): array { $get = fn( string $k ) => get_post_meta( $post->ID, $k, true ); $start = (string) ( $get( '_acc_start_date' ) ?: '' ); $end = (string) ( $get( '_acc_end_date' ) ?: '' ); $kw = $get( '_acc_keywords' ); $start_y = $start ? (int) date_i18n( 'Y', strtotime( $start ) ) : 0; $end_y = $end ? (int) date_i18n( 'Y', strtotime( $end ) ) : 0; if ( $start_y && $end_y && $start_y !== $end_y ) { $year_range = $start_y . "\u{2013}" . $end_y; } elseif ( $start_y && $end_y ) { $year_range = (string) $start_y; } elseif ( $start_y ) { $year_range = $start_y . "\u{2013}" . __( 'ongoing', 'academiccrew' ); } else { $year_range = ''; } $linked_page = (int) get_post_meta( $post->ID, '_academiccrew_linked_page_id', true ); $url = $linked_page ? get_permalink( $linked_page ) : get_permalink( $post->ID ); $linked = (array) ( $get( '_acc_linked_members' ) ?: [] ); return [ 'title' => get_the_title( $post ), 'url' => (string) $url, 'type' => (string) ( $get( '_acc_project_type' ) ?: '' ), 'status' => ( $end && strtotime( $end ) < time() ) ? 'completed' : 'ongoing', 'keywords' => is_array( $kw ) ? array_values( $kw ) : [], 'year_range' => $year_range, 'pi_name' => CollaborationMeta::extract_pi_name( $linked ), 'short_desc' => (string) ( $get( '_acc_short_desc' ) ?: '' ), ]; } // ------------------------------------------------------------------------- // Markup — identical to the Featured Projects strip. // ------------------------------------------------------------------------- private function render_row( array $p ): void { $status_label = $p['status'] === 'ongoing' ? __( 'Ongoing', 'academiccrew' ) : __( 'Completed', 'academiccrew' ); $href = $p['url'] ? esc_url( $p['url'] ) : '#'; ?>
PI ·