Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Sun, Apr 20, 9:12 AM

in-portal

Index: branches/RC/kernel/units/reviews/reviews_event_handler.php
===================================================================
--- branches/RC/kernel/units/reviews/reviews_event_handler.php (revision 10518)
+++ branches/RC/kernel/units/reviews/reviews_event_handler.php (revision 10519)
@@ -1,474 +1,474 @@
<?php
class ReviewsEventHandler extends kDBEventHandler
{
/**
* Get's special of main item for linking with subitem
*
* @param kEvent $event
* @return string
*/
function getMainSpecial(&$event)
{
if ($event->Special == 'product' && !$this->Application->IsAdmin()) {
// rev.product should auto-link
return '';
}
return parent::getMainSpecial($event);
}
/**
* Checks REVIEW/REVIEW.PENDING permission by main object primary category (not current category)
*
* @param kEvent $event
*/
function CheckPermission(&$event)
{
if ($event->Name == 'OnAddReview' || $event->Name == 'OnCreate') {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$main_object =& $this->Application->recallObject($parent_prefix);
/* @var $main_object kCatDBItem */
$perm_name = $this->getPermPrefix($event).'.REVIEW';
$res = $this->Application->CheckPermission($perm_name, 0, $main_object->GetDBField('CategoryId')) ||
$this->Application->CheckPermission($perm_name.'.PENDING', 0, $main_object->GetDBField('CategoryId'));
if (!$res) {
$event->status = erPERM_FAIL;
}
return $res;
}
$check_events = Array (
'OnItemBuild', 'OnUpdate', /*'OnMassApprove', 'OnMassDecline'*/
);
$perm_category = $this->_getReviewCategory($event);
if (in_array($event->Name, $check_events)) {
// check for PRODUCT.VIEW permission
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$perm_prefix = $this->getPermPrefix($event);
if ($perm_category === false) {
// no item id present -> allow
return true;
}
switch ($event->Name) {
case 'OnItemBuild':
$res = $this->Application->CheckPermission($perm_prefix . '.VIEW', 0, $perm_category);
break;
case 'OnUpdate':
case 'OnMassApprove':
case 'OnMassDecline':
$res = $this->Application->CheckPermission($perm_prefix . '.ADD', 0, $perm_category) ||
$this->Application->CheckPermission($perm_prefix . '.MODIFY', 0, $perm_category);
break;
}
if (!$res) {
$event->status = erPERM_FAIL;
}
return $res;
}
return parent::CheckPermission($event);
}
/**
* Returns primary category of review's main item
*
* @param kEvent $event
* @return int
*/
function _getReviewCategory(&$event)
{
$items_info = $this->Application->GetVar($event->getPrefixSpecial());
list ($review_id, ) = each($items_info);
if (!$review_id) {
return false;
}
// 1. get main item resource id
$sql = 'SELECT ItemId
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . ' = ' . $review_id;
$resource_id = $this->Conn->GetOne($sql);
// 2. set main item id (for permission checks)
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$sql = 'SELECT ' . $this->Application->getUnitOption($parent_prefix, 'IDField') .'
FROM ' . $this->Application->getUnitOption($parent_prefix, 'TableName') .'
WHERE ResourceId = ' . $resource_id;
$this->Application->SetVar($parent_prefix . '_id', $this->Conn->GetOne($sql));
// 3. get main item category
$sql = 'SELECT CategoryId
FROM ' . $this->Application->getUnitOption('ci', 'TableName') .'
WHERE ItemResourceId = ' . $resource_id .' AND PrimaryCat = 1';
return $this->Conn->GetOne($sql);
}
/**
* Returns prefix for permissions
*
* @param kEvent $event
*/
function getPermPrefix(&$event)
{
$main_prefix = $this->Application->GetTopmostPrefix($event->Prefix, true);
// this will return LINK for l, ARTICLE for n, TOPIC for bb, PRODUCT for p
$item_prefix = $this->Application->getUnitOption($main_prefix, 'PermItemPrefix');
return $item_prefix;
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @access protected
* @see OnListBuild
*/
function SetCustomQuery(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
if (!$this->Application->IsAdmin()) {
$object->addFilter('active', '%1$s.Status = '.STATUS_ACTIVE);
}
switch ($event->Special)
{
case 'showall':
$object->clearFilters();
break;
case 'item': // used ?
$object->clearFilters();
$info = $object->getLinkedInfo();
$this->Application->setUnitOption($info['ParentPrefix'], 'AutoLoad', true);
$parent =& $this->Application->recallObject($info['ParentPrefix']);
$object->addFilter('item_reviews', '%1$s.ItemId = '.$parent->GetDBField('ResourceId'));
break;
case 'products': // used in In-Portal (Sturcture & Data -> Reviews section)
$object->removeFilter('parent_filter'); // this is important
$object->addFilter('product_reviews', 'pr.ResourceId IS NOT NULL');
break;
/*case 'product':
$object->addFilter('product_reviews', '%1$s.ItemId = pr.ResourceId'); // for LEFT JOIN
break;*/
}
if (preg_match('/(.*)-rev/', $event->Prefix, $regs)) {
// "Structure & Data" -> "Reviews" (section in K4)
$item_type = $this->Application->getUnitOption($regs[1], 'ItemType');
$object->addFilter('itemtype_filter', '%1$s.ItemType = ' . $item_type);
}
if ($event->getEventParam('type') == 'current_user') {
// $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'].'"');
}
}
/**
* Adds review from front in case if user is logged in
*
* @param kEvent $event
*/
function OnAddReview(&$event)
{
$event->CallSubEvent('OnCreate');
}
/**
* Get new review status on user review permission
*
* @param kEvent $event
* @return int
*/
function getReviewStatus(&$event)
{
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$main_object =& $this->Application->recallObject($parent_prefix);
/* @var $main_object kCatDBItem */
$ret = STATUS_DISABLED;
$perm_name = $this->getPermPrefix($event).'.REVIEW';
if ($this->Application->CheckPermission($perm_name, 0, $main_object->GetDBField('CategoryId'))) {
$ret = STATUS_ACTIVE;
}
else if ($this->Application->CheckPermission($perm_name.'.PENDING', 0, $main_object->GetDBField('CategoryId'))) {
$ret = STATUS_PENDING;
}
return $ret;
}
/**
* Prefills all fields on front-end
*
* @param kEvent $event
*/
function OnBeforeItemCreate(&$event)
{
$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 */
$spam_helper->InitHelper($parent_info['ParentId'], 'Review', 0);
if ($spam_helper->InSpamControl()) {
$event->status = erFAIL;
$object->SetError('ReviewText', 'too_frequent', 'lu_ferror_review_duplicate');
return ;
}
$rating = $object->GetDBField('Rating');
if ($rating < 1 || $rating > 5) {
$object->SetDBField('Rating', null);
}
$object->SetDBField('ItemId', $parent_info['ParentId']); // ResourceId
$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
$object->SetDBField('Status', $this->getReviewStatus($event));
$object->SetDBField('TextFormat', 0); // set plain text format directly
}
/**
* 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->updateSubitemCounters($event);
if (!$this->Application->IsAdmin()) {
$spam_helper =& $this->Application->recallObject('SpamHelper');
/* @var $spam_helper SpamHelper */
$object =& $event->getObject();
$parent_info = $object->getLinkedInfo();
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
$review_settings = $config_mapping['ReviewDelayValue'].':'.$config_mapping['ReviewDelayInterval'];
$spam_helper->InitHelper($parent_info['ParentId'], 'Review', $review_settings);
$spam_helper->AddToSpamControl();
}
}
/**
* Updates item review counter
*
* @param kEvent $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 */
if (!$main_object->isLoaded()) {
// deleting main item / cloning main item
return ;
}
$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->updateSubitemCounters($event);
}
/**
* Creates review & redirect to confirmation template
*
* @param kEvent $event
*/
function OnCreate(&$event)
{
parent::OnCreate($event);
if ($event->status != erSUCCESS || $this->Application->IsAdmin()) {
return ;
}
$object =& $event->getObject();
$next_template = $object->GetDBField('Status') == STATUS_ACTIVE ? 'success_template' : 'success_pending_template';
$event->redirect = $this->Application->GetVar($next_template);
$event->SetRedirectParam('opener', 's');
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$event->SetRedirectParam('pass', 'm,'.$parent_prefix);
}
/**
* Makes left join to item's table, when in separate grid
*
* @param kEvent $event
*/
function OnAfterConfigRead(&$event)
{
parent::OnAfterConfigRead($event);
- if (preg_match('/(.*)-rev/', $event->Prefix, $regs)) {
+ if (preg_match('/(.*)-rev/', $event->Prefix, $regs) && $this->Application->prefixRegistred($regs[1])) {
// "Structure & Data" -> "Reviews" (section in K4)
// 1. add join to items table (for "Structure & Data" -> "Reviews" section)
$item_table = $this->Application->getUnitOption($regs[1], 'TableName');
$list_sqls = $this->Application->getUnitOption($event->Prefix, 'ListSQLs');
$list_sqls[''] .= ' LEFT JOIN '.$item_table.' item_table ON item_table.ResourceId = %1$s.ItemId';
$this->Application->setUnitOption($event->Prefix, 'ListSQLs', $list_sqls);
// 2. add calculated field
$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
$calculated_fields['']['CatalogItemName'] = 'item_table.' . $this->getTitleField($regs[1]);
$calculated_fields['']['CatalogItemId'] = 'item_table.' . $this->Application->getUnitOption($regs[1], 'IDField');
$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
}
}
/**
* Convert TitleField field of kMultiLanguage formatter used for it
*
* @param string $prefix
* @return string
*/
function getTitleField($prefix)
{
$lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_';
$title_field = $this->Application->getUnitOption($prefix, 'TitleField');
$field_options = $this->Application->getUnitOption($prefix.'.'.$title_field, 'Fields');
$formatter_class = isset($field_options['formatter']) ? $field_options['formatter'] : '';
if ($formatter_class == 'kMultiLanguage' && !isset($field_options['master_field'])) {
$title_field = $lang_prefix.$title_field;
}
return $title_field;
}
}
?>
\ No newline at end of file
Property changes on: branches/RC/kernel/units/reviews/reviews_event_handler.php
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.14.2.3
\ No newline at end of property
+1.14.2.4
\ No newline at end of property
Index: branches/RC/kernel/admin_templates/reviews.tpl
===================================================================
--- branches/RC/kernel/admin_templates/reviews.tpl (revision 10518)
+++ branches/RC/kernel/admin_templates/reviews.tpl (revision 10519)
@@ -1,146 +1,145 @@
<inp2:m_include t="incs/header" nobody="yes" noform="yes"/>
<body topmargin="0" leftmargin="8" marginheight="0" marginwidth="8" bgcolor="#FFFFFF">
<inp2:m_RenderElement name="combined_header" section="in-portal:reviews" prefix="c" module="in-portal" title_preset="reviews"/>
<!-- main kernel_form: begin -->
<inp2:m_RenderElement name="kernel_form"/>
<!-- ToolBar --->
<table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td>
<input type="hidden" name="m_cat_id" value="<inp2:m_get name="m_cat_id"/>"/>
<link rel="stylesheet" rev="stylesheet" href="incs/nlsmenu.css" type="text/css" />
<script type="text/javascript" src="js/nlsmenu.js"></script>
<script type="text/javascript" src="js/nlsmenueffect_1_2_1.js"></script>
<script type="text/javascript" src="js/ajax.js"></script>
<script type="text/javascript" src="<inp2:m_TemplatesBase module='in-portal'/>/incs/catalog.js"></script>
<script type="text/javascript">
var menuMgr = new NlsMenuManager("mgr");
menuMgr.timeout = 500;
menuMgr.flowOverFormElement = true;
Request.progressText = '<inp2:m_phrase name="la_title_Loading" escape="1"/>';
Catalog.prototype.AfterInit = function() {
this.switchTab();
}
Catalog.prototype.refreshTab = function($prefix, $div_id, $force) {
var $cat_id = get_hidden_field('m_cat_id');
var $tab_cat_id = document.getElementById($div_id).getAttribute('category_id');
if ($cat_id != $tab_cat_id || $force) {
// query tab content only in case if not queried or category don't match
var $url = this.URLMask.replace('#ITEM_PREFIX#', $prefix).replace('#TAB_NAME#', this.queryTabRegistry('prefix', $prefix, 'tab_id'));
this.BusyRequest[$prefix] = false;
Request.makeRequest($url, this.BusyRequest[$prefix], $div_id, this.successCallback, this.errorCallback, $div_id, this);
}
}
var $Catalog = new Catalog('<inp2:m_Link template="in-portal/reviews/reviews_tab" item_prefix="#ITEM_PREFIX#" tab_name="#TAB_NAME#" pass_through="td,item_prefix,tab_name" td="no" m_cat_id="-1" no_amp="1"/>', 'reviews_', 0);
var a_toolbar = new ToolBar();
a_toolbar.AddButton( new ToolBarButton('edit', '<inp2:m_phrase label="la_ToolTip_Edit" escape="1"/>', edit) );
a_toolbar.AddButton( new ToolBarButton('delete', '<inp2:m_phrase label="la_ToolTip_Delete" escape="1"/>',
function() {
- var $template = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'view_template');
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
- std_delete_items($Catalog.ActivePrefix, $template, 1);
+ std_delete_items($Catalog.ActivePrefix, null, 1);
} ) );
<inp2:m_ModuleInclude template="catalog_buttons" main_template="reviews" skip_prefixes="m,cms"/>
a_toolbar.AddButton( new ToolBarSeparator('sep2') );
a_toolbar.AddButton( new ToolBarButton('approve', '<inp2:m_phrase label="la_ToolTip_Approve" escape="1"/>', function() {
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
$Catalog.submit_event($Catalog.ActivePrefix, 'OnMassApprove');
}
) );
a_toolbar.AddButton( new ToolBarButton('decline', '<inp2:m_phrase label="la_ToolTip_Decline" escape="1"/>', function() {
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
$Catalog.submit_event($Catalog.ActivePrefix, 'OnMassDecline');
}
) );
a_toolbar.AddButton( new ToolBarSeparator('sep3') );
a_toolbar.AddButton( new ToolBarButton('view', '<inp2:m_phrase label="la_ToolTip_View" escape="1"/>', function() {
show_viewmenu(a_toolbar, 'view');
}
) );
a_toolbar.Render();
function edit()
{
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
var $kf = document.getElementById($form_name);
var $prev_action = $kf.action;
$kf.action = '<inp2:m_t pass="all" pass_through="item_prefix" item_prefix="#PREFIX#" no_amp="1"/>' . replace('#PREFIX#', $Catalog.ActivePrefix);
std_edit_temp_item($Catalog.ActivePrefix, 'in-portal/reviews/review_direct_edit');
$kf.action = $prev_action;
}
</script>
</td>
</tr>
</tbody>
</table>
<inp2:m_RenderElement name="kernel_form_end"/>
<!-- main kernel_form: end -->
<br />
<!-- item tabs: begin -->
<table cellpadding="0" cellspacing="0">
<tr>
<inp2:m_DefineElement name="item_tab" title="">
<td nowrap="nowrap" width="140">
<table id="<inp2:m_param name="prefix"/>-rev_tab" cellpadding="0" cellspacing="0" width="100%" class="catalog-tab-unselected" onclick="$Catalog.switchTab('<inp2:m_param name="prefix"/>-rev');">
<tr>
<td class="catalog-tab-left">
<img src="img/spacer.gif" height="22" width="9" />
</td>
<td class="catalog-tab-middle" width="100%" valign="middle" nowrap="nowrap">
<inp2:m_phrase name="$title"/> <span class="cats_stats">(<span id="<inp2:m_param name="prefix"/>-rev_item_count">?</span>)</span>
</td>
<td class="catalog-tab-right">
<img src="img/spacer.gif" height="22" width="9" />
</td>
<td style="background-color: #FFFFFF;">
<img src="img/spacer.gif" height="1" width="5" />
</td>
</tr>
</table>
</td>
</inp2:m_DefineElement>
<inp2:adm_ListCatalogTabs render_as="item_tab" title_property="ViewMenuPhrase" skip_prefixes="m,cms"/>
</tr>
</table>
<!-- item tabs: end -->
<inp2:m_set prefix_append="-rev" td="no"/>
<inp2:m_ModuleInclude template="catalog_tab" tab_init="2" skip_prefixes="m,cms"/>
<inp2:m_if check="m_get" var="SetTab">
<script type="text/javascript">
$Catalog.switchTab('<inp2:m_get var="SetTab"/>-rev');
</script>
</inp2:m_if>
<script type="text/javascript">
addLoadEvent(
function() {
$Catalog.Init();
}
);
</script>
<inp2:m_include t="incs/footer" noform="yes"/>
\ No newline at end of file
Property changes on: branches/RC/kernel/admin_templates/reviews.tpl
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.1.2.1
\ No newline at end of property
+1.1.2.2
\ No newline at end of property
Index: branches/RC/core/units/reviews/reviews_event_handler.php
===================================================================
--- branches/RC/core/units/reviews/reviews_event_handler.php (revision 10518)
+++ branches/RC/core/units/reviews/reviews_event_handler.php (revision 10519)
@@ -1,474 +1,474 @@
<?php
class ReviewsEventHandler extends kDBEventHandler
{
/**
* Get's special of main item for linking with subitem
*
* @param kEvent $event
* @return string
*/
function getMainSpecial(&$event)
{
if ($event->Special == 'product' && !$this->Application->IsAdmin()) {
// rev.product should auto-link
return '';
}
return parent::getMainSpecial($event);
}
/**
* Checks REVIEW/REVIEW.PENDING permission by main object primary category (not current category)
*
* @param kEvent $event
*/
function CheckPermission(&$event)
{
if ($event->Name == 'OnAddReview' || $event->Name == 'OnCreate') {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$main_object =& $this->Application->recallObject($parent_prefix);
/* @var $main_object kCatDBItem */
$perm_name = $this->getPermPrefix($event).'.REVIEW';
$res = $this->Application->CheckPermission($perm_name, 0, $main_object->GetDBField('CategoryId')) ||
$this->Application->CheckPermission($perm_name.'.PENDING', 0, $main_object->GetDBField('CategoryId'));
if (!$res) {
$event->status = erPERM_FAIL;
}
return $res;
}
$check_events = Array (
'OnItemBuild', 'OnUpdate', /*'OnMassApprove', 'OnMassDecline'*/
);
$perm_category = $this->_getReviewCategory($event);
if (in_array($event->Name, $check_events)) {
// check for PRODUCT.VIEW permission
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$perm_prefix = $this->getPermPrefix($event);
if ($perm_category === false) {
// no item id present -> allow
return true;
}
switch ($event->Name) {
case 'OnItemBuild':
$res = $this->Application->CheckPermission($perm_prefix . '.VIEW', 0, $perm_category);
break;
case 'OnUpdate':
case 'OnMassApprove':
case 'OnMassDecline':
$res = $this->Application->CheckPermission($perm_prefix . '.ADD', 0, $perm_category) ||
$this->Application->CheckPermission($perm_prefix . '.MODIFY', 0, $perm_category);
break;
}
if (!$res) {
$event->status = erPERM_FAIL;
}
return $res;
}
return parent::CheckPermission($event);
}
/**
* Returns primary category of review's main item
*
* @param kEvent $event
* @return int
*/
function _getReviewCategory(&$event)
{
$items_info = $this->Application->GetVar($event->getPrefixSpecial());
list ($review_id, ) = each($items_info);
if (!$review_id) {
return false;
}
// 1. get main item resource id
$sql = 'SELECT ItemId
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . ' = ' . $review_id;
$resource_id = $this->Conn->GetOne($sql);
// 2. set main item id (for permission checks)
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$sql = 'SELECT ' . $this->Application->getUnitOption($parent_prefix, 'IDField') .'
FROM ' . $this->Application->getUnitOption($parent_prefix, 'TableName') .'
WHERE ResourceId = ' . $resource_id;
$this->Application->SetVar($parent_prefix . '_id', $this->Conn->GetOne($sql));
// 3. get main item category
$sql = 'SELECT CategoryId
FROM ' . $this->Application->getUnitOption('ci', 'TableName') .'
WHERE ItemResourceId = ' . $resource_id .' AND PrimaryCat = 1';
return $this->Conn->GetOne($sql);
}
/**
* Returns prefix for permissions
*
* @param kEvent $event
*/
function getPermPrefix(&$event)
{
$main_prefix = $this->Application->GetTopmostPrefix($event->Prefix, true);
// this will return LINK for l, ARTICLE for n, TOPIC for bb, PRODUCT for p
$item_prefix = $this->Application->getUnitOption($main_prefix, 'PermItemPrefix');
return $item_prefix;
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @access protected
* @see OnListBuild
*/
function SetCustomQuery(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
if (!$this->Application->IsAdmin()) {
$object->addFilter('active', '%1$s.Status = '.STATUS_ACTIVE);
}
switch ($event->Special)
{
case 'showall':
$object->clearFilters();
break;
case 'item': // used ?
$object->clearFilters();
$info = $object->getLinkedInfo();
$this->Application->setUnitOption($info['ParentPrefix'], 'AutoLoad', true);
$parent =& $this->Application->recallObject($info['ParentPrefix']);
$object->addFilter('item_reviews', '%1$s.ItemId = '.$parent->GetDBField('ResourceId'));
break;
case 'products': // used in In-Portal (Sturcture & Data -> Reviews section)
$object->removeFilter('parent_filter'); // this is important
$object->addFilter('product_reviews', 'pr.ResourceId IS NOT NULL');
break;
/*case 'product':
$object->addFilter('product_reviews', '%1$s.ItemId = pr.ResourceId'); // for LEFT JOIN
break;*/
}
if (preg_match('/(.*)-rev/', $event->Prefix, $regs)) {
// "Structure & Data" -> "Reviews" (section in K4)
$item_type = $this->Application->getUnitOption($regs[1], 'ItemType');
$object->addFilter('itemtype_filter', '%1$s.ItemType = ' . $item_type);
}
if ($event->getEventParam('type') == 'current_user') {
// $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'].'"');
}
}
/**
* Adds review from front in case if user is logged in
*
* @param kEvent $event
*/
function OnAddReview(&$event)
{
$event->CallSubEvent('OnCreate');
}
/**
* Get new review status on user review permission
*
* @param kEvent $event
* @return int
*/
function getReviewStatus(&$event)
{
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$main_object =& $this->Application->recallObject($parent_prefix);
/* @var $main_object kCatDBItem */
$ret = STATUS_DISABLED;
$perm_name = $this->getPermPrefix($event).'.REVIEW';
if ($this->Application->CheckPermission($perm_name, 0, $main_object->GetDBField('CategoryId'))) {
$ret = STATUS_ACTIVE;
}
else if ($this->Application->CheckPermission($perm_name.'.PENDING', 0, $main_object->GetDBField('CategoryId'))) {
$ret = STATUS_PENDING;
}
return $ret;
}
/**
* Prefills all fields on front-end
*
* @param kEvent $event
*/
function OnBeforeItemCreate(&$event)
{
$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 */
$spam_helper->InitHelper($parent_info['ParentId'], 'Review', 0);
if ($spam_helper->InSpamControl()) {
$event->status = erFAIL;
$object->SetError('ReviewText', 'too_frequent', 'lu_ferror_review_duplicate');
return ;
}
$rating = $object->GetDBField('Rating');
if ($rating < 1 || $rating > 5) {
$object->SetDBField('Rating', null);
}
$object->SetDBField('ItemId', $parent_info['ParentId']); // ResourceId
$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
$object->SetDBField('Status', $this->getReviewStatus($event));
$object->SetDBField('TextFormat', 0); // set plain text format directly
}
/**
* 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->updateSubitemCounters($event);
if (!$this->Application->IsAdmin()) {
$spam_helper =& $this->Application->recallObject('SpamHelper');
/* @var $spam_helper SpamHelper */
$object =& $event->getObject();
$parent_info = $object->getLinkedInfo();
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
$review_settings = $config_mapping['ReviewDelayValue'].':'.$config_mapping['ReviewDelayInterval'];
$spam_helper->InitHelper($parent_info['ParentId'], 'Review', $review_settings);
$spam_helper->AddToSpamControl();
}
}
/**
* Updates item review counter
*
* @param kEvent $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 */
if (!$main_object->isLoaded()) {
// deleting main item / cloning main item
return ;
}
$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->updateSubitemCounters($event);
}
/**
* Creates review & redirect to confirmation template
*
* @param kEvent $event
*/
function OnCreate(&$event)
{
parent::OnCreate($event);
if ($event->status != erSUCCESS || $this->Application->IsAdmin()) {
return ;
}
$object =& $event->getObject();
$next_template = $object->GetDBField('Status') == STATUS_ACTIVE ? 'success_template' : 'success_pending_template';
$event->redirect = $this->Application->GetVar($next_template);
$event->SetRedirectParam('opener', 's');
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$event->SetRedirectParam('pass', 'm,'.$parent_prefix);
}
/**
* Makes left join to item's table, when in separate grid
*
* @param kEvent $event
*/
function OnAfterConfigRead(&$event)
{
parent::OnAfterConfigRead($event);
- if (preg_match('/(.*)-rev/', $event->Prefix, $regs)) {
+ if (preg_match('/(.*)-rev/', $event->Prefix, $regs) && $this->Application->prefixRegistred($regs[1])) {
// "Structure & Data" -> "Reviews" (section in K4)
// 1. add join to items table (for "Structure & Data" -> "Reviews" section)
$item_table = $this->Application->getUnitOption($regs[1], 'TableName');
$list_sqls = $this->Application->getUnitOption($event->Prefix, 'ListSQLs');
$list_sqls[''] .= ' LEFT JOIN '.$item_table.' item_table ON item_table.ResourceId = %1$s.ItemId';
$this->Application->setUnitOption($event->Prefix, 'ListSQLs', $list_sqls);
// 2. add calculated field
$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
$calculated_fields['']['CatalogItemName'] = 'item_table.' . $this->getTitleField($regs[1]);
$calculated_fields['']['CatalogItemId'] = 'item_table.' . $this->Application->getUnitOption($regs[1], 'IDField');
$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
}
}
/**
* Convert TitleField field of kMultiLanguage formatter used for it
*
* @param string $prefix
* @return string
*/
function getTitleField($prefix)
{
$lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_';
$title_field = $this->Application->getUnitOption($prefix, 'TitleField');
$field_options = $this->Application->getUnitOption($prefix.'.'.$title_field, 'Fields');
$formatter_class = isset($field_options['formatter']) ? $field_options['formatter'] : '';
if ($formatter_class == 'kMultiLanguage' && !isset($field_options['master_field'])) {
$title_field = $lang_prefix.$title_field;
}
return $title_field;
}
}
?>
\ No newline at end of file
Property changes on: branches/RC/core/units/reviews/reviews_event_handler.php
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.14.2.3
\ No newline at end of property
+1.14.2.4
\ No newline at end of property
Index: branches/RC/core/admin_templates/reviews/reviews.tpl
===================================================================
--- branches/RC/core/admin_templates/reviews/reviews.tpl (revision 10518)
+++ branches/RC/core/admin_templates/reviews/reviews.tpl (revision 10519)
@@ -1,146 +1,145 @@
<inp2:m_include t="incs/header" nobody="yes" noform="yes"/>
<body topmargin="0" leftmargin="8" marginheight="0" marginwidth="8" bgcolor="#FFFFFF">
<inp2:m_RenderElement name="combined_header" section="in-portal:reviews" prefix="c" module="in-portal" title_preset="reviews"/>
<!-- main kernel_form: begin -->
<inp2:m_RenderElement name="kernel_form"/>
<!-- ToolBar --->
<table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td>
<input type="hidden" name="m_cat_id" value="<inp2:m_get name="m_cat_id"/>"/>
<link rel="stylesheet" rev="stylesheet" href="incs/nlsmenu.css" type="text/css" />
<script type="text/javascript" src="js/nlsmenu.js"></script>
<script type="text/javascript" src="js/nlsmenueffect_1_2_1.js"></script>
<script type="text/javascript" src="js/ajax.js"></script>
<script type="text/javascript" src="<inp2:m_TemplatesBase module='in-portal'/>/incs/catalog.js"></script>
<script type="text/javascript">
var menuMgr = new NlsMenuManager("mgr");
menuMgr.timeout = 500;
menuMgr.flowOverFormElement = true;
Request.progressText = '<inp2:m_phrase name="la_title_Loading" escape="1"/>';
Catalog.prototype.AfterInit = function() {
this.switchTab();
}
Catalog.prototype.refreshTab = function($prefix, $div_id, $force) {
var $cat_id = get_hidden_field('m_cat_id');
var $tab_cat_id = document.getElementById($div_id).getAttribute('category_id');
if ($cat_id != $tab_cat_id || $force) {
// query tab content only in case if not queried or category don't match
var $url = this.URLMask.replace('#ITEM_PREFIX#', $prefix).replace('#TAB_NAME#', this.queryTabRegistry('prefix', $prefix, 'tab_id'));
this.BusyRequest[$prefix] = false;
Request.makeRequest($url, this.BusyRequest[$prefix], $div_id, this.successCallback, this.errorCallback, $div_id, this);
}
}
var $Catalog = new Catalog('<inp2:m_Link template="in-portal/reviews/reviews_tab" item_prefix="#ITEM_PREFIX#" tab_name="#TAB_NAME#" pass_through="td,item_prefix,tab_name" td="no" m_cat_id="-1" no_amp="1"/>', 'reviews_', 0);
var a_toolbar = new ToolBar();
a_toolbar.AddButton( new ToolBarButton('edit', '<inp2:m_phrase label="la_ToolTip_Edit" escape="1"/>', edit) );
a_toolbar.AddButton( new ToolBarButton('delete', '<inp2:m_phrase label="la_ToolTip_Delete" escape="1"/>',
function() {
- var $template = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'view_template');
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
- std_delete_items($Catalog.ActivePrefix, $template, 1);
+ std_delete_items($Catalog.ActivePrefix, null, 1);
} ) );
<inp2:m_ModuleInclude template="catalog_buttons" main_template="reviews" skip_prefixes="m,cms"/>
a_toolbar.AddButton( new ToolBarSeparator('sep2') );
a_toolbar.AddButton( new ToolBarButton('approve', '<inp2:m_phrase label="la_ToolTip_Approve" escape="1"/>', function() {
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
$Catalog.submit_event($Catalog.ActivePrefix, 'OnMassApprove');
}
) );
a_toolbar.AddButton( new ToolBarButton('decline', '<inp2:m_phrase label="la_ToolTip_Decline" escape="1"/>', function() {
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
$Catalog.submit_event($Catalog.ActivePrefix, 'OnMassDecline');
}
) );
a_toolbar.AddButton( new ToolBarSeparator('sep3') );
a_toolbar.AddButton( new ToolBarButton('view', '<inp2:m_phrase label="la_ToolTip_View" escape="1"/>', function() {
show_viewmenu(a_toolbar, 'view');
}
) );
a_toolbar.Render();
function edit()
{
$form_name = $Catalog.queryTabRegistry('prefix', $Catalog.ActivePrefix, 'tab_id') + '_form';
var $kf = document.getElementById($form_name);
var $prev_action = $kf.action;
$kf.action = '<inp2:m_t pass="all" pass_through="item_prefix" item_prefix="#PREFIX#" no_amp="1"/>' . replace('#PREFIX#', $Catalog.ActivePrefix);
std_edit_temp_item($Catalog.ActivePrefix, 'in-portal/reviews/review_direct_edit');
$kf.action = $prev_action;
}
</script>
</td>
</tr>
</tbody>
</table>
<inp2:m_RenderElement name="kernel_form_end"/>
<!-- main kernel_form: end -->
<br />
<!-- item tabs: begin -->
<table cellpadding="0" cellspacing="0">
<tr>
<inp2:m_DefineElement name="item_tab" title="">
<td nowrap="nowrap" width="140">
<table id="<inp2:m_param name="prefix"/>-rev_tab" cellpadding="0" cellspacing="0" width="100%" class="catalog-tab-unselected" onclick="$Catalog.switchTab('<inp2:m_param name="prefix"/>-rev');">
<tr>
<td class="catalog-tab-left">
<img src="img/spacer.gif" height="22" width="9" />
</td>
<td class="catalog-tab-middle" width="100%" valign="middle" nowrap="nowrap">
<inp2:m_phrase name="$title"/> <span class="cats_stats">(<span id="<inp2:m_param name="prefix"/>-rev_item_count">?</span>)</span>
</td>
<td class="catalog-tab-right">
<img src="img/spacer.gif" height="22" width="9" />
</td>
<td style="background-color: #FFFFFF;">
<img src="img/spacer.gif" height="1" width="5" />
</td>
</tr>
</table>
</td>
</inp2:m_DefineElement>
<inp2:adm_ListCatalogTabs render_as="item_tab" title_property="ViewMenuPhrase" skip_prefixes="m,cms"/>
</tr>
</table>
<!-- item tabs: end -->
<inp2:m_set prefix_append="-rev" td="no"/>
<inp2:m_ModuleInclude template="catalog_tab" tab_init="2" skip_prefixes="m,cms"/>
<inp2:m_if check="m_get" var="SetTab">
<script type="text/javascript">
$Catalog.switchTab('<inp2:m_get var="SetTab"/>-rev');
</script>
</inp2:m_if>
<script type="text/javascript">
addLoadEvent(
function() {
$Catalog.Init();
}
);
</script>
<inp2:m_include t="incs/footer" noform="yes"/>
\ No newline at end of file
Property changes on: branches/RC/core/admin_templates/reviews/reviews.tpl
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.1.2.1
\ No newline at end of property
+1.1.2.2
\ No newline at end of property

Event Timeline