e8fd25567d8bfc5594ae33f2881910b7d25f77d8
[atutor.git] / mods / atutor_opencaps / opencaps / include / classes / project_class.php
1 <?php
2 /*
3  * OpenCaps
4  * http://opencaps.atrc.utoronto.ca
5  * 
6  * Copyright 2009 Heidi Hazelton
7  * Adaptive Technology Resource Centre, University of Toronto
8  * 
9  * Licensed under the Educational Community License (ECL), Version 2.0. 
10  * You may not use this file except in compliance with this License.
11  * http://www.opensource.org/licenses/ecl2.php
12  * 
13  */
14
15 class project {
16         //public $owner;
17         
18         public $id;
19         public $name;
20         //public $prefs;
21
22         public $media_loc; //url to media file
23         public $media_height;
24         public $media_width;
25         public $duration;
26         
27         public $caption_loc; //url to caption json file
28         public $clip_collection;  // holds everything: captions, descriptions, etc.
29
30         public $layout;
31         
32         /* new project object belonging to member */
33         function __construct() {
34                 $this->clip_collection = new clipCollection();  
35         }
36         
37         /* create a new project */
38         function createNew($name, $media, $captions) {  
39                 global $this_db;
40                 
41                 $this->name = $name;
42                 $this->layout = 0;
43                                 
44                 //enter into db 
45                 $this->id = $this_db->addProj($this);
46                 
47                 if (isset($_SESSION['errors'])) {
48                         header("Location:start.php");
49                         exit;
50                 }
51                 
52                 $_SESSION['pid'] = $this->id;           
53                 
54                 //make project folder
55                 if (!file_exists('projects/'.$this->id.'/')) {
56                         @mkdir('projects/'.$this->id.'/');
57                         @copy('projects/index.html', 'projects/'.$this->id.'/index.html');
58                 }               
59                 
60                 // if uploaded
61                 if (is_array($media)) { 
62                         $this->media_loc = 'projects/'.$this->id.'/'.$media['name'];
63                                 
64                         if ( !move_uploaded_file($media['tmp_name'], 'projects/'.$this->id.'/'.basename($media['name'])) ) {
65                                 $_SESSION['errors'][] = "Problem uploading media file - can't copy file to server. The file may exceed file size limits. Try a smaller file or contact your server administrator.";
66                                 
67                                 $this->delete($this->id);
68                                 return;                         
69                         }
70                         
71                 // if URL       
72                 } else {
73                         $this->media_loc = $media;      
74                 }
75                                                 
76                 //convert caption file to quicktime &  save
77                 if (!empty($captions['tmp_name'])) {    
78                                                         
79                         $this->importCaptions($captions);       
80                 }
81                                         
82                 //save reference file
83                 $json = json_encode(get_object_vars($this));            
84                 $this->saveJson($json, $this->id);                              
85                 $this_db->updateProj($this);
86                 
87                 return $this->id;
88         }
89         
90         /* open user project */
91         function open($pid) {   
92                 global $this_db;        
93                 $sql = "UPDATE projects SET last_accessed=NOW() WHERE project_id=$pid AND member_id=$_SESSION[mid]";
94                 if (!$result = mysql_query($sql, $this_db->db)) {
95                         echo 'Database error: '.mysql_error();
96                         exit;   
97                 }
98                 
99                 $_SESSION['pid'] = $pid;        
100         }                       
101         
102         
103         /* save uploaded media - returns location of file */
104         function saveMedia($upload) {
105                 $dir = 'projects';
106                 if (!move_uploaded_file($file['tmp_name'], $dir.'/'.basename($file['name'])) ) {
107                         //$err = "Problem uploading file - can't copy file to server. The file may exceed file size limits. Try a smaller file or contact your server administrator.";
108                 }
109         }
110         
111         /* list the current user's projects */
112         function printUserProjects($pageNum) {
113                 global $this_db, $stripslashes, $addslashes;
114                 
115                 if (!isset($pageNum))
116                         $pageNum = 1;
117                                 
118                 $projsPerPage = 20;
119                         
120                 //printing page numbers
121                 $sql  = "SELECT project_id FROM projects WHERE member_id=".intval($_SESSION['mid']);
122                 $result  = @mysql_query($sql, $this_db->db);
123                 $numrows = @mysql_num_rows($result);
124                         
125                 $maxPage = ceil($numrows/$projsPerPage);
126                         
127                         $nav  = 'Page: ';               
128                         for($page = 1; $page <= $maxPage; $page++) {
129                            if ($page == $pageNum) {
130                               $nav .= " $page "; 
131                            } else {
132                               $nav .= ' <a href="start.php?page='.$page.'">'.$page.'</a> ';
133                            }
134                         }               
135                         
136                         if ($maxPage > 1)
137                                 echo $nav."<br /><br />";
138                         
139                         $offset = ($pageNum - 1) * $projsPerPage;
140                         $sql = "SELECT * FROM projects WHERE member_id=".intval($_SESSION['mid'])." ORDER BY last_accessed DESC LIMIT $offset, $projsPerPage";
141                         $result = @mysql_query($sql, $this_db->db);             
142                         
143                 
144                 if ($numrows == 0) {
145                         echo "No projects yet.";
146                 } else {
147                         echo '<ul class="proj-list">';                  
148                         while ($row = @mysql_fetch_assoc($result)) {                                    
149                                 echo '<li><label><input type="radio" name="proj" value='.$row['project_id'].' /> '.$stripslashes($row['name']).'</label> (<a href="#" onClick="confirmDelete('.$row['project_id'].', \''.$addslashes($row['name']).'\');">Delete</a>)</li>';
150                         }
151                         echo '</ul>';   
152                         echo "<div style='text-align:right;'><input type='submit' class='button' style='width:6em;margin-top:5px;' name='submit_new' value='Submit' /></div>";          
153                         
154                 }                       
155         }
156         
157         function saveJson($json, $pid) {
158                 global $stripslashes;\r
159                                 
160                 $json_path = INCLUDE_PATH.'../projects/'.$pid.'/';
161                         
162                 if (!file_exists($json_path))
163                         mkdir($json_path);\r
164                         \r
165                 // addede by ANTO\r
166                 ///////////////////////////////////////////\r
167                 if (get_magic_quotes_gpc()) \r
168                 {\r
169                         $json = stripslashes($json);\r
170                 \r
171                 }\r
172                 // second test using regexp\r
173                 $validJsonRegExp = '/"clips":\[/'; // can be better tho\r
174                 if (!preg_match($validJsonRegExp, $validJsonRegExp))\r
175                 {\r
176                         $json = str_replace('\"','"',$json);\r
177                 }\r
178                 //end added by ANTO\r
179                 ///////////////////////////////////////////\r
180                 
181 \r
182                 if (!@file_put_contents($json_path.'opencaps.json', $stripslashes($json))) {
183                         echo 'Could not create project file.';
184                 }       \r
185         }
186         
187         function importCaptions($capfile, $upload=true) {               
188                 global $page, $remote_systems;
189                 \r
190                 // added by anto\r
191                 if (OC_DEBUG_MODE_ON)\r
192                 {\r
193                         $ocAtDebugMsg = '*************************';\r
194                         $ocAtDebugMsg .= '<br/>';\r
195                         $ocAtDebugMsg .= '<b>importCaptions() - class: project</b>';\r
196                         $ocAtDebugMsg .= '<br/>';\r
197                         $ocAtDebugMsg .= '<br/>Session ID: '.$_SESSION['pid'];\r
198                         $ocAtDebugMsg .= '<br/>$this->id: '.$this->id;\r
199                         $ocAtDebugMsg .= '<br/><br/>';\r
200                         $ocAtDebugMsg .= '*************************';\r
201                         ///echo $ocAtDebugMsg;\r
202                         $_SESSION['feedback'][] = $ocAtDebugMsg;\r
203                 }\r
204                 
205                 $page = explode('/',$_SERVER["SCRIPT_NAME"]); 
206                 $page = end($page);
207                 
208                 $page_len = strlen($page)+1;
209                 
210                 $ccollection = new clipCollection() ;
211                 
212                 //save
213                 if ($upload) {
214                         if( !move_uploaded_file( $capfile['tmp_name'], INCLUDE_PATH.'../projects/'.$this->id.'/'.basename($capfile['name'])) ) {
215                                 $_SESSION['errors'][] = "Problem uploading caption file - can't copy file to server.";                  
216                                 $this->delete($this->id);
217                                 return;
218                         }
219                         
220                         $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -$page_len);                                   
221                         $caption_file = urlencode('../projects/'.$this->id.'/'.basename($capfile['name']));                                             
222                         
223                 } else {                        
224                         /* system - matterhorn */
225                         $page_len += strlen("include/");
226                         $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -$page_len);                                   
227                         
228                         $uri = substr($capfile, strlen($remote_systems[$_SESSION['rid']]['url']));
229                         $caps = matterhornAuth($_SESSION['rid'], $uri);
230                         $caption_file = INCLUDE_PATH.'../projects/'.$this->id.'/'.'captions.xml';
231                         @file_put_contents($caption_file, $caps);                       
232                 }
233                                         
234                 $convert_url = $base_url.'/conversion_service/?cc_url='.$caption_file.'&cc_result=0&cc_target=JSONcc&cc_name=noname.___';                                       
235                 $json_captions = json_decode(@file_get_contents($convert_url)); 
236                                 
237                 if (!empty($json_captions) && $json_captions != "The format of source Caption was not recognized.") {                   
238                         
239                         foreach ($json_captions->captionCollection as $clip) {                          
240                                 $this_clip = new clip($clip->inTime, $clip->outTime, trim($clip->caption));
241                                 $ccollection->addClip($this_clip);
242                         }       
243
244                         $_SESSION['feedback'][] = "Captions imported successfully.";\r
245                         $_SESSION['feedback'][] = "id: ".$this->id;
246                                                                                 
247                 } else  {
248                         $_SESSION['errors'][] = "Problem uploading caption file - the format is incorrect, or unsupported.";
249                 }               
250                 
251                 $this->clip_collection = $ccollection;
252                         
253                 //save reference file
254                 $json = json_encode(get_object_vars($this));            
255                 \r
256                 \r
257                 // changed by ANTO\r
258                 $this->saveJson($json, $_SESSION['pid']);               
259
260                 return;
261
262         }               
263         
264         
265         function exportCaption($format) {
266
267                 if ($format == "all") {
268                                 $this->export_pkg();                            
269                                                 
270                 } else if ($format == "json") {
271                                 $cappath = INCLUDE_PATH.'../projects/'.$this->id.'/'.'opencaps.json';
272                                 //make a copy of the json that has the proj name as prefix
273                                 
274                                                 
275                 } else {
276                         $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -10);          
277                         
278                         $convert_url = $base_url.'conversion_service/?cc_url='.urlencode('../projects/'.$this->id.'/opencaps.json').'&cc_result=0&cc_target='.$format.'&cc_name=noname.___';    
279                         $formatted_captions = @file_get_contents($convert_url);
280                         if (!empty($formatted_captions)) {
281                                 $formatted_captions = trim($formatted_captions);                                
282                                 $cappath = INCLUDE_PATH.'../projects/'.$this->id.'/'.str_replace(' ', '_', $this->name).'_';
283                         
284                                 switch($format) {
285                                         case "DFXP":
286                                                 $cappath = $cappath.'captions.dfxp.xml';
287                                                 break;
288         
289                                         case "DvdStl":
290                                                 $cappath = $cappath.'captions.stl';
291                                                 break;                                  
292                                                 
293                                         case "MicroDvd":
294                                                 $cappath = $cappath.'captions.sub';
295                                                 break;
296                                                 
297                                         case "MPlayer":
298                                                 $cappath = $cappath.'captions.MPsub';
299                                                 break;
300                                                 
301                                         case "QTtext":                                          
302                                                 $formatted_captions = $formatted_captions."\r\n".'['.$this->duration.']'; /* white cap background hack */                                               
303                                                 $cappath = $cappath.'captions.txt';
304                                                 break;                                  
305         
306                                         case "RealText":
307                                                 $cappath = $cappath.'captions.rt';
308                                                 break;  
309                                                                                         
310                                         case "Sami":
311                                                 $cappath = $cappath.'capscribe.smi';
312                                                 break;
313         
314                                         case "SubRipSrt":
315                                                 $cappath = $cappath.'captions.srt';
316                                                 break;
317                                                 
318                                         case "Scc":
319                                                 $cappath = $cappath.'captions.scc';
320                                                 break;          
321         
322                                         case "SubViewer":
323                                                 $cappath = $cappath.'captions.sub';
324                                                 break;                                          
325                                 }
326         
327                                 @file_put_contents($cappath, $formatted_captions);
328                         }
329                 }
330                 export_file($cappath);  
331                 exit;           
332         }
333         
334         function delete($proj_id) {
335                 global $this_db;
336                                 
337                 if (deleteDir('../projects/'.$proj_id."/")) {                           
338                         $sql = "DELETE from projects WHERE project_id=".$proj_id." AND member_id=".$_SESSION['mid'];
339                         $result = mysql_query($sql, $this_db->db);                      
340                 } else {
341                         //echo "Project could not be deleted.";
342                 }
343         }
344
345         function preview($layout) {     
346                 $this->layout = $layout;
347                 
348                 //send this to the conversion service
349                 $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -20);          
350                 $json_url = urlencode($base_url.'projects/'.$this->id.'/opencaps.json');
351                 $request = $base_url."conversion_service/?cc_url=".$json_url."&cc_result=0&cc_target=QTtext&cc_name=noname.___";
352                         
353                 //create the qt-text file
354                 $qt_text = @file_get_contents($request)."\r\n".'['.$this->duration.']'; 
355                 @file_put_contents('../projects/'.$this->id.'/captions.txt', $qt_text);
356
357                 //send the embed height back as a response
358                 $eheight = $this->get_smil('save');
359                 if ($eheight >= 100)
360                         echo $eheight;
361                 else 
362                         echo '100';
363         }
364         
365
366         function get_smil($method="") {
367                 $layout = $this->layout; 
368                                                 
369                 $contents = @file_get_contents(INCLUDE_PATH.'../projects/layouts/smil_'.$layout.'.mov');
370                 $contents = str_replace("%rootwidth%", $this->media_width, $contents);
371                 
372                 $vid_file_name = end(explode('/',$this->media_loc));
373         
374                 if ($this->media_loc == 'projects/'.$this->id.'/'.$vid_file_name)
375                         $contents = str_replace("%video%", $vid_file_name, $contents);
376                 else
377                         $contents = str_replace("%video%", $this->media_loc, $contents);
378                         
379                 $contents = str_replace("%duration%", $this->duration, $contents);
380                 $contents = str_replace("%width%", $this->media_width, $contents);
381                 $contents = str_replace("%height%", $this->media_height, $contents);
382                 
383                 $contents = str_replace("%capwidth%", $this->media_width-10, $contents);
384                 
385                 if ($layout == 0) { //cap below
386                         $contents = str_replace("%rootheight%", $this->media_height+85, $contents);
387                         $obj_height = $this->media_height+100;
388                         $contents = str_replace("%captop%", $this->media_height+10, $contents);
389                         $contents = str_replace("%capheight%", 135, $contents);  //affects font size
390                         
391                 } else if ($layout == 1) { //cap bottom
392                         $contents = str_replace("%rootheight%", $this->media_height, $contents);
393                         $obj_height = $this->media_height+30;
394                         $contents = str_replace("%captop%", $this->media_height-75, $contents);
395                         $contents = str_replace("%capheight%", 135, $contents);
396                         
397                 } else { //caption only
398                         $contents = str_replace("%rootheight%", 85, $contents);
399                         $obj_height = 155;
400                         $contents = str_replace("%captop%", 10, $contents);
401                         $contents = str_replace("%capheight%", 135, $contents);
402                 }
403
404                 if ($method == "save") {
405                         $proj_smil = INCLUDE_PATH.'../projects/'.$this->id.'/smil_'.$layout.'.mov';
406                         @file_put_contents($proj_smil, $contents);
407                         return $obj_height;     
408                 } else {
409                         return $contents;
410                 }
411         }       
412         
413         function export_pkg() {                                         
414                 //create zipfile
415                 $zip = new ZipArchive();
416                 
417                 $proj_name = str_replace(' ', '', $this->name);
418                 $proj_name = str_replace("'", '', $proj_name);  
419                 $zipfile = $proj_name.".zip";
420                 if ($zip->open(INCLUDE_PATH.'../projects/'.$this->id.'/'.$zipfile, ZIPARCHIVE::CREATE)!==TRUE) {
421                         exit("cannot open <$zipfile>\n");
422                 }
423                 
424                 $zip->addEmptyDir($proj_name);
425                 
426                 //add smil
427                 $contents = $this->get_smil();          
428                 $zip->addFromString($proj_name.'/smil.mov', $contents);
429         
430                 //create player from template   
431                 $contents = file_get_contents(INCLUDE_PATH.'../projects/player_template.php');
432                 $contents = str_replace("%width%", $this->media_width, $contents);
433                 $contents = str_replace("%height%", $this->media_height+135, $contents);                
434                         
435                 //add player
436                 $zip->addFromString($proj_name.'/player.html', $contents);
437                                 
438                 //add captions          
439                 $zip->addFile(INCLUDE_PATH.'../projects/'.$this->id.'/captions.txt', $proj_name.'/captions.txt');
440                 
441                 //add movie if not a URL
442                 if (current(explode('/', $this->media_loc)) == "projects") {
443                         $media_name = end(explode('/', $this->media_loc));
444                         $zip->addFile($this->media_loc, $proj_name.'/'.$media_name);
445                 }
446                                 
447                 $zip->close();          
448                 //export_file(INCLUDE_PATH.'../projects/'.$this->id.'/'.$zipfile);
449                 unlink(INCLUDE_PATH.'../projects/'.$this->id.'/'.$zipfile);
450                 exit;           
451         }       
452         
453         function editName($name) {
454                 global $addslashes, $this_db;
455                                 
456                 $this->name = $addslashes($name);
457                 
458                 //save reference file
459                 $json = json_encode(get_object_vars($this));            
460                 $this->saveJson($json, $this->id);                              
461                 $this_db->updateProj($this);            
462         }
463         
464 }       
465
466
467 /* utility functions */
468
469 /* force download of a file in browser */
470 function export_file($exfile) {
471         if (file_exists($exfile)) {
472                 header('Content-Description: File Transfer');
473                 header('Content-Type: application/octet-stream');
474                 header('Content-Disposition: attachment; filename='.basename($exfile));
475                 header('Content-Transfer-Encoding: binary');
476                 header('Expires: 0');
477                 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
478                 header('Pragma: public');
479                 header('Content-Length: '.filesize($exfile));
480                 ob_clean();
481                 flush();
482                 readfile($exfile);
483         }
484 }
485
486 /* delete a directory and its contents */
487 function deleteDir($dir) {
488         $dh = @opendir($dir);
489         while ( $file = @readdir($dh) ) {
490                 if ( $file != '.' || $file != '..') {
491                         @unlink($dir.$file);
492                         //if ( ! @unlink ( $dir . '/' . $obj ) ) deleteDir ( $dir . '/' . $obj, true )
493                 }
494         }
495         @closedir ($dh);
496         if (@rmdir($dir))
497                 return true;
498         else
499                 return false;
500 }
501
502
503 ?>