upload facility now works in single CIS mode; some simple command-line video moderati...
[living-lab-site.git] / application / models / videos_model.php
1 <?php
2
3 /**
4  * Class Videos_model models videos information from the DB
5  *
6  * @category    Model
7  * @author              Călin-Andrei Burloiu
8  */
9 class Videos_model extends CI_Model {
10         public $db = NULL;
11         
12         public function __construct()
13         {
14                 parent::__construct();
15                 
16                 if ($this->db === NULL)
17                 {
18                         $this->load->library('singleton_db');
19                         $this->db = $this->singleton_db->connect();
20                 }
21         }
22         
23         /**
24          * Retrieves a set of videos information which can be used for displaying
25          * that videos as a list with few details.
26          *
27          * @param               int $category_id        DB category ID; pass NULL for all
28          * categories
29          * @param mixed $user an user_id (as int) or an username 
30          * (as string); pass NULL for all users
31          * @param int $offset
32          * @param int $count number of videos to retrieve; if set to TRUE this
33          * method will retrieve the number of videos that satisfy condition
34          * @param string $ordering      control videos ording by these
35          * possibilities:
36          * <ul>
37          *   <li><strong>'hottest':</strong> newest most appreciated first. An
38          *   appreciated video is one which has a bigger
39          *   score = views + likes - dislikes.</li>
40          *   <li><strong>'newest':</strong> newest first.</li>
41          *   <li><strong>'alphabetically':</strong> sort alphabetically.</li>
42          * </ul>
43          * @param bool $unactivated whether to retrieve or not ingested unactivated
44          * videos; typically only administrators should see this kind of assets
45          * @return array a list of videos, each one being an assoc array with:
46          * <ul>
47          *   <li>id, name, title, duration, thumbs_count, default_thumb, views => from DB</li>
48          *   <li>shorted_title => ellipsized title</li>
49          *   <li>video_url => P2P-Tube video URl</li>
50          *   <li>user_id, user_name</li>
51          *   <li>thumbs => thumbnail images' URLs</li>
52          * </ul>
53          */
54         public function get_videos_summary($category_id, $user, $offset, $count,
55                 $ordering = 'hottest', $unactivated = FALSE)
56         {
57                 $this->load->helper('text');
58                 
59                 $order_statement = "";
60                 if ($count !== TRUE)
61                 {
62                         // Ordering
63                         switch ($ordering)
64                         {
65                         case 'hottest':
66                                 $order_statement = "ORDER BY date DESC, score DESC, RAND()";
67                                 break;
68                         case 'newest':
69                                 $order_statement = "ORDER BY date DESC";
70                                 break;
71                         case 'alphabetically':
72                                 $order_statement = "ORDER BY title";
73                                 break;
74
75                         default:
76                                 $order_statement = "";
77                         }
78                 }
79                 
80                 // Show unactivated videos.
81                 $cond_unactivated = ($unactivated
82                                 ? '(a.activation_code IS NULL OR a.activation_code IS NOT NULL
83                                         AND a.content_ingested = 1)'
84                                 : 'a.activation_code IS NULL');
85                 
86                 // Category filtering
87                 if ($category_id === NULL)
88                         $cond_category = "1";
89                 else
90                 {
91                         $category_id = intval($category_id);
92                         $cond_category = "category_id = $category_id";
93                 }
94                 
95                 // User filtering
96                 if ($user === NULL)
97                         $cond_user = "1";
98                 else
99                 {
100                         if (is_int($user))
101                                 $cond_user = "v.user_id = $user";
102                         else if (is_string($user))
103                                 $cond_user = "u.username = '$user'";
104                 }
105                 
106                 if ($count === TRUE)
107                         $fields = "COUNT(*) count";
108                 else
109                         $fields = "v.id, name, title, duration, user_id, u.username, views,
110                                 thumbs_count, default_thumb,
111                                 (views + likes - dislikes) AS score,
112                                 a.activation_code, a.content_ingested";
113                 
114                 $query = $this->db->query(
115                         "SELECT $fields
116                         FROM `videos` v 
117                                 LEFT JOIN `videos_unactivated` a ON (id = a.video_id),
118                                 `users` u
119                         WHERE v.user_id = u.id AND $cond_category AND $cond_user
120                                 AND $cond_unactivated
121                         $order_statement
122                         LIMIT $offset, $count"); 
123                 
124                 if ($query->num_rows() > 0)
125                 {
126                         if ($count === TRUE)
127                                 return $query->row()->count;
128                         
129                         $videos = $query->result_array();
130                 }
131                 else
132                         return array();
133                 
134                 foreach ($videos as & $video)
135                 {
136                         // P2P-Tube Video URL
137                         $video['video_url'] = site_url(sprintf("watch/%d/%s",
138                                 $video['id'], $video['name']));
139                         
140                         // Thumbnails
141                         $video['thumbs'] = $this->get_thumbs($video['name'], 
142                                 $video['thumbs_count']);
143                                 
144                         // Ellipsized title
145                         //$video['shorted_title'] = ellipsize($video['title'], 45, 0.75);
146                         $video['shorted_title'] = character_limiter($video['title'], 50);
147                 }
148                 
149                 return $videos;
150         }
151         
152         /**
153          * Returns the number of videos from database from a specific category or
154          * user.
155          * NULL parameters count videos from all categories and / or all users.
156          * 
157          * @param int $category_id
158          * @param mixed $user an user_id (as int) or an username (as string)
159          * @return int number of videos or FALSE if an error occured
160          */
161         public function get_videos_count($category_id = NULL, $user = NULL,
162                         $unactivated = FALSE)
163         {
164                 return $this->get_videos_summary($category_id, $user, 0, TRUE, NULL,
165                                 $unactivated);
166         }
167         
168         /**
169          * Retrieves information about a video.
170          *
171          * If $name does not match with the video's `name` from the DB an error is
172          * marked in the key 'err'. If it's NULL it is ignored.
173          *
174          * @access public
175          * @param string $id    video's `id` column from `videos` DB table
176          * @param string $name  video's `name` column from `videos` DB
177          * table. NULL means there is no name provided.
178          * @return array        an associative list with information about a video
179          * with the following keys:
180          * <ul>
181          *   <li>all columns form DB with some exceptions that are overwritten or new</li>
182          *   <li>content is moved in assets</li>
183          *   <li>assets => list of associative lists where each one represents a</li>
184          * video asset having keys: "src", "res", "par" and "ext". Value of key
185          * "src" is the video torrent formated as
186          * {name}_{format}.{video_ext}.{default_torrent_ext}</li>
187          *   <li>username => user name from `users` table</li>
188          *   <li>category_title => a human-friendly category name</li>
189          *   <li>tags => associative list of "tag => score"</li>
190          *   <li>date => date and time when the video was created</li>
191          *   <li>thumbs => thumbnail images' URLs</li>
192          * </ul>
193          */
194         public function get_video($id, $name = NULL)
195         {
196                 $this->load->helper('video');
197                 $this->load->helper('text');
198                 
199                 $query = $this->db->query("SELECT v.*, u.username,
200                                         a.activation_code, a.content_ingested
201                                 FROM `videos` v 
202                                         LEFT JOIN `videos_unactivated` a ON (v.id = a.video_id),
203                                         `users` u
204                                 WHERE v.user_id = u.id AND v.id = $id");
205                 $video = array();
206                 
207                 if ($query->num_rows() > 0)
208                 {
209                         $video = $query->row_array();
210                         if ($name !== NULL && $video['name'] != $name)
211                                 $video['err'] = 'INVALID_NAME';
212                 }
213                 else
214                 {
215                         return FALSE;
216                 }
217                 
218                 // Convert JSON encoded string to arrays.
219                 $video['assets'] = json_decode($video['formats'], TRUE);
220                 unset($video['formats']);
221                 $video['tags'] = json_decode($video['tags'], TRUE);
222                 asort($video['tags']);
223                 $video['tags'] = array_reverse($video['tags'], TRUE);
224                 
225                 // Sort assets by their megapixels number.
226                 function access_function($a) { return $a['res']; }
227                 function assets_cmp($a, $b) 
228                         { return megapixels_cmp($a, $b, "access_function"); }
229                 usort($video['assets'], "assets_cmp");
230                 
231                 // Torrents
232                 $video['url'] = array();
233                 foreach ($video['assets'] as & $asset)
234                 {
235                         $def = substr($asset['res'], strpos($asset['res'], 'x') + 1) . 'p';
236                         $asset['def'] = $def;
237                         $asset['src'] = site_url('data/torrents/'. $video['name'] . '_'
238                                 . $def . '.'. $asset['ext']
239                                 . '.'. $this->config->item('default_torrent_ext'));
240                 }
241                 
242                 // Category title
243                 $categories = $this->config->item('categories');
244                 $category_name = $categories[ intval($video['category_id']) ];
245                 $video['category_title'] = $category_name ?
246                         $this->lang->line("ui_categ_$category_name") : $category_name;
247                 
248                 // Thumbnails
249                 $video['thumbs'] = $this->get_thumbs($video['name'], $video['thumbs_count']);
250                 
251                 // Shorted description
252                 $video['shorted_description'] = character_limiter(
253                                 $video['description'], 128);
254                 
255                 return $video;
256         }
257         
258         /**
259          * Adds a new uploaded video to the DB.
260          * 
261          * @param string $name
262          * @param string $title
263          * @param string $description
264          * @param string $tags comma separated tags
265          * @param string $duration video duration formatted [HH:]mm:ss
266          * @param array $formats a dictionary corresponding to `formats` JSON
267          * column from `videos` table
268          * @param int $category_id
269          * @param int $user_id
270          * @param string $uploaded_file the raw video file uploaded by the user
271          * @return mixed returns an activation code on success or FALSE otherwise
272          */
273         public function add_video($name, $title, $description, $tags, $duration,
274                         $formats, $category_id, $user_id, $uploaded_file)
275         {
276                 // Tags.
277                 $json_tags = array();
278                 $tok = strtok($tags, ',');
279                 while ($tok != FALSE)
280                 {
281                         $json_tags[trim($tok)] = 0;
282                         
283                         $tok = strtok(',');
284                 }
285                 $json_tags = json_encode($json_tags);
286                 
287                 // TODO formats
288                 $json_formats = json_encode($formats);
289                 
290                 $query = $this->db->query("INSERT INTO `videos`
291                                 (name, title, description, duration, formats, category_id,
292                                                 user_id, tags, date)
293                                 VALUES ('$name', '$title', '$description', '$duration',
294                                                 '$json_formats', $category_id,
295                                                 $user_id, '$json_tags', utc_timestamp())");
296                 if ($query === FALSE)
297                         return FALSE;
298                 
299                 // Find out the id of the new video added.
300                 $query = $this->db->query("SELECT id from `videos`
301                                 WHERE name = '$name'");
302                 if ($query->num_rows() === 0)
303                         return FALSE;
304                 $video_id = $query->row()->id;
305                 
306                 // Activation code.
307                 $activation_code = Videos_model::gen_activation_code();
308                 
309                 $query = $this->db->query("INSERT INTO `videos_unactivated`
310                                 (video_id, activation_code, uploaded_file)
311                                 VALUES ($video_id, '$activation_code', '$uploaded_file')");
312                 
313                 return $activation_code;
314         }
315         
316         public function set_content_ingested($activation_code)
317         {
318                 return $this->db->query("UPDATE `videos_unactivated`
319                         SET content_ingested = 1
320                         WHERE activation_code = '$activation_code'");
321         }
322         
323         /**
324          * Activates a video by deleting its entry from `videos_unactivated`.
325          * 
326          * @param mixed $code_or_id use type string for activation_code or type
327          * int for video_id
328          * @return boolean TRUE on success, FALSE otherwise
329          */
330         public function activate_video($code_or_id)
331         {
332                 if (is_string($code_or_id))
333                         $query = $this->db->query("SELECT uploaded_file from `videos_unactivated`
334                                 WHERE activation_code = '$code_or_id'");
335                 else if (is_int($code_or_id))
336                         $query = $this->db->query("SELECT uploaded_file from `videos_unactivated`
337                                 WHERE video_id = '$code_or_id'");
338                 else
339                         return FALSE;
340                 
341                 if ($query->num_rows() > 0)
342                         $uploaded_file = $query->row()->uploaded_file;
343                 else
344                         return FALSE;
345                 
346                 if (is_string($code_or_id))
347                         $query = $this->db->query("DELETE FROM `videos_unactivated`
348                                 WHERE activation_code = '$code_or_id'");
349                 else if (is_int($code_or_id))
350                         $query = $this->db->query("DELETE FROM `videos_unactivated`
351                                 WHERE video_id = '$code_or_id'");
352                 else
353                         return FALSE;
354                 
355                 if (!$query)
356                         return $query;
357                 
358                 return unlink("data/upload/$uploaded_file");            
359         }
360         
361         public function get_unactivated_videos()
362         {
363                 $query = $this->db->query("SELECT a.video_id, v.name, a.content_ingested
364                         FROM `videos_unactivated` a, `videos` v
365                         WHERE a.video_id = v.id AND a.content_ingested = 1");
366                 
367                 if ($query->num_rows() > 0)
368                         return $query->result_array();
369                 else
370                         return FALSE;
371         }
372         
373         /**
374          * Retrieves comments for a video.
375          * 
376          * @param int $video_id
377          * @param int $offset
378          * @param int $count
379          * @param string $ordering      control comments ording by these possibilities:
380          * <ul>
381          *   <li><strong>'hottest':</strong> newest most appreciated first. An
382          *   appreciated comment is one which has a bigger
383          *   score = likes - dislikes.</li>
384          *   <li><strong>'newest':</strong> newest first.</li>
385          * </ul>
386          * @return array        an array with comments
387          */
388         public function get_video_comments($video_id, $offset, $count,
389                         $ordering = 'newest')
390         {
391                 $this->load->helper('date');
392                 $cond_hottest = '';
393                 
394                 // Ordering
395                 switch ($ordering)
396                 {
397                 case 'newest':
398                         $order_statement = "ORDER BY time DESC";
399                         break;
400                 case 'hottest':
401                         $order_statement = "ORDER BY score DESC, time DESC";
402                         $cond_hottest = "AND c.likes + c.dislikes > 0";
403                         break;
404                                 
405                 default:
406                         $order_statement = "";
407                 }
408                 
409                 $query = $this->db->query(
410                         "SELECT c.*, u.username, u.time_zone, (c.likes + c.dislikes) AS score
411                                 FROM `videos_comments` c, `users` u
412                                 WHERE c.user_id = u.id AND video_id = $video_id $cond_hottest
413                                 $order_statement
414                                 LIMIT $offset, $count");
415                 
416                 if ($query->num_rows() == 0)
417                         return array();
418                 
419                 $comments = $query->result_array();
420                 
421                 foreach ($comments as & $comment)
422                 {
423                         $comment['local_time'] = human_gmt_to_human_local($comment['time'],
424                                 $comment['time_zone']);
425                 }
426                 
427                 return $comments;
428         }
429         
430         public function get_video_comments_count($video_id)
431         {
432                 $query = $this->db->query(
433                                         "SELECT COUNT(*) count
434                                                 FROM `videos_comments`
435                                                 WHERE video_id = $video_id");
436                                 
437                 if ($query->num_rows() == 0)
438                         return FALSE;
439                 
440                 return $query->row()->count;
441         }
442         
443         /**
444          * Insert in DB a comment for a video.
445          * 
446          * @param int $video_id
447          * @param int $user_id
448          * @param string $content
449          */
450         public function comment_video($video_id, $user_id, $content)
451         {
452                 // Prepping content.
453                 $content = substr($content, 0, 512);
454                 $content = htmlspecialchars($content);
455                 $content = nl2br($content);
456                 
457                 return $query = $this->db->query(
458                         "INSERT INTO `videos_comments` (video_id, user_id, content, time)
459                         VALUES ($video_id, $user_id, '$content', UTC_TIMESTAMP())");
460         }
461         
462         /**
463          * Increments views count for a video.
464          * 
465          * @param int $id       DB video id
466          * @return void
467          */
468         public function inc_views($id)
469         {
470                 return $this->db->query('UPDATE `videos` '
471                                                 . 'SET `views`=`views`+1 '
472                                                 . 'WHERE id='. $id); 
473         }
474         
475         public function vote($video_id, $user_id, $like = TRUE)
476         {
477                 if ($like)
478                 {
479                         $col = 'likes';
480                         $action = 'like';
481                 }
482                 else
483                 {
484                         $col = 'dislikes';
485                         $action = 'dislike';
486                 }
487                 
488                 $query = $this->db->query("SELECT * FROM `users_actions`
489                         WHERE user_id = $user_id
490                                 AND target_id = $video_id
491                                 AND target_type = 'video'
492                                 AND action = '$action'
493                                 AND date = CURDATE()");
494                 // User already voted today
495                 if ($query->num_rows() > 0)
496                         return -1;
497                 
498                 $this->db->query("UPDATE `videos`
499                         SET $col = $col + 1
500                         WHERE id = $video_id");
501                 
502                 // Mark this action so that the user cannot repeat it today.
503                 $this->db->query("INSERT INTO `users_actions`
504                                 (user_id, action, target_type, target_id, date)
505                         VALUES ( $user_id, '$action', 'video', $video_id, CURDATE() )");
506                 
507                 $query = $this->db->query("SELECT $col FROM `videos`
508                         WHERE id = $video_id");
509                 
510                 if ($query->num_rows() === 1)
511                 {
512                         $row = $query->row_array();
513                         return $row[ $col ];
514                 }
515                 
516                 // Error
517                 return FALSE;
518         }
519         
520         public function vote_comment($comment_id, $user_id, $like = TRUE)
521         {
522                 if ($like)
523                 {
524                         $col = 'likes';
525                         $action = 'like';
526                 }
527                 else
528                 {
529                         $col = 'dislikes';
530                         $action = 'dislike';
531                 }
532         
533                 $query = $this->db->query("SELECT * FROM `users_actions`
534                                 WHERE user_id = $user_id
535                                         AND target_id = $comment_id
536                                         AND target_type = 'vcomment'
537                                         AND action = '$action'
538                                         AND date = CURDATE()");
539                 // User already voted today
540                 if ($query->num_rows() > 0)
541                         return -1;
542         
543                 $this->db->query("UPDATE `videos_comments`
544                                 SET $col = $col + 1
545                                 WHERE id = $comment_id");
546         
547                 // Mark this action so that the user cannot repeat it today.
548                 $this->db->query("INSERT INTO `users_actions`
549                                         (user_id, action, target_type, target_id, date)
550                                 VALUES ( $user_id, '$action', 'vcomment', $comment_id, CURDATE() )");
551         
552                 $query = $this->db->query("SELECT $col FROM `videos_comments`
553                                 WHERE id = $comment_id");
554         
555                 if ($query->num_rows() === 1)
556                 {
557                         $row = $query->row_array();
558                         return $row[ $col ];
559                 }
560         
561                 // Error
562                 return FALSE;
563         }
564         
565         public function get_thumbs($name, $count)
566         {
567                 $thumbs = array();
568                 
569                 for ($i=0; $i < $count; $i++)
570                         $thumbs[] = site_url(sprintf("data/thumbs/%s_t%02d.jpg", $name, $i));
571                 
572                 return $thumbs;
573         }
574
575         /**
576          * Searches videos in DB based on a search query string and returns an
577          * associative array of results.
578          * If count is zero the function only return the number of results.
579          * @param string $search_query
580          * @param int $offset
581          * @param int $count
582          * @param int $category_id      if NULL, all categories are searched
583          * @return array        an associative array with the same keys as that from
584          * get_videos_summary's result, but with two additional keys: 
585          * description and date.
586          */
587         public function search_videos($search_query, $offset = 0, $count = 0, 
588                                                                         $category_id = NULL)
589         {
590                 $search_query = trim($search_query);
591                 $search_query = str_replace("'", " ", $search_query);
592                 
593                 // Search word fragments.
594                 // sfc = search fragment condition
595                 $sfc = "( ";
596                 // sfr = search fragment relevance
597                 $sfr = "( ";
598                 $sep = ' +-*<>()~"';
599                 $fragm = strtok($search_query, $sep);
600                 while ($fragm !== FALSE)
601                 {
602                         $sfc .= "(title LIKE '%$fragm%'
603                                         OR description LIKE '%$fragm%'
604                                         OR tags LIKE '%$fragm%') OR ";
605                         
606                         // Frament relevances are half of boolean relevances such
607                         // that they will appear at the end of the results.
608                         $sfr .= "0.25 * (title LIKE '%$fragm%')
609                                         + 0.1 * (description LIKE '%$fragm%')
610                                         + 0.15 * (tags LIKE '%$fragm%') + ";
611                         
612                         $fragm = strtok($sep);
613                 }
614                 $sfc = substr($sfc, 0, -4) . " )";
615                 $sfr = substr($sfr, 0, -3) . " )";
616                 
617                 if (! $this->is_advanced_search_query($search_query))
618                 {
619                         $search_cond = "MATCH (title, description, tags)
620                                         AGAINST ('$search_query') OR $sfc";
621                         $relevance = "( MATCH (title, description, tags)
622                                         AGAINST ('$search_query') + $sfr ) AS relevance";
623                 }
624                 // boolean mode
625                 else
626                 {
627                         $against = "AGAINST ('$search_query' IN BOOLEAN MODE)";
628                         $search_cond = "( MATCH (title, description, tags)
629                                         $against) OR $sfc";
630                         $relevance = "( 0.5 * (MATCH(title) $against)
631                                         + 0.3 * (MATCH(tags) $against)
632                                         + 0.2 * (MATCH(description) $against)
633                                         + $sfr) AS relevance";
634                 }
635                 
636                 if ($count === 0)
637                 {
638                         $selected_columns = "COUNT(*) count";
639                         $order = "";
640                         $limit = "";
641                 }
642                 else
643                 {
644                         // TODO select data, description if details are needed
645                         $selected_columns = "v.id, name, title, duration, user_id, views,
646                                         thumbs_count, default_thumb, u.username,
647                                         (views + likes - dislikes) AS score, 
648                                         $relevance";
649                         $order = "ORDER BY relevance DESC, score DESC";
650                         $limit = "LIMIT $offset, $count";
651                 }
652                 
653                 if ($category_id !== NULL)
654                         $category_cond = "category_id = '$category_id' AND ";
655                 else
656                         $category_cond = "";
657
658                 $str_query = "SELECT $selected_columns
659                         FROM `videos` v, `users` u
660                         WHERE  v.user_id = u.id AND $category_cond ( $search_cond )
661                         $order
662                         $limit";
663 //              echo "<p>$str_query</p>";
664                 $query = $this->db->query($str_query);
665                 
666                 if ($query->num_rows() > 0)
667                 {
668                         if ($count === 0)
669                                 return $query->row()->count;
670                         else
671                                 $videos = $query->result_array();
672                 }
673                 else
674                         return NULL;
675                 
676                 $this->load->helper('text');
677                 
678                 foreach ($videos as & $video)
679                 {
680                         // P2P-Tube Video URL
681                         $video['video_url'] = site_url(sprintf("watch/%d/%s",
682                                 $video['id'], $video['name']));
683                         
684                         // Thumbnails
685                         $video['thumbs'] = $this->get_thumbs($video['name'], 
686                                 $video['thumbs_count']);
687                                 
688                         // Ellipsized title
689                         //$video['shorted_title'] = ellipsize($video['title'], 45, 0.75);
690                         $video['shorted_title'] = character_limiter($video['title'], 50);
691                         
692                         // TODO: user information
693                         $video['user_name'] = 'TODO';
694                 }
695                 
696                 return $videos;
697         }
698         
699         public function decode_search_query($search_query)
700         {
701                 $search_query = urldecode($search_query);
702                 
703                 $search_query = str_replace('_AST_', '*', $search_query);
704                 $search_query = str_replace('_AND_', '+', $search_query);
705                 $search_query = str_replace('_GT_', '>', $search_query);
706                 $search_query = str_replace('_LT_', '<', $search_query);
707                 $search_query = str_replace('_PO_', '(', $search_query);
708                 $search_query = str_replace('_PC_', ')', $search_query);
709                 $search_query = str_replace('_LOW_', '~', $search_query);
710                 $search_query = str_replace('_QUO_', '"', $search_query);
711                 
712                 return $search_query;
713         }
714         
715         public function encode_search_query($search_query)
716         {
717                 $search_query = str_replace('*', '_AST_', $search_query);
718                 $search_query = str_replace('+', '_AND_', $search_query);
719                 $search_query = str_replace('>', '_GT_', $search_query);
720                 $search_query = str_replace('<', '_LT_', $search_query);
721                 $search_query = str_replace('(', '_PO_', $search_query);
722                 $search_query = str_replace(')', '_PC_', $search_query);
723                 $search_query = str_replace('~', '_LOW_', $search_query);
724                 $search_query = str_replace('"', '_QUO_', $search_query);
725                 
726                 $search_query = urlencode($search_query);
727         
728                 return $search_query;
729         }
730         
731         /**
732          * Return TRUE if it contains any special caracter from an advanced search
733          * query.
734          * @param string $search_query
735          * @return boolean
736          */
737         public function is_advanced_search_query($search_query)
738         {
739                 return (preg_match('/\*|\+|\-|>|\<|\(|\)|~|"/', $search_query) == 0
740                         ? FALSE : TRUE);
741         }
742         
743         public static function gen_activation_code()
744         {
745                 $ci =& get_instance();
746                 
747                 $activation_code = substr(
748                         sha1($ci->config->item('encryption_key')
749                                 . mt_rand()),
750                         0,
751                         16);
752                 
753                 return $activation_code;
754         }
755 }
756
757 /* End of file videos_model.php */
758 /* Location: ./application/models/videos_model.php */