چیدن پست‌های وردپرس براساس تاریخ به صورت نزولی، صعودی همزمان

تو یکی از پروژه‌های اخیر که مربوط به یک سایت رویداد محور بود(کلاس‌های دیجیتال مارکتینگ)، باید رویدادها رو به صورت نزولی و به ترتیب تاریخ مرتب میکردم و در عین حال پست‌هایی که هنوز منقضی نشدن(رویدادهای پیشرو) به ترتیب تاریخ باشن ولی صعودی، یعنی نزدینک‌ترین رویداد اول بیاد. به این شکل:

مثلا امروز 9 خرداد هست. ترتیب باید این شکلی میشد:

Events Order:

|تاریخ رویداد ||وضعیت رویداد |
|-------------||-------------|
|1396/03/15   ||برگزار میشود |
|1396/03/17   ||برگزار میشود |
|1396/03/20   ||برگزار میشود |
|1396/03/01   ||منقضی        |
|1396/02/26   ||منقضی        |
|1395/02/20   ||منقضی        |
|1394/02/16   ||منقضی        |

فکر کنم متوجه شده باشین که منظورم چی هست ولی اگر هنوز درست معلوم نیست میتونین صفحات مربوط به کسب‌وکارها تو ایوند رو نگاه کنین مثل این صفحه ، الان حالتی که ایوند داره این شکلی هست:

Events Order:

|تاریخ رویداد ||وضعیت رویداد |
|-------------||-------------|
|1396/03/15   ||برگزار میشود |
|1396/03/17   ||برگزار میشود |
|1396/03/20   ||برگزار میشود |
|1396/02/16   ||منقضی        |
|1396/02/20   ||منقضی        |
|1396/02/26   ||منقضی        |
|1396/02/16   ||منقضی        |

بدی این حالت اینه که اولین رویداد منقضی برمیگرده به یه زمان خیلی قبل و اگر کسی بخواد بدونه که این شرکت یا آکادمی چه رویدادهایی قبلا داشته باید بره به صفحه آخر تا این رو ببینه، چیزی که از من خواستن حل کردن این مشکل بود.

نکته :) ، ایوند رو کلا برای مثال گفتم.

خب من خیلی گشتم دنبال راه حل ولی انگار قبلا از کسی این کار رو نخواسته بودن یا اینکه من پیداش نکردم، پس تصمیم گرفتم یه روش خودم بسازم که امیدوارم به درد بقیه هم بخوره یا اینکه اگر بد هست ایرادش رو برطرف کنم.

من دو تا فیلد سفارشی(custom field) به اسم‌های event_publish_date و event_state دارم که اولی تاریخ برگزاری رویداد هست که unix_timestampهست و دومی وضعیت رویداد که اونم دو حالتش الان مهمه حالت 1 یعنی رویداد پیشرو و حالت 2 یعنی رویداد منقضی.

خب اولین کار چیدن رویدادها براساس وضعیت هست که رویدادهای پیشرو اول بیان، بعد باید رویدادها رو براساس تاریخ بچینم، من اینجا همرو به صورت نزولی(DESC) میچینم بعدا داخل صفحه رویداد درستشون میکنیم که نزدیک‌ترها اول نمایش داده بشن.

با ستفاده از هوک قبل از پست‌ها ( pre_get_posts) که برای تغییر در wp_queryقبل از وارد شدن به حلقه loop هست، تغییراتم رو انجام میدم.

این قسمت کار اینجا هست

function customize_custom_taxonomy_archive_display($query)
{
 // اینجا میام مطمئن میشم که توی صفحه آرشیو دسته‌بتدی هستم  
 if (($query->is_main_query()) && (is_tax('event_categories'))) {
 //اینجا مشخص میکنم که پست‌های من بر چه اساسی باید چیده بشن
 $query->set( 'orderby', array(
 'state_clause' => 'ASC', // اول براساس وضعیت نزولی
 'date_clause' => 'DESC', // بر اساس تاریخ صعودی          
        ));
 $query->set( 'meta_query', array(
 // یک حالت برای چیدن بر اساس فیلد روز برگزاری رویداد
 'date_clause' => array(
 'key' => 'event_publish_date',
 'type' => 'NUMERIC',
            ),
 'state_clause' => array(
 // یک حالت برای چیدن بر اساس فیلد وضعیت رویداد
 'key' => 'event_state',
 'type' => 'NUMERIC',
            ),
        ));
    }
}
// اضافه کردن تابع به هوک پست‌ها
add_action( 'pre_get_posts', 'customize_custom_taxonomy_archive_display' );

کد بالا چینش مارو این شکلی میکنه

Events Order:

|تاریخ رویداد ||وضعیت رویداد |
|-------------||-------------|
|1396/03/20   ||برگزار میشود |
|1396/03/17   ||برگزار میشود |
|1396/03/15   ||برگزار میشود |
|1396/03/01   ||منقضی        |
|1396/02/26   ||منقضی        |
|1395/02/20   ||منقضی        |
|1394/02/16   ||منقضی        |

خب تا اینجا رویدادها چیده شدن ولی الان مشکلی که هست، توی رویدادهای پیشرو از آخر به اول میان که باید برعکس بشه، یعنی تبدیل بشن به نزولی پس داخل صفحه آرشیو رویدادها میام wp_query رو تغییر میدم، به این صورت که:

// events_archive.php
global $wp_query; // اول خود کووری رو میگیریم
//این آرایه رویدادهای پیشرو رو به حالت برعکس داخل خودش نگه میداره
$upcomingArray = array();

//خب برعکس آرایه پست‌ها رو میگردیم دونه دونه از آخر به اول تا رویدادهای پیشرو رو داخلش جدا کنیم
foreach ( array_reverse( $wp_query->posts ) as $key => $value ) {

 /*
  از اونجایی که داخل حلقه من مقدار این 2 تا فیلد رو چاپ میکنم پس دیدم،
  بهتره که نگهشون دارم که اونجا دوباره مقدارشون رو نگیرم.
  to_ping , pinged
  این 2 تا متغیر برام استفاده نداشتن و پیشفرض هم هستن مقدارشون رو اینجا
  دخیره کردم راحت‌ترم هست.
  */
 $wp_query->posts[ $key ]->to_ping = get_post_meta( $wp_query->posts[ $key ]->ID, 'event_state', true );
 $wp_query->posts[ $key ]->pinged = get_post_meta( $wp_query->posts[ $key ]->ID, 'event_publish_date', true );

 // خب اینجا چک میکنم اگر وضعیت برابر با 2 بود پس رویداد پیشرو هست.
 
 if ( $wp_query->posts[ $key ]->to_ping == 2 ) {

 // از اونجایی که از آخر به اول میریم پس این باید بره اول آرایه رویدادهای پیشرو
 $upcomingArray[] = $wp_query->posts[ $key ];
  }
}

// یکی از تعداد کم میکنم چون count از یک شروع میشه
$countUpcomingPosts = count( $upcomingArray ) - 1;

//حالا اون رویدادهایی که داخل آرایه بالا ذخیره کردم میبرم تو پست‌های اصلی
for ( $i = 0; $i < count( $upcomingArray ); $i ++, $countUpcomingPosts -- ) {
 $wp_query->posts[ $countUpcomingPosts ] = $upcomingArray[ $i ];
}

امیدوارم خوب توضیح داده باشم که چیکار کردم، چون کلا اولین پست من در مورد کدنویسی هست.

این مشکل کمی خاص منظوره بود و نگارش منم ضعیف، میدونم که متن ممکنه مشکل زیاد داشته‌باشه، خوشحال میشم نظرات شما رو ببینم بخصوص نظرات منفی چون ازشون یاد میگیرم که سراغ چه جور موضوع‌هایی باید برم و سراغ کدوما نباید.

لینک همین کد هم داخل گیتهاب هست که دارم کاملش میکنم، به درد کسی بخوره شاید.