Index: trunk/kernel/units/reviews/reviews_event_handler.php =================================================================== diff -u -N -r8444 -r8481 --- trunk/kernel/units/reviews/reviews_event_handler.php (.../reviews_event_handler.php) (revision 8444) +++ trunk/kernel/units/reviews/reviews_event_handler.php (.../reviews_event_handler.php) (revision 8481) @@ -101,7 +101,7 @@ } if ($event->getEventParam('type') == 'current_user') { - $object->removeFilter('active'); +// $object->removeFilter('active'); $object->addFilter('current_user', '%1$s.CreatedById = '.$this->Application->RecallVar('user_id')); $object->addFilter('current_ip', '%1$s.IPAddress = "'.$_SERVER['REMOTE_ADDR'].'"'); } @@ -148,15 +148,20 @@ */ function OnBeforeItemCreate(&$event) { - if ($this->Application->IsAdmin()) { - return ; - } - $object =& $event->getObject(); /* @var $object kDBItem */ $parent_info = $object->getLinkedInfo(); + $item_type = $this->Application->getUnitOption($parent_info['ParentPrefix'], 'ItemType'); + $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('ItemType', $item_type); + $object->SetDBField('Module', $this->Application->findModule('Var', $parent_info['ParentPrefix'], 'Name')); + + if ($this->Application->IsAdmin()) { + return ; + } + $spam_helper =& $this->Application->recallObject('SpamHelper'); /* @var $spam_helper SpamHelper */ @@ -168,25 +173,41 @@ return ; } - $item_type = $this->Application->getUnitOption($parent_info['ParentPrefix'], 'ItemType'); + $rating = $object->GetDBField('Rating'); + if ($rating < 1 || $rating > 5) { + $object->SetDBField('Rating', null); + } - $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); $object->SetDBField('ItemId', $parent_info['ParentId']); // ResourceId $object->SetDBField('CreatedById', $this->Application->RecallVar('user_id')); - $object->SetDBField('ItemType', $item_type); + $object->SetDBField('Status', $this->getReviewStatus($event)); $object->SetDBField('TextFormat', 0); // set plain text format directly - $object->SetDBField('Module', $this->Application->findModule('Var', $parent_info['ParentPrefix'], 'Name')); } /** + * Sets correct rating value + * + * @param kEvent $event + */ + function OnBeforeItemUpdate(&$event) + { + $object =& $event->getObject(); + + $rating = $object->GetDBField('Rating'); + if (!$rating) { + $object->SetDBField('Rating', null); + } + } + + /** * Updates item review counter * * @param kEvent $event */ function OnAfterItemCreate(&$event) { - $this->updateReviewsCounter($event); + $this->updateSubitemCounters($event); if (!$this->Application->IsAdmin()) { $spam_helper =& $this->Application->recallObject('SpamHelper'); @@ -203,13 +224,24 @@ } } + /** - * Updates total review counter + * Updates item review counter * * @param kEvent $event */ - function updateReviewsCounter(&$event) + function OnAfterItemUpdate(&$event) { + $this->updateSubitemCounters($event); + } + + /** + * Updates total review counter, cached rating, votes count + * + * @param kEvent $event + */ + function updateSubitemCounters(&$event) + { $parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix'); $main_object =& $this->Application->recallObject($parent_prefix, null, Array ('raise_warnings' => 0)); /* @var $main_object kCatDBItem */ @@ -220,24 +252,72 @@ } $object =& $event->getObject(); // for temp tables + /* @var $object kDBItem */ + // 1. update review counter $sql = 'SELECT COUNT(ReviewId) FROM '.$object->TableName.' WHERE ItemId = '.$main_object->GetDBField('ResourceId'); $review_count = $this->Conn->GetOne($sql); $main_object->SetDBField('CachedReviewsQty', $review_count); + + // 2. update votes counter + rating + $rating = $object->GetDBField('Rating'); + $avg_rating = $main_object->GetDBField('CachedRating'); + $votes_count = $main_object->GetDBField('CachedVotesQty'); + + switch ($event->Name) { + case 'OnAfterItemCreate': // adding new review with rating + $this->changeRating($avg_rating, $votes_count, $rating, '+'); + break; + + case 'OnAfterItemDelete': + $this->changeRating($avg_rating, $votes_count, $rating, '-'); + break; + + case 'OnAfterItemUpdate': + $this->changeRating($avg_rating, $votes_count, $object->GetOriginalField('Rating'), '-'); + $this->changeRating($avg_rating, $votes_count, $rating, '+'); + break; + } + $main_object->SetDBField('CachedRating', $avg_rating); + $main_object->SetDBField('CachedVotesQty', $votes_count); $main_object->Update(); } + /** + * Changes average rating and votes count based on requested operation + * + * @param float $avg_rating average rating before new vote + * @param int $votes_count votes count before new vote + * @param int $rating new vote (from 1 to 5) + * @param string $operation requested operation (+ / -) + */ + function changeRating(&$avg_rating, &$votes_count, $rating, $operation) + { + if ($rating < 1 || $rating > 5) { + return ; + } + if ($operation == '+') { + $avg_rating = (($avg_rating * $votes_count) + $rating) / ($votes_count + 1); + ++$votes_count; + } + else { + $avg_rating = (($avg_rating * $votes_count) - $rating) / ($votes_count - 1); + --$votes_count; + } + } + + /** * Updates main item cached review counter * * @param kEvent $event */ function OnAfterItemDelete(&$event) { - $this->updateReviewsCounter($event); + $this->updateSubitemCounters($event); } /**