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'] ) : '#';
?>