Index: branches/RC/core/units/general/cat_tag_processor.php
===================================================================
diff -u -N -r10712 -r10870
--- branches/RC/core/units/general/cat_tag_processor.php (.../cat_tag_processor.php) (revision 10712)
+++ branches/RC/core/units/general/cat_tag_processor.php (.../cat_tag_processor.php) (revision 10870)
@@ -404,40 +404,13 @@
*/
function VotesIndicator($params)
{
- $blocks_params = $this->prepareTagParams($params);
- $blocks_params['name'] = $params['render_as'];
-
$object =& $this->getObject($params);
/* @var $object kDBItem */
- if (false && $this->Application->ConfigValue('UseFloatRating')) {
- $rating = $object->GetDBField('CachedRating');
- $float_rating = floor(($rating - floor($rating)) / 0.25) * 0.25;
- }
- else {
- $rating = round( $object->GetDBField('CachedRating') );
- $float_rating = 0;
- }
+ $rating_helper =& $this->Application->recallObject('RatingHelper');
+ /* @var $rating_helper RatingHelper */
- $i = 1;
- $ret = '';
- while ($i <= 5) {
- $blocks_params['number'] = $i;
- $blocks_params['active'] = $rating >= $i ? 1 : 0;
-
- if ($rating > $i - 1 && $rating < $i && $float_rating > 0) {
- $blocks_params['active'] = 1;
- $blocks_params['float_rating'] = $float_rating;
- }
- else {
- $blocks_params['float_rating'] = '';
- }
-
- $ret .= trim($this->Application->ParseBlock($blocks_params));
- $i++;
- }
-
- return $ret;
+ return $rating_helper->ratingBar($object);
}
function RelevanceIndicator($params)
Index: branches/RC/core/units/general/helpers/rating_helper.php
===================================================================
diff -u -N
--- branches/RC/core/units/general/helpers/rating_helper.php (revision 0)
+++ branches/RC/core/units/general/helpers/rating_helper.php (revision 10870)
@@ -0,0 +1,165 @@
+ 'lu_CurrentRating',
+ 'vote_title' => 'lu_VoteTitle',
+ 'vote_count' => 'lu_VoteCount',
+ 'invalid_rating' => 'lu_InvalidRating',
+ 'already_voted' => 'lu_AlreadyVoted',
+ 'thanks_for_voting' => 'lu_ThanksForVoting',
+ );
+
+ /**
+ * Draws rating bar for a given category item
+ *
+ * @param kDBItem $object
+ * @param bool $show_div
+ * @param string $additional_msg
+ * @return string
+ */
+ function ratingBar(&$object, $show_div = true, $additional_msg = '')
+ {
+ $perm_prefix = $this->Application->getUnitOption($object->Prefix, 'PermItemPrefix');
+ $static = !$this->Application->CheckPermission($perm_prefix . '.RATE', 0, $object->GetDBField('CategoryId'));
+
+ $total_votes = $object->GetDBField('CachedVotesQty');
+ $total_rating = $object->GetDBField('CachedRating') * $total_votes;
+
+ $spam_helper =& $this->Application->recallObject('SpamHelper');
+ /* @var $spam_helper SpamHelper */
+
+ $config_mapping = $this->Application->getUnitOption($object->Prefix, 'ConfigMapping');
+ $review_settings = $config_mapping['RatingDelayValue'].':'.$config_mapping['RatingDelayInterval'];
+ $spam_helper->InitHelper($object->GetDBField('ResourceId'), 'Rating', $review_settings);
+
+ $user_voted = $spam_helper->InSpamControl();
+
+ // now draw the rating bar
+ $rating_width = $total_votes ? @number_format($total_rating / $total_votes, 2) * $this->ratingUnitWidth : 0;
+ $rating1 = $total_votes ? @number_format($total_rating / $total_votes, 1) : 0;
+ $rating2 = $total_votes ? @number_format($total_rating / $total_votes, 2) : 0;
+
+ $rater = '
+ ' . $this->_replaceInPhrase('current_rating', Array ('' . $rating2 . ' ', $this->ratingMaximal)) . ' ';
+
+ if (!$static && !$user_voted) {
+ // allow to set rating when not static and user not voted before
+ for ($ncount = 1; $ncount <= $this->ratingMaximal; $ncount++) {
+ $rater .= '' . $ncount . ' ';
+ }
+ }
+
+ $msg_class = Array ();
+
+ if ($static) {
+ $msg_class[] = 'static';
+ }
+
+ if ($user_voted) {
+ $msg_class[] = 'voted';
+ }
+
+ $rater .= '
+ ' .
+ $this->_replaceInPhrase('vote_title', Array(''.$rating1.' ', $this->ratingMaximal)) . ' ('. $this->_replaceInPhrase('vote_count', Array($total_votes)) . ') ' . $additional_msg . '
+
';
+
+ if ($show_div) {
+ // adds div around rating stars (when drawing rating first time)
+ $rater = '';
+ }
+
+ return $rater;
+ }
+
+ /**
+ * Saves user's vote, when allowed
+ *
+ * @param kDBItem $object
+ * @return string
+ */
+ function makeVote(&$object)
+ {
+ $spam_helper =& $this->Application->recallObject('SpamHelper');
+ /* @var $spam_helper SpamHelper */
+
+ $config_mapping = $this->Application->getUnitOption($object->Prefix, 'ConfigMapping');
+ $review_settings = $config_mapping['RatingDelayValue'].':'.$config_mapping['RatingDelayInterval'];
+ $spam_helper->InitHelper($object->GetDBField('ResourceId'), 'Rating', $review_settings);
+
+ if (!$object->isLoaded() || $spam_helper->InSpamControl()) {
+ return '@err:' . $this->_replaceInPhrase('already_voted');
+ }
+
+ $perm_prefix = $this->Application->getUnitOption($object->Prefix, 'PermItemPrefix');
+ $can_rate = $this->Application->CheckPermission($perm_prefix . '.RATE', 0, $object->GetDBField('CategoryId'));
+ $rating = (int)$this->Application->GetVar('rating'); // not numeric rating is from GoogleBot :(
+
+ if (($rating <= 0) || ($rating > $this->ratingMaximal) || !$can_rate) {
+ return '@err:' . $this->_replaceInPhrase('invalid_rating');
+ }
+
+ // save current rating
+ $fields_hash = Array (
+ 'ItemId' => $object->GetID(),
+ 'RatingValue' => $rating,
+ 'IPAddress' => $_SERVER['REMOTE_ADDR'],
+ 'CreatedOn' => adodb_mktime(),
+ );
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ItemRating');
+
+ // recalculate average rating
+ $votes_count = $object->GetDBField('CachedVotesQty');
+ $avg_rating = $object->GetDBField('CachedRating');
+
+ $avg_rating = round((($votes_count * $avg_rating) + $rating) / ($votes_count + 1), 2);
+ $object->SetDBField('CachedRating', "$avg_rating");
+ $object->Update();
+
+ $sql = 'UPDATE '.$object->TableName.'
+ SET CachedVotesQty = CachedVotesQty + 1
+ WHERE '.$object->IDField.' = '.$object->GetID();
+ $this->Conn->Query($sql);
+
+ $object->SetDBField('CachedVotesQty', $object->GetDBField('CachedVotesQty') + 1); // for using in template
+
+ // prevent user from voting too quickly
+ $spam_helper->AddToSpamControl();
+
+ return $this->ratingBar($object, false, '' . $this->_replaceInPhrase('thanks_for_voting') . ' ');
+ }
+
+ /**
+ * Performs sprintf on phrase translation using given variables
+ *
+ * @param string $phrase
+ * @param Array $arguments
+ * @return string
+ */
+ function _replaceInPhrase($phrase, $arguments = Array ())
+ {
+ $value = $this->Application->Phrase($this->_phrases[$phrase]);
+
+ if ($arguments) {
+ return vsprintf($value, $arguments);
+ }
+
+ return $value;
+ }
+ }
\ No newline at end of file
Index: branches/RC/themes/default2007/platform/elements/html_head.tpl
===================================================================
diff -u -N -r10362 -r10870
--- branches/RC/themes/default2007/platform/elements/html_head.tpl (.../html_head.tpl) (revision 10362)
+++ branches/RC/themes/default2007/platform/elements/html_head.tpl (.../html_head.tpl) (revision 10870)
@@ -6,13 +6,13 @@
- " />
+ " />
" />
- " />
+ " />
" />
@@ -25,14 +25,20 @@
-
+
inc/lbox/lightbox.css" type="text/css" media="screen" />
+
inc/styles.css" type="text/css" />
-inc/script.js">
-inc/calendar.js">
+
+
+
+
-inc/lbox/prototype.js">
-inc/lbox/scriptaculous.js?load=effects">
-inc/lbox/lightbox.js">
+
+
+
+
\ No newline at end of file
Index: branches/RC/core/units/general/cat_event_handler.php
===================================================================
diff -u -N -r10796 -r10870
--- branches/RC/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 10796)
+++ branches/RC/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 10870)
@@ -19,10 +19,9 @@
'OnBeforeDeleteOriginal' => Array('self' => 'edit|advanced:approve'),
'OnDownloadFile' => Array('self' => 'view'),
-
'OnCancelAction' => Array('self' => true),
-
'OnItemBuild' => Array('self' => true),
+ 'OnMakeVote' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
@@ -1118,7 +1117,15 @@
}
foreach ($field_list as $field) {
- $config_elem = $search_config[ $search_config_map[$field] ];
+
+ if (!array_key_exists($field, $search_config_map)) {
+ $map_key = $search_config_map[$items_table . '.' . $field];
+ }
+ else {
+ $map_key = $search_config_map[$field];
+ }
+
+ $config_elem = $search_config[ $map_key ];
$weight = $config_elem['Priority'];
$revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)';
foreach ($positive_words as $keyword) {
@@ -2432,6 +2439,31 @@
$filename = $object->GetField($field, 'full_path');
$file_helper->DownloadFile($filename);
}
+
+ /**
+ * Saves user's vote
+ *
+ * @param kEvent $event
+ */
+ function OnMakeVote(&$event)
+ {
+ $event->status = erSTOP;
+
+ if ($this->Application->GetVar('ajax') != 'yes') {
+ // this is supposed to call from AJAX only
+ return ;
+ }
+
+ $rating_helper =& $this->Application->recallObject('RatingHelper');
+ /* @var $rating_helper RatingHelper */
+
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
+ $object->Load( $this->Application->GetVar('id') );
+
+ echo $rating_helper->makeVote($object);
+ }
}
?>
\ No newline at end of file
Index: branches/RC/themes/default2007/platform/img/starrating.gif
===================================================================
diff -u -N
Binary files differ
Index: branches/RC/core/kernel/db/db_tag_processor.php
===================================================================
diff -u -N -r10859 -r10870
--- branches/RC/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 10859)
+++ branches/RC/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 10870)
@@ -1408,6 +1408,20 @@
return $ret;
}
+ /**
+ * Checks, that grid has icons defined and they should be shown
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function UseItemIcons($params)
+ {
+ $object =& $this->getObject($params);
+
+ $grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
+ return array_key_exists('Icons', $grids[ $params['grid'] ]);
+ }
+
function ItemIcon($params)
{
$object =& $this->getObject($params);
Index: branches/RC/core/units/general/helpers/helpers_config.php
===================================================================
diff -u -N -r10155 -r10870
--- branches/RC/core/units/general/helpers/helpers_config.php (.../helpers_config.php) (revision 10155)
+++ branches/RC/core/units/general/helpers/helpers_config.php (.../helpers_config.php) (revision 10870)
@@ -26,5 +26,6 @@
Array('pseudo'=>'CategoryHelper','class'=>'CategoryHelper','file'=>'category_helper.php','build_event'=>'','require_classes'=>'kHelper'),
Array('pseudo'=>'CSVHelper','class'=>'kCSVHelper','file'=>'csv_helper.php','build_event'=>'','require_classes'=>'kHelper'),
Array('pseudo'=>'ChartHelper','class'=>'kChartHelper','file'=>'chart_helper.php','build_event'=>'','require_classes'=>'kHelper'),
+ Array('pseudo'=>'RatingHelper','class'=>'RatingHelper','file'=>'rating_helper.php','build_event'=>'','require_classes'=>'kHelper'),
),
);
\ No newline at end of file
Index: branches/RC/themes/default2007/platform/inc/styles.css
===================================================================
diff -u -N -r10833 -r10870
--- branches/RC/themes/default2007/platform/inc/styles.css (.../styles.css) (revision 10833)
+++ branches/RC/themes/default2007/platform/inc/styles.css (.../styles.css) (revision 10870)
@@ -508,6 +508,89 @@
vertical-align:top;
}
+/* --- Item Raring Styles --- */
+.ratingblock, .ratingblock div {
+ display: block;
+}
+
+.unit-rating { /* the UL */
+ list-style: none;
+ margin: 0px;
+ padding: 0px;
+ height: 30px;
+ position: relative;
+ background: url('../img/starrating.gif') top left repeat-x;
+}
+
+.unit-rating li {
+ text-indent: -90000px;
+ padding: 0px;
+ margin: 0px;
+ /*\*/
+ float: left;
+ /* */
+}
+
+.unit-rating li a {
+ outline: none;
+ display: block;
+ width: 30px;
+ height: 30px;
+ text-decoration: none;
+ text-indent: -9000px;
+ z-index: 20;
+ position: absolute;
+ padding: 0px;
+}
+
+.unit-rating li a:hover {
+ background: url('../img/starrating.gif') left center;
+ z-index: 2;
+ left: 0px;
+}
+
+.unit-rating a.r1-unit{left: 0px;}
+.unit-rating a.r1-unit:hover{width:30px;}
+.unit-rating a.r2-unit{left:30px;}
+.unit-rating a.r2-unit:hover{width: 60px;}
+.unit-rating a.r3-unit{left: 60px;}
+.unit-rating a.r3-unit:hover{width: 90px;}
+.unit-rating a.r4-unit{left: 90px;}
+.unit-rating a.r4-unit:hover{width: 120px;}
+.unit-rating a.r5-unit{left: 120px;}
+.unit-rating a.r5-unit:hover{width: 150px;}
+.unit-rating a.r6-unit{left: 150px;}
+.unit-rating a.r6-unit:hover{width: 180px;}
+.unit-rating a.r7-unit{left: 180px;}
+.unit-rating a.r7-unit:hover{width: 210px;}
+.unit-rating a.r8-unit{left: 210px;}
+.unit-rating a.r8-unit:hover{width: 240px;}
+.unit-rating a.r9-unit{left: 240px;}
+.unit-rating a.r9-unit:hover{width: 270px;}
+.unit-rating a.r10-unit{left: 270px;}
+.unit-rating a.r10-unit:hover{width: 300px;}
+
+.unit-rating li.current-rating {
+ background: url('../img/starrating.gif') left bottom;
+ position: absolute;
+ height: 30px;
+ display: block;
+ text-indent: -9000px;
+ z-index: 1;
+}
+
+.voted {
+ color: #999;
+}
+
+.thanks {
+ color: #36AA3D;
+}
+
+.static {
+ color: #5D3126;
+}
+
/* --- Unprocessed Styles --- */
.text-title {
font-size: 12px;
@@ -544,4 +627,4 @@
.information-background {
background-color: #F6F6FF;
-}
\ No newline at end of file
+}
Index: branches/RC/themes/default2007/platform/inc/ajax.js
===================================================================
diff -u -N
--- branches/RC/themes/default2007/platform/inc/ajax.js (revision 0)
+++ branches/RC/themes/default2007/platform/inc/ajax.js (revision 10870)
@@ -0,0 +1,240 @@
+function preg_print_pre(obj, reg)
+{
+ if (!reg) reg = /.*/;
+ var p = ''
+ for (var prop in obj) {
+ if (prop.match(reg) ) {
+ p += prop + ': '+obj[prop] + '\n'
+ }
+ }
+ alert(p)
+}
+
+
+// Main AJAX classs
+function Request() {}
+
+Request.timeout = 60000; //60 seconds
+Request.method = 'GET';
+Request.headers = new Array();
+Request.params = null;
+
+Request.makeRequest = function(p_url, p_busyReq, p_progId, p_successCallBack, p_errorCallBack, p_pass, p_object) {
+ //p_url: the web service url
+ //p_busyReq: is a request for this object currently in progress?
+ //p_progId: element id where progress HTML should be shown
+ //p_successCallBack: callback function for successful response
+ //p_errorCallBack: callback function for erroneous response
+ //p_pass: string of params to pass to callback functions
+ //p_object: object of params to pass to callback functions
+
+ if (p_busyReq) return;
+ var req = Request.getRequest();
+ if (req != null) {
+ p_busyReq = true;
+ Request.showProgress(p_progId);
+ req.onreadystatechange = function() {
+ if (req.readyState == 4) {
+ p_busyReq = false;
+ window.clearTimeout(toId);
+ try {
+ if (req.status == 200) {
+ // preg_print_pre(req)
+ p_successCallBack(req, p_pass, p_object);
+ } else {
+ p_errorCallBack(req, p_pass, p_object);
+ }
+ Request.hideProgress(p_progId);
+ }
+ catch (e) {
+// alert('AJAX error')
+ }
+ }
+ }
+ var $ajax_mark = (p_url.indexOf('?') ? '&' : '?') + 'ajax=yes';
+ req.open(Request.method, p_url + $ajax_mark, true);
+
+ if (Request.method == 'POST') {
+ Request.headers['Content-type'] = 'application/x-www-form-urlencoded';
+ Request.headers['referer'] = p_url;
+ }
+ else {
+ Request.headers['If-Modified-Since'] = 'Sat, 1 Jan 2000 00:00:00 GMT';
+ }
+
+ Request.sendHeaders(req);
+ if (Request.method == 'POST') {
+ req.send(Request.params);
+ Request.method = 'GET'; // restore method back to GET
+ }
+ else {
+ req.send(null);
+ }
+
+ var toId = window.setTimeout( function() {if (p_busyReq) req.abort();}, Request.timeout );
+ }
+}
+
+Request.processRedirect = function($request) {
+ var $match_redirect = new RegExp('^#redirect#(.*)').exec($request.responseText);
+ if ($match_redirect != null) {
+ // redirect to external template requested
+ window.location.href = $match_redirect[1];
+ return true;
+ }
+ return false;
+}
+Request.sendHeaders = function($request) {
+ for (var $header_name in Request.headers) {
+ if (typeof Request.headers[$header_name] == 'function') {
+ continue;
+ }
+ $request.setRequestHeader($header_name, Request.headers[$header_name]);
+ }
+ Request.headers = new Array(); // reset header afterwards
+}
+
+Request.getRequest = function() {
+ var xmlHttp;
+ try { xmlHttp = new ActiveXObject('MSXML2.XMLHTTP'); return xmlHttp; } catch (e) {}
+ try { xmlHttp = new ActiveXObject('Microsoft.XMLHTTP'); return xmlHttp; } catch (e) {}
+ try { xmlHttp = new XMLHttpRequest(); return xmlHttp; } catch(e) {}
+ return null;
+}
+
+Request.showProgress = function(p_id) {
+ if (p_id != '') {
+ Request.setOpacity(20, p_id);
+
+ if (!document.getElementById(p_id + '_progress')) {
+ document.body.appendChild(Request.getProgressObject(p_id));
+ }
+ else {
+ var $progress_div = document.getElementById(p_id + '_progress');
+ $progress_div.style.top = getRealTop(p_id) + 'px';
+ $progress_div.style.height = document.getElementById(p_id).clientHeight;
+ $progress_div.style.display = 'block';
+ }
+// document.getElementById(p_id).innerHTML = Request.getProgressHtml();
+ }
+}
+
+Request.hideProgress = function(p_id) {
+ if (p_id != '') {
+ document.getElementById(p_id + '_progress').style.display = 'none';
+ Request.setOpacity(100, p_id);
+ }
+}
+
+Request.setOpacity = function (opacity, id) {
+ var elem = typeof(id)=='string' ? document.getElementById(id) : id;
+ var object = elem.style;
+ object.opacity = (opacity / 100);
+ object.MozOpacity = (opacity / 100);
+ object.KhtmlOpacity = (opacity / 100);
+ object.filter = "alpha(opacity=" + opacity + ")";
+}
+
+Request.getProgressHtml = function() {
+ return "" + Request.progressText + "
";
+}
+
+Request.getProgressObject = function($id) {
+ var $div = document.createElement('DIV');
+ var $parent_div = document.getElementById($id);
+
+ $div.id = $id + '_progress';
+
+ $div.style.width = $parent_div.clientWidth + 'px';
+ $div.style.height = '150px'; // default height if div is empty (first ajax request for div)
+ $div.style.left = getRealLeft($parent_div) + 'px';
+ $div.style.top = getRealTop($parent_div) + 'px';
+ $div.style.position = 'absolute';
+
+ /*$div.style.border = '1px solid green';
+ $div.style.backgroundColor = '#FF0000';*/
+
+ $div.innerHTML = ''+Request.progressText+'
';
+ return $div;
+}
+
+Request.getErrorHtml = function(p_req) {
+ //TODO: implement accepted way to handle request error
+ return '[status: ' + p_req.status + '; status_text: ' + p_req.statusText + '; responce_text: ' + p_req.responseText + ']';
+}
+
+Request.serializeForm = function(theform) {
+ if (typeof(theform) == 'string') {
+ theform = document.getElementById(theform);
+ }
+
+ var els = theform.elements;
+ var len = els.length;
+ var queryString = '';
+
+ Request.addField = function(name, value) {
+ if (queryString.length > 0) queryString += '&';
+ queryString += encodeURIComponent(name) + '=' + encodeURIComponent(value);
+ };
+
+ for (var i = 0; i= 0) {
+ Request.addField(el.name, el.options[el.selectedIndex].value);
+ }
+ break;
+
+ case 'select-multiple':
+ for (var j = 0; j < el.options.length; j++) {
+ if (!el.options[j].selected) continue;
+ Request.addField(el.name, el.options[j].value);
+ }
+ break;
+
+ case 'checkbox':
+ case 'radio':
+ if (!el.checked) continue;
+ Request.addField(el.name,el.value);
+ break;
+ }
+ }
+ return queryString;
+};
+
+function RatingManager ($url) {
+ this.Url = $url;
+ this.BusyRequest = false;
+}
+
+RatingManager.prototype.makeVote = function ($vote, $prefix, $id) {
+ var $url = this.Url.replace('#PREFIX#', $prefix).replace('#VOTE#', $vote).replace('#ID#', $id);
+
+ Request.makeRequest($url, this.BusyRequest, '', this.successCallback, this.errorCallback, [$vote, $prefix, $id], this);
+}
+
+RatingManager.prototype.successCallback = function ($request, $params, $object) {
+ var response = $request.responseText;
+
+ if (response.substring(0, 5) == '@err:') {
+ alert(response.substring(5));
+ return ;
+ }
+
+ document.getElementById('page_rating_' + $params[2]).innerHTML = response;
+}
+
+
+RatingManager.prototype.errorCallback = function($request, $params, $object) {
+ alert('AJAX Error; class: RatingManager; ' + Request.getErrorHtml($request));
+}
\ No newline at end of file