Reputation: 2439
I have an array of objects (goals) that I want to sort based on 2 of their properties, the Status
and the DueDate
.
Here are the rules:
Statuses:
If a goal has a status of 4 (completed) or 5 (archived) then the DueDate
doesn't matter.
If a goal is neither 4 nor 5 and its DueDate
is less than now then it is "Overdue" and should be at the top
If a goal is not "Overdue" then the order of statuses determines it's position (lowest to highest)
If $a
and $b
are both "Overdue" then the one with the earliest DueDate
is more important
The order should be:
Here is the last thing I tried:
function cmp($a, $b)
{
$now = new DateTime("now");
$aDueDate = new DateTime($a->GetDueDate());
$bDueDate = new DateTime($b->GetDueDate());
if($a->GetStatus() != 4 && $a->GetStatus() != 5 && $b->GetStatus() != 4 && $b->GetStatus() != 5){
if($aDueDate < $now || $bDueDate < $now){
if($aDueDate == $bDueDate){
return 0;
}
return ($aDueDate < $bDueDate) ? -1 : 1;
}
}
elseif(($a->GetStatus() == 4 || $a->GetStatus() == 5) && ($b->GetStatus() != 4 && $b->GetStatus() != 5)) {
return -1;
}
elseif(($a->GetStatus() != 4 && $a->GetStatus() != 5) && ($b->GetStatus() == 4 || $b->GetStatus() == 5)){
return 1;
}
if ($a->GetStatus() == $b->GetStatus()) {
return 0;
}
return ($a->GetStatus() < $b->GetStatus()) ? -1 : 1;
}
Which orders the array like so:
Upvotes: 1
Views: 70
Reputation: 42507
The following should meet your requirements:
function cmp($a, $b) {
$now = new DateTime("now");
$aDueDate = new DateTime($a->GetDueDate());
$bDueDate = new DateTime($b->GetDueDate());
$aStatus = $a->GetStatus();
$bStatus = $b->GetStatus();
$incompleteStatuses = array(1, 2, 3);
// use date if same status (might not be needed)
if ($aStatus == $bStatus) {
return ($aDueDate < $bDueDate ? -1 : 1);
}
// if A is overdue:
if (in_array($aStatus, $incompleteStatuses) && $aDueDate < $now) {
// if B is overdue too, only consider dates
if (in_array($bStatus, $incompleteStatuses) && $bDueDate < $now) {
return ($aDueDate < $bDueDate ? -1 : 1);
}
return -1; // A definitely first
}
// if B is overdue:
elseif (in_array($bStatus, $incompleteStatuses) && $bDueDate < $now) {
return 1; // B definitely first (we know A is not overdue from above)
}
// both A and B are not overdue; order by status
return $aStatus - $bStatus;
}
Upvotes: 1