1 <?php
2
3 4 5 6 7 8
9 class RatingExtension extends DataObjectDecorator {
10
11 public $RatingInt = null;
12 public $RatingFloat = null;
13 public $Votes = null;
14
15 static = false;
16 static $need_auth = false;
17
18 static = 5;
19 static $max_rating = 5;
20 static $vote_cookie_lifetime = 60;
21
22 23 24 25
26 function () {
27 return array(
28 'casting' => array(
29 'RatingInt' => 'Int',
30 'RatingFloat' => 'Decimal',
31 'Votes' => 'Int',
32 'AlreadyVote' =>'Boolean',
33 'ShowForm' =>'Boolean'
34 ),
35 );
36 }
37
38 static function ($allow = true) {
39 self::$allow_comments = $allow;
40 }
41
42 static function ($count) {
43 self::$commentsPerPage = $count;
44 }
45
46 static function set_max_rating($rating = 5) {
47 self::$max_rating = $rating;
48 }
49
50 static function set_vote_cookie_lifetime($time) {
51 self::$vote_cookie_lifetime = $time;
52 }
53
54 static function set_need_auth($need = true) {
55 self::$need_auth = $need;
56 }
57
58 private function run_calc_rate(){
59 $this->RatingFloat = 0;
60 $this->RatingInt = 0;
61 $this->Votes = 0;
62
63 $clazz = $this->owner->ClassName;
64 $id = $this->owner->ID;
65
66 $votes = DataObject::get('RatingDataObject', 'ObjectClass LIKE \''.$clazz.'\' AND ObjectID = '.$id.'');
67
68 if (!$votes) {
69 return false;
70 }
71
72 $summ = 0;
73 $this->Votes = Int::create('Int', $votes->Count());
74
75 foreach ($votes as $vote) {
76 $summ += $vote->Rate;
77 }
78
79 $this->RatingFloat = Decimal::create('Decimal', $summ / $this->Votes->getValue());
80 $this->RatingInt = Int::create('Int', round($summ / $this->Votes->getValue()));
81
82 return true;
83 }
84
85 function getRatingInt(){
86 if(is_null($this->RatingInt))
87 $this->run_calc_rate();
88 return $this->RatingInt;
89 }
90
91 function getRatingFloat(){
92 if(is_null($this->RatingFloat))
93 $this->run_calc_rate();
94 return $this->RatingFloat;
95 }
96
97 function getVotes(){
98 if(is_null($this->Votes))
99 $this->run_calc_rate();
100 return $this->Votes;
101 }
102
103
104 public function VotesIteration() {
105 $rs = new DataObjectSet();
106 $rating = $this->owner->Votes;
107 if ($rating) {
108 for($i = 0; $i < $rating->getValue(); $i++) {
109 $rs->push(new DataObject(array($i)));
110 }
111 }
112 return $rs;
113 }
114
115
116 public function MaxRatingIteration() {
117 $rs = new DataObjectSet();
118 $rating = self::$max_rating;
119 $currentRating = $this->owner->RatingInt;
120 for($i = 0; $i < $rating; $i++) {
121 $active = ($currentRating) ? ($i < $currentRating->getValue()) : 0;
122 $rs->push(new DataObject(array('Index' => $i, 'Active' => $active)));
123 }
124 return $rs;
125 }
126
127 function getAlreadyVote(){
128 $ratingID = Cookie::get('ratingid');
129 if ($ratingID) {
130 return !RatingDataObject::is_unique($ratingID, $this->owner->ClassName, $this->owner->ID);
131 }
132 return false;
133 }
134
135 static function VoteNeedAuth() {
136 return (self::$need_auth && !Member::CurrentUserID());
137 }
138
139 public function VoteForm() {
140 if (self::$need_auth) {
141 if (!Member::CurrentUserID()) {
142 return false;
143 }
144 }
145
146 $votes = array();
147 for($i = 1; $i <= self::$max_rating; $i++) {
148 $votes[$i] = $i;
149 }
150
151 $required = array();
152 $fields = new FieldSet(
153 new HiddenField("objid", "objid", $this->owner->ID),
154 new HiddenField("objcls", "objcls", $this->owner->ClassName),
155 new DropdownField('vote', _t('Rating.Vote',"Vote"), $votes)
156 );
157
158 if (self::$allow_comments) {
159 $required[] = 'author';
160 $required[] = 'comment';
161 $author = '';
162 if (Member::currentUserID()) {
163 $member = Member::currentUser();
164 $author = trim($member->FirstName . ' ' . $member->Surname);
165 }
166 $fields->push(new TextField('author', _t('Rating.Author', "Author"), $author));
167 $fields->push(new TextAreaField('comment', _t('Rating.Сomment', "Сomment")));
168 }
169
170 $form = new Form(
171 new RatingExtension_Controller(),
172 "vote",
173 $fields,
174 new FieldSet(new FormAction('rating', 'Проголосовать')),
175 new RequiredFields($required)
176 );
177 $form->disableSecurityToken();
178 return $form;
179 }
180
181 182 183 184 185
186 public function () {
187 $start = 0;
188
189 if (isset($_GET['voteStart'])) {
190 $start = (int) $_GET['voteStart'];
191 }
192 $count = self::$commentsPerPage;
193 $ID = $this->owner->ID;
194 $ClassName = $this->owner->ClassName;
195
196 $rs = DataObject::get('RatingDataObject', "ObjectClass = '{$ClassName}' AND ObjectID = '{$ID}'", 'ID DESC', '', "$start,$count");
197 if (!$rs)
198 return false;
199 $rs->setPaginationGetVar('voteStart');
200 return $rs;
201 }
202
203 204 205 206 207
208 static function genRatingID() {
209 $str = '';
210 for($i = 0; $i < 10; $i++) {
211 $str .= rand(0, 9);
212 }
213 return md5($str . time());
214 }
215
216 }
217
218 class RatingExtension_Controller extends ContentController {
219
220 221 222 223 224 225 226
227 function vote($data) {
228 $error = false;
229
230 if (RatingExtension::VoteNeedAuth()) {
231 $error = true;
232 $error_msg = _t('Rating.NeedAuth',"Необходима авторизация");
233 }
234
235
236 $comment = '';
237 $author = '';
238 if(!$error && isset($data) && isset($data['objid']) && isset($data['objcls']) && isset($data['vote'])){
239 if(is_numeric($data['objid']) && is_numeric($data['vote'])){
240 $vote = $data['vote'];
241 $cls = Convert::raw2sql($data['objcls']);
242 $id = Convert::raw2sql($data['objid']);
243 if (RatingExtension::$allow_comments) {
244 $comment = (isset($data['comment'])) ? Convert::raw2sql(trim($data['comment'])) : '';
245 $author = (isset($data['author'])) ? Convert::raw2sql(trim($data['author'])) : '';
246 }
247 }
248 else{
249 $error = true;
250 $error_msg = _t('Rating.Error',"Недопустимое действие");
251 }
252 }
253
254 elseif (!$error){
255 $cls = Convert::raw2sql(Director::urlParam('ID'));
256 $id = (int) Director::urlParam('OtherID');
257 $vote = (int) Director::urlParam('AnotherID');
258 $vote = ($vote) ? $vote : 1;
259
260 if (RatingExtension::$allow_comments) {
261 $comment = (isset($_REQUEST['comment'])) ? Convert::raw2sql(trim($_REQUEST['comment'])) : '';
262 $author = (isset($_REQUEST['author'])) ? Convert::raw2sql(trim($_REQUEST['author'])) : '';
263 }
264 }
265
266 if (!(($vote >= 0) && ($vote <= RatingExtension::$max_rating))) {
267 $error = true;
268 $error_msg = _t('Rating.BadVote',"Неверная оценка!");
269 }
270
271
272 if(!$error && isset($vote) && isset($cls) && isset($id)){
273
274 if(ClassInfo::exists($cls) && ClassInfo::is_subclass_of($cls, 'DataObject') && DataObject::has_extension($cls, 'RatingExtension')){
275 $ratingID = Cookie::get('ratingid');
276 if (!$ratingID) {
277 $ratingID = RatingExtension::genRatingID();
278 Cookie::set('ratingid', $ratingID, RatingExtension::$vote_cookie_lifetime);
279 }
280 if (RatingDataObject::is_unique($ratingID, $cls, $id)) {
281 $rateData = new RatingDataObject(
282 array(
283 'RatingID'=> Convert::raw2sql($ratingID),
284 'ObjectClass' => $cls,
285 'ObjectID' => $id,
286 'Rate' => $vote,
287 'Comment' => $comment,
288 'Author' => $author,
289 'VotedUserID' => Member::currentUserID()
290 )
291 );
292 $rateData->write();
293 }
294 else {
295 $error = true;
296 $error_msg = _t('Rating.Voted',"Вы уже голосовали");
297 }
298 } else {
299 $error = true;
300 $error_msg = _t('Rating.Error',"Недопустимое действие");
301 }
302 }
303
304 if($this->isAjax()){
305
306 if ($error) {
307 return Convert::array2json(array('error'=>$error_msg));
308 }
309 $obj = DataObject::get_by_id($cls, $id);
310
311 return Convert::array2json(array(
312 'RatingInt' => $obj->getRatingInt()->getValue(),
313 'RatingFloat' => $obj->getRatingFloat()->Nice(),
314 'Votes' => $obj->getVotes()->getValue(),
315 'AlreadyVote' => $obj->getAlreadyVote()
316 ));
317 }
318
319 if($error && isset($error_msg)){
320 return $this->renderWith(array('RatingErrorPage', 'ErrorPage', 'Page'),array('Title'=>_t('Rating.ErrorTitle', 'Ошибка'), 'Content' => $error_msg));
321 }
322 Director::redirectBack();
323 return null;
324 }
325
326 327 328 329 330 331 332 333
334 function ($data) {
335 $error = false;
336 if(isset($data) && isset($data['objid']) && isset($data['objcls']) && isset($data['start'])){
337 if(is_numeric($data['objid']) && is_numeric($data['start'])){
338 $start = (int)$data['start'];
339 $cls = Convert::raw2sql($data['objcls']);
340 $id = Convert::raw2sql($data['objid']);
341 }
342 else{
343 $error = true;
344 $error_msg = _t('Rating.Error',"Недопустимое действие");
345 }
346 } else {
347 $cls = Convert::raw2sql(Director::urlParam('ID'));
348 $id = (int) Director::urlParam('OtherID');
349 $start = (int) Director::urlParam('AnotherID');
350 }
351
352 $comments = new DataObjectSet();
353 if (!$error) {
354 $count = RatingExtension::$commentsPerPage;
355 $comments = DataObject::get('RatingDataObject', "ObjectClass = '{$cls}' AND ObjectID = '{$id}'", 'ID DESC', '', "$start,$count");
356 }
357 return $this->renderWith('RatingCommentsList', array('VoteComments'=> $comments));
358 }
359 }
360
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-