made a copy
[atutor.git] / mods / _standard / social / lib / classes / Application.class.php
1 <?php
2 /****************************************************************/
3 /* ATutor                                                                                                               */
4 /****************************************************************/
5 /* Copyright (c) 2002-2009                                                                              */
6 /* Adaptive Technology Resource Centre / University of Toronto  */
7 /* http://atutor.ca                                                                                             */
8 /*                                                              */
9 /* This program is free software. You can redistribute it and/or*/
10 /* modify it under the terms of the GNU General Public License  */
11 /* as published by the Free Software Foundation.                                */
12 /****************************************************************/
13 // $Id$
14
15 require_once(dirname(__FILE__) . '/Applications.class.php');
16 require_once(dirname(__FILE__) .'/../SecurityToken.php');
17 require_once(dirname(__FILE__) .'/../BlobCrypter.php');
18 require_once(dirname(__FILE__) .'/../Crypto.php');
19 require_once(dirname(__FILE__) .'/../BasicSecurityToken.php');
20 require_once(dirname(__FILE__) .'/../BasicBlobCrypter.php');
21
22 /**
23  * Object for Application, (aka Gadgets)
24  */
25 class Application extends Applications{
26         var $id;        //application id
27         var $url, $title, $height, $screenshot, $thumbnail, $author, $author_email, $description, $settings, $views;
28         var $version;
29
30         //constructor
31         function Application ($id=0){
32                 if ($id!=0){
33                         $this->id = $id;
34                         $this->getApplicationPrefs();   
35                 }
36         }
37
38         /* 
39          * Add application by URL
40          * @param       object          gadget object retrieved from JSON + cURL
41          */
42         function addApplication($gadget_obj){ 
43                 global $db, $addslashes;
44
45                 //TODO: Many more fields to add
46 //              $id                                             = $gadget_obj['moduleId'];   //after i change the URL to the key.
47                 $author                                 = $addslashes($gadget_obj->author);
48                 $author_location                = $addslashes($gadget_obj->authorLocation);
49                 $author_email                   = $addslashes($gadget_obj->authorEmail);
50                 $description                    = $addslashes($gadget_obj->description);
51                 $screenshot                             = $addslashes($gadget_obj->screenshot);
52                 $thumbnail                              = $addslashes($gadget_obj->thumbnail);
53                 $title                                  = $addslashes($gadget_obj->title);
54                 $height                                 = intval($gadget_obj->height);
55                 $module_id                              = intval($gadget_obj->module_id);
56                 $url                                    = $addslashes($gadget_obj->url);
57                 $userPrefs                              = $addslashes(serialize($gadget_obj->userPrefs));
58                 $views                                  = $addslashes(serialize($gadget_obj->views));
59                 $scrolling                              = intval(($gadget_obj->scrolling=='true'?1:0));
60
61                 //determine next id
62                 $sql = 'SELECT MAX(id) AS max_id FROM '.TABLE_PREFIX.'social_applications';
63                 $result = mysql_query($sql, $db);
64                 if ($result){
65                         $row = mysql_fetch_assoc($result);
66                         $id = $row['max_id'] + 1;
67                 } else {
68                         $id = 1;
69                 }
70                 $member_id = $_SESSION['member_id'];
71
72                 $sql = 'INSERT INTO '.TABLE_PREFIX."social_applications (id, url, title, height, scrolling, screenshot, thumbnail, author, author_email, description, settings, views, last_updated) VALUES ($id, '$url', '$title', $height, $scrolling, '$screenshot', '$thumbnail', '$author', '$author_email', '$description', '$userPrefs', '$views', NOW())";
73                 $result = mysql_query($sql, $db);
74                 
75                 //This application is already in the database, get its ID out
76                 if (!$result){                  
77                         $sql = 'SELECT id, UNIX_TIMESTAMP(last_updated) AS last_updated FROM '.TABLE_PREFIX."social_applications WHERE url='$url'";
78                         $result = mysql_query($sql, $db);
79                         $row = mysql_fetch_assoc($result);
80                         $id = $row['id'];
81
82                         //Update the gadget
83                         //TODO: Needs some sort of comparing instead of blinding updating everytime. Version(can't find any)? Date(need another field in db?)
84                         //Use TIMESTAMP for now, but i perfer version #.
85                         //If the gadget is SOCIAL_APPLICATION_UPDATE_SCHEDULE days old, update it
86                         if (abs($row['last_updated']) < strtotime('-'.SOCIAL_APPLICATION_UPDATE_SCHEDULE.' day')){
87                                 $sql = 'UPDATE '.TABLE_PREFIX."social_applications SET title='$title', height=$height, scrolling=$scrolling, screenshot='$screenshot', thumbnail='$thumbnail', author='$author', author_email='$author_email', description='$description', settings='$userPrefs', views='$views', last_updated=NOW() WHERE url='$url'";
88                                 $result = mysql_query($sql, $db);
89                                 //echo $sql;
90                         }
91                 } 
92
93                 //Add a record into application_member table for mapping
94                 $this->addMemberApplication($member_id, $id);
95                 
96                 // Post gadget information to www.atutor.ca for sharing
97                 $this->saveApplicationForShare($gadget_obj->url, $gadget_obj->title, $gadget_obj->height,
98                         $gadget_obj->screenshot, $gadget_obj->thumbnail, $gadget_obj->description,
99                         $gadget_obj->author, $gadget_obj->authorEmail);
100         }
101
102
103         /**
104          * Add this application to the member's application list
105          * @param       int             member_id
106          * @param       int             application_id
107          */
108         function addMemberApplication($member_id, $app_id){
109                 global $db;
110
111                 $member_id = intval($member_id);
112                 $app_id = intval($app_id);
113
114                 $sql = 'INSERT INTO '.TABLE_PREFIX."social_members_applications (member_id, application_id) VALUES ($member_id, $app_id)";
115                 $result = mysql_query($sql, $db);
116
117                 if ($result){
118                         //Add this to the home page
119                         $home_settings = $this->getHomeDisplaySettings();
120                         $home_settings[$app_id] = 1;    //manually set this application
121                         $this->setHomeDisplaySettings($home_settings);
122
123                         $act = new Activity();          
124                         $act->addActivity($_SESSION['member_id'], '', $app_id);
125                         unset($act);
126                 }
127         }
128
129
130         /**
131          * Parse application details
132          * @return      array of the attributes
133          *
134          */
135         function parseModulePrefs($app_url){
136                 //parse all the attributes of the <ModulePrefs> tag
137                 //and save everything in the object.
138                  $gadget = $this->fetch_gadget_metadata($app_url);
139                  return $gadget->gadgets;
140         }
141
142
143         // Restful - JSON CURL data transfer
144         private function fetch_gadget_metadata($app_url) {
145                 $request = json_encode(array(
146                         'context' => array('country' => 'US', 'language' => 'en', 'view' => 'default', 
147                                 'container' => 'atutor'), 
148                         'gadgets' => array(array('url' => $app_url, 'moduleId' => '1'))));
149                 $ch = curl_init();
150                 curl_setopt($ch, CURLOPT_URL, AT_SHINDIG_URL.'/gadgets/metadata');
151                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
152                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
153                 curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
154                 curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
155                 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
156                 curl_setopt($ch, CURLOPT_TIMEOUT, 20);
157                 curl_setopt($ch, CURLOPT_POST, 1);
158                 curl_setopt($ch, CURLOPT_POSTFIELDS, 'request=' . urlencode($request));
159                 $content = @curl_exec($ch);
160                 return json_decode($content);
161         }
162
163
164         /**
165          * Add application perferences into the table.
166          * @param       int             member id
167          * @param       string  hash's key, usually the name of the application
168          * @param       string  hash's value, contains key, value, and st.
169          * @return      true(1) if the perference has been updated, false(0) otherwise.
170          */
171         function setApplicationSettings($member_id, $key, $value){
172                 global $addslashes, $db;
173
174                 $app_id         = $this->id;
175                 $member_id      = intval($member_id);           
176                 $key            = $addslashes($key);
177                 $value          = $addslashes($value);
178
179                 $sql = 'INSERT INTO '.TABLE_PREFIX."social_application_settings (application_id, member_id, name, value) VALUES ($app_id, $member_id, '$key', '$value') ON DUPLICATE KEY UPDATE value='$value'";
180                 $result = mysql_query($sql, $db);
181
182                 //TODO: Might want to add something here to throw appropriate exceptions
183                 return $result;
184         }
185
186
187         /**
188          * Get member's applications
189          * @param       int             the member id
190          */
191         function getMemberApplications($member_id){
192                 global $db;
193                 $result = array();
194
195                 $member_id = intval($member_id);
196                 $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_members_applications WHERE member_id='.$member_id;
197                 $rs = mysql_query($sql, $db);
198                 if ($rs){
199                         while($row = mysql_fetch_assoc($rs)){
200                                 $result[] = $row['app_id'];
201                         }
202                 }
203                 return $result;
204         }
205
206
207         /**
208          * Get user perferences for this application
209          * @return      array
210          */
211         function getApplicationSettings($member_id){
212                 global $db;
213                 $result = array();
214                 $member_id = intval($member_id);
215
216                 $sql = 'SELECT * FROM '.TABLE_PREFIX."social_application_settings WHERE member_id=$member_id AND application_id=".$this->id;
217                 $rs = mysql_query($sql);
218                 if ($rs){
219                         //loop cause an application can have multiple pairs of key=>value
220                         while ($row = mysql_fetch_assoc($rs)){
221                                 $result[$row['name']] = $row['value'];
222                         }
223                 }
224                 return $result;
225         }
226
227         function getId(){
228                 return $this->id;
229         }
230
231         function getUrl(){
232                 return $this->url;
233         }
234
235         function getTitle(){
236                 return $this->title;
237         }
238
239         function getModuleId(){
240                 return intval($this->module_id);
241         }
242
243         function getHeight(){
244                 if ($this->height==0){
245                         return 600;
246                 }
247                 return $this->height;
248         }
249
250         function getScreenshot(){
251                 return $this->screenshot;
252         }
253
254         function getThumbnail(){
255                 //check if this thumbnail link is a relative link
256                 $url = parse_url($this->thumbnail);
257                 if (!isset($url['scheme']) && !isset($url['host'])){
258                         $orig_url = parse_url($this->getUrl());
259                         return $orig_url['scheme'].'://'.$orig_url['host'].$this->thumbnail;
260                 }
261                 return $this->thumbnail;
262         }
263
264         function getAuthor(){
265                 return $this->author;
266         }
267
268         function getAuthorEmail(){
269                 return $this->author_email;
270         }
271
272         function getAuthorLocation(){
273                 return $this->author_location;
274         }
275
276         function getDescription(){
277                 return $this->description;
278         }
279
280         function getScrolling(){
281                 return ($this->scrolling==1?'yes':'no');
282         }
283
284         function getSettings(){
285                 return unserialize($this->settings);
286         }
287
288         function getViews(){
289                 return unserialize($this->views);
290         }
291
292         /** 
293          * Return iframe URL based on the given parameters
294          * @param       int                     owner id
295          * @param       string          avaiable options are 'profile', 'canvas'
296          *                                              http://code.google.com/apis/orkut/docs/orkutdevguide/orkutdevguide-0.8.html#ops_mode
297          * @param       string          extra application parameters
298          * @return      iframe url
299          */
300         function getIframeUrl($oid, $view='profile', $appParams=''){
301                 //let view=profile as default option
302                 if ($view!='profile' && $view!='canvas'){
303                         $view = 'profile';
304                 }
305
306                 $app_settings = $this->getSettings();
307                 $user_settings = $this->getApplicationSettings($_SESSION['member_id']);
308
309                 //retrieve user preferences
310                 foreach ($app_settings as $key => $setting) {
311                         if (! empty($key)) {
312                           $value = isset($user_settings[$key]) ? $user_settings[$key] : (isset($setting->default) ? $setting->default : null);
313                           if (isset($user_settings[$key])) {
314                                 unset($user_settings[$key]);
315                           }
316                           //shindig doesn't like ';', it only takes '&' as of Apr 6th, 2009
317                           //$prefs .= SEP.'up_' . urlencode($key) . '=' . urlencode($value);
318                           $prefs .= '&up_' . urlencode($key) . '=' . urlencode($value);
319                         }
320                 }
321                 foreach ($user_settings as $name => $value) {
322                         // if some keys _are_ set in the db, but not in the gadget metadata, we still parse them on the url
323                         // (the above loop unsets the entries that matched  
324                         if (! empty($value) && ! isset($appParams[$name])) {
325                         //shindig doesn't like ';', it only takes '&' as of Apr 6th, 2009
326                         //$prefs .= SEP.'up_' . urlencode($name) . '=' . urlencode($value);
327                         $prefs .= '&up_' . urlencode($name) . '=' . urlencode($value);
328                         }
329                 }
330
331                 //generate security token
332                 $securityToken = BasicSecurityToken::createFromValues(($oid > 0?$oid:$_SESSION['member_id']), // owner
333                                                 $_SESSION['member_id'], // viewer
334                                                 $this->getId(), // app id
335                                                 'default', // domain key, shindig will check for php/config/<domain>.php for container specific configuration
336                                                 urlencode($this->getUrl()), // app url
337                                                 $this->getModuleId());// mod id
338 //debug($securityToken);
339                 $url = AT_SHINDIG_URL.'/gadgets/ifr?' 
340                         . "synd=default" 
341                         . SEP."container=default" 
342                         . SEP."viewer=". $_SESSION['member_id']
343                         . SEP."owner=" . $oid
344                         . SEP."aid=" . $this->getId()                   //application id
345                         . SEP."mid=" . $this->getModuleId()     //not sure what mod_id is
346                         . SEP."country=US" 
347                         . SEP."lang=en" 
348                         . SEP."view=" . $view   //canvas for this big thing, should be a variable
349                         . SEP."parent=" . urlencode("http://" . $_SERVER['HTTP_HOST']) . $prefs . (isset($appParams) ? '&view-params=' . urlencode($appParams) : '') 
350                         . SEP."st=" . urlencode(base64_encode($securityToken->toSerialForm())) 
351                         . SEP."v=" . $this->getVersion()
352                         . SEP."url=" . urlencode($this->getUrl()) . "#rpctoken=" . rand(0, getrandmax());
353                 return $url;
354         }
355
356         //TO BE IMPLEMENTED
357         function getVersion(){
358                 return '0.1';
359         }
360
361
362         /**
363          * Retrieve all information about this gadget and save it in the object
364          * @private
365          */
366         function getApplicationPrefs(){
367                 global $db;
368
369                 $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_applications WHERE id='.$this->id;
370                 $rs = mysql_query($sql);
371
372                 if ($rs){
373                         $row = mysql_fetch_assoc($rs);
374                         //assign values
375                         $this->url                      = $row['url'];
376                         $this->title            = $row['title'];
377                         $this->height           = $row['height'];
378                         $this->scrolling        = $row['scrolling'];
379                         $this->screenshot       = $row['screenshot'];
380                         $this->thumbnail        = $row['thumbnail'];
381                         $this->author           = $row['author'];
382                         $this->author_email     = $row['author_email'];
383                         $this->description      = $row['description'];
384                         $this->settings         = $row['settings'];
385                         $this->views            = $row['views'];
386                         $this->last_updated     = $row['last_updated'];
387                 }
388         }
389
390         /** 
391          * Delete an application
392          */
393         function deleteApplication(){
394                 global $db;
395
396                 //delete application mapping
397                 $sql = 'DELETE FROM '.TABLE_PREFIX.'social_members_applications WHERE application_id='.$this->id.' AND member_id='.$_SESSION['member_id'];
398                 $rs = mysql_query($sql);
399
400                 //delete application data?
401                 $sql = 'DELETE FROM '.TABLE_PREFIX.'social_application_settings WHERE application_id='.$this->id.' AND member_id='.$_SESSION['member_id'];
402                 $rs = mysql_query($sql);
403
404                 //delete application settings
405                 $home_settings = $this->getHomeDisplaySettings();
406                 if (isset($home_settings[$this->id])){                  
407                         unset($home_settings[$this->id]);
408                         $this->setHomeDisplaySettings($home_settings);
409                 }
410
411                 return $rs;
412         }
413         
414         /** 
415          * Save gadget informaiton into atutor.ca/gadget_log.php to share among ATutor users
416          */
417         function saveApplicationForShare($url, $title, $height, $screenshot, $thumbnail, $description, $author, $authorEmail){
418                 $request = "&url=".urlencode($url)."&title=".urlencode($title).
419                            "&height=".urlencode($height)."&screenshot=".urlencode($screenshot).
420                            "&thumbnail=".urlencode($thumbnail)."&desc=".urlencode($description).
421                            "&author=".urlencode($author)."&authorEmail=".urlencode($authorEmail);
422                 
423                 $header = "POST /gadget_log.php HTTP/1.1\r\n";
424                 $header .= "Host: atutor.ca\r\n";
425                 $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
426                 $header .= "Content-Length: " . strlen($request) . "\r\n\r\n";
427                 $fp = fsockopen('www.atutor.ca', 80, $errno, $errstr, 30);
428
429                 if ($fp) {
430                         fputs($fp, $header . $request . "\r\n\r\n");
431                         fclose($fp);
432                 }
433         }
434 }
435 ?>