Dotclear

source: inc/core/class.dc.media.php @ 3167:9b0e5988c0eb

Revision 3167:9b0e5988c0eb, 36.0 KB checked in by franck <carnet.franck.paul@…>, 10 years ago (diff)

Cope with sort of "un-attached" media → allows new features as "featured media" plugin. Video and Audio HTML5 element are now used (if possible) rather than Flash object for attachments.

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14/**
15@ingroup DC_CORE
16@brief Dotclear media manage
17
18This class handles Dotclear media items.
19*/
20class dcMedia extends filemanager
21{
22     protected $core;         ///< <b>dcCore</b> dcCore instance
23     protected $con;          ///< <b>connection</b> Database connection
24     protected $table;        ///< <b>string</b> Media table name
25     protected $type;         ///< <b>string</b> Media type filter
26     protected $postmedia;
27     protected $file_sort = 'name-asc';
28
29     protected $file_handler = array(); ///< <b>array</b> Array of callbacks
30
31     public $thumb_tp = '%s/.%s_%s.jpg';     ///< <b>string</b> Thumbnail file pattern
32     public $thumb_tp_alpha = '%s/.%s_%s.png'; ///< <b>string</b> Thumbnail file pattern (with alpha layer)
33
34     /**
35     <b>array</b> Tubmnail sizes:
36     - m: medium image
37     - s: small image
38     - t: thumbnail image
39     - sq: square image
40     */
41     public $thumb_sizes = array(
42          'm' => array(448,'ratio','medium'),
43          's' => array(240,'ratio','small'),
44          't' => array(100,'ratio','thumbnail'),
45          'sq' => array(48,'crop','square')
46     );
47
48     public $icon_img = 'images/media/%s.png';    ///< <b>string</b> Icon file pattern
49
50     /**
51     Object constructor.
52
53     @param    core      <b>dcCore</b>       dcCore instance
54     @param    type      <b>string</b>       Media type filter
55     */
56     public function __construct($core,$type='')
57     {
58          $this->core =& $core;
59          $this->con =& $core->con;
60          $this->postmedia = new dcPostMedia($core);
61
62          if ($this->core->blog == null) {
63               throw new Exception(__('No blog defined.'));
64          }
65
66          $this->table = $this->core->prefix.'media';
67          $root = $this->core->blog->public_path;
68
69          if (preg_match('#^http(s)?://#',$this->core->blog->settings->system->public_url)) {
70               $root_url = rawurldecode($this->core->blog->settings->system->public_url);
71          } else {
72               $root_url = rawurldecode($this->core->blog->host.path::clean($this->core->blog->settings->system->public_url));
73          }
74
75          if (!is_dir($root)) {
76               # Check public directory
77               if ( $core->auth->isSuperAdmin() ) {
78                    throw new Exception(__("There is no writable directory /public/ at the location set in about:config \"public_path\". You must create this directory with sufficient rights (or change this setting)."));
79               } else {
80                    throw new Exception(__("There is no writable root directory for the media manager. You should contact your administrator."));
81               }
82          }
83
84          $this->type = $type;
85
86          parent::__construct($root,$root_url);
87          $this->chdir('');
88
89          $this->path = $this->core->blog->settings->system->public_path;
90
91          $this->addExclusion(DC_RC_PATH);
92          $this->addExclusion(dirname(__FILE__).'/../');
93
94          $this->exclude_pattern = $core->blog->settings->system->media_exclusion;
95
96          # Event handlers
97          $this->addFileHandler('image/jpeg','create',array($this,'imageThumbCreate'));
98          $this->addFileHandler('image/png','create',array($this,'imageThumbCreate'));
99          $this->addFileHandler('image/gif','create',array($this,'imageThumbCreate'));
100
101          $this->addFileHandler('image/png','update',array($this,'imageThumbUpdate'));
102          $this->addFileHandler('image/jpeg','update',array($this,'imageThumbUpdate'));
103          $this->addFileHandler('image/gif','update',array($this,'imageThumbUpdate'));
104
105          $this->addFileHandler('image/png','remove',array($this,'imageThumbRemove'));
106          $this->addFileHandler('image/jpeg','remove',array($this,'imageThumbRemove'));
107          $this->addFileHandler('image/gif','remove',array($this,'imageThumbRemove'));
108
109          $this->addFileHandler('image/jpeg','create',array($this,'imageMetaCreate'));
110
111          $this->addFileHandler('image/jpeg','recreate',array($this,'imageThumbCreate'));
112          $this->addFileHandler('image/png','recreate',array($this,'imageThumbCreate'));
113          $this->addFileHandler('image/gif','recreate',array($this,'imageThumbCreate'));
114
115          $this->addFileHandler('image/jpeg','recreate',array($this,'imageThumbCreate'));
116          $this->addFileHandler('image/png','recreate',array($this,'imageThumbCreate'));
117          $this->addFileHandler('image/gif','recreate',array($this,'imageThumbCreate'));
118
119          # Thumbnails sizes
120          $this->thumb_sizes['m'][0] = abs($core->blog->settings->system->media_img_m_size);
121          $this->thumb_sizes['s'][0] = abs($core->blog->settings->system->media_img_s_size);
122          $this->thumb_sizes['t'][0] = abs($core->blog->settings->system->media_img_t_size);
123
124          # Thumbnails sizes names
125          $this->thumb_sizes['m'][2] = __($this->thumb_sizes['m'][2]);
126          $this->thumb_sizes['s'][2] = __($this->thumb_sizes['s'][2]);
127          $this->thumb_sizes['t'][2] = __($this->thumb_sizes['t'][2]);
128          $this->thumb_sizes['sq'][2] = __($this->thumb_sizes['sq'][2]);
129
130          # --BEHAVIOR-- coreMediaConstruct
131          $this->core->callBehavior('coreMediaConstruct',$this);
132     }
133
134     /**
135     Changes working directory.
136
137     @param    dir       <b>string</b>       Directory name.
138     */
139     public function chdir($dir)
140     {
141          parent::chdir($dir);
142          $this->relpwd = preg_replace('/^'.preg_quote($this->root,'/').'\/?/','',$this->pwd);
143     }
144
145     /**
146     Adds a new file handler for a given media type and event.
147
148     Available events are:
149     - create: file creation
150     - update: file update
151     - remove: file deletion
152
153     @param    type      <b>string</b>       Media type
154     @param    event     <b>string</b>       Event
155     @param    function  <b>callback</b>
156     */
157     public function addFileHandler($type,$event,$function)
158     {
159          if (is_callable($function)) {
160               $this->file_handler[$type][$event][] = $function;
161          }
162     }
163
164     protected function callFileHandler($type,$event)
165     {
166          if (!empty($this->file_handler[$type][$event]))
167          {
168               $args = func_get_args();
169               array_shift($args);
170               array_shift($args);
171
172               foreach ($this->file_handler[$type][$event] as $f)
173               {
174                    call_user_func_array($f,$args);
175               }
176          }
177     }
178
179     /**
180     Returns HTML breadCrumb for media manager navigation.
181
182     @param    href      <b>string</b>       URL pattern
183     @param    last      <b>string</b>       Last item pattern
184     @return   <b>string</b> HTML code
185     */
186     public function breadCrumb($href,$last='')
187     {
188          $res = '';
189          if ($this->relpwd && $this->relpwd != '.') {
190               $pwd = '';
191               $arr = explode('/',$this->relpwd);
192               $count = count($arr);
193               foreach ($arr as $v) {
194                    if (($last != '') && (0 === --$count)) {
195                         $res .= sprintf($last,$v);
196                    } else {
197                         $pwd .= rawurlencode($v).'/';
198                         $res .= '<a href="'.sprintf($href,$pwd).'">'.$v.'</a> / ';
199                    }
200               }
201          }
202          return $res;
203
204     }
205
206     protected function fileRecord($rs)
207     {
208          if ($rs->isEmpty()) { return null; }
209
210          if (!$this->isFileExclude($this->root.'/'.$rs->media_file) && is_file($this->root.'/'.$rs->media_file))
211          {
212               $f = new fileItem($this->root.'/'.$rs->media_file,$this->root,$this->root_url);
213
214               if ($this->type && $f->type_prefix != $this->type) {
215                    return null;
216               }
217
218               $meta = @simplexml_load_string($rs->media_meta);
219
220               $f->editable = true;
221               $f->media_id = $rs->media_id;
222               $f->media_title = $rs->media_title;
223               $f->media_meta =  $meta instanceof SimpleXMLElement ? $meta : simplexml_load_string('<meta></meta>');
224               $f->media_user = $rs->user_id;
225               $f->media_priv = (boolean) $rs->media_private;
226               $f->media_dt = strtotime($rs->media_dt);
227               $f->media_dtstr = dt::str('%Y-%m-%d %H:%M',$f->media_dt);
228
229               $f->media_image = false;
230
231               if (!$this->core->auth->check('media_admin',$this->core->blog->id)
232               && $this->core->auth->userID() != $f->media_user) {
233                    $f->del = false;
234                    $f->editable = false;
235               }
236
237               $type_prefix = explode('/',$f->type);
238               $type_prefix = $type_prefix[0];
239
240               switch ($type_prefix) {
241                    case 'image':
242                         $f->media_image = true;
243                         $f->media_icon = 'image';
244                         break;
245                    case 'audio':
246                         $f->media_icon = 'audio';
247                         break;
248                    case 'text':
249                         $f->media_icon = 'text';
250                         break;
251                    case 'video':
252                         $f->media_icon = 'video';
253                         break;
254                    default:
255                         $f->media_icon = 'blank';
256               }
257               switch ($f->type) {
258                    case 'application/msword':
259                    case 'application/vnd.oasis.opendocument.text':
260                    case 'application/vnd.sun.xml.writer':
261                    case 'application/pdf':
262                    case 'application/postscript':
263                         $f->media_icon = 'document';
264                         break;
265                    case 'application/msexcel':
266                    case 'application/vnd.oasis.opendocument.spreadsheet':
267                    case 'application/vnd.sun.xml.calc':
268                         $f->media_icon = 'spreadsheet';
269                         break;
270                    case 'application/mspowerpoint':
271                    case 'application/vnd.oasis.opendocument.presentation':
272                    case 'application/vnd.sun.xml.impress':
273                         $f->media_icon = 'presentation';
274                         break;
275                    case 'application/x-debian-package':
276                    case 'application/x-bzip':
277                    case 'application/x-gzip':
278                    case 'application/x-java-archive':
279                    case 'application/rar':
280                    case 'application/x-redhat-package-manager':
281                    case 'application/x-tar':
282                    case 'application/x-gtar':
283                    case 'application/zip':
284                         $f->media_icon = 'package';
285                         break;
286                    case 'application/octet-stream':
287                         $f->media_icon = 'executable';
288                         break;
289                    case 'application/x-shockwave-flash':
290                         $f->media_icon = 'video';
291                         break;
292                    case 'application/ogg':
293                         $f->media_icon = 'audio';
294                         break;
295                    case 'text/html':
296                         $f->media_icon = 'html';
297                         break;
298               }
299
300               $f->media_type = $f->media_icon;
301               $f->media_icon = sprintf($this->icon_img,$f->media_icon);
302
303               # Thumbnails
304               $f->media_thumb = array();
305               $p = path::info($f->relname);
306
307               $alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
308
309               $thumb = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$this->root.'/'.$p['dirname'],$p['base'],'%s');
310               $thumb_url = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$this->root_url.$p['dirname'],$p['base'],'%s');
311
312               # Cleaner URLs
313               $thumb_url = preg_replace('#\./#','/',$thumb_url);
314               $thumb_url = preg_replace('#(?<!:)/+#','/',$thumb_url);
315
316               if ($alpha) {
317                    $thumb_alt = sprintf($this->thumb_tp,$this->root.'/'.$p['dirname'],$p['base'],'%s');
318                    $thumb_url_alt = sprintf($this->thumb_tp,$this->root_url.$p['dirname'],$p['base'],'%s');
319                    # Cleaner URLs
320                    $thumb_url_alt = preg_replace('#\./#','/',$thumb_url_alt);
321                    $thumb_url_alt = preg_replace('#(?<!:)/+#','/',$thumb_url_alt);
322               }
323
324               foreach ($this->thumb_sizes as $suffix => $s) {
325                    if (file_exists(sprintf($thumb,$suffix))) {
326                         $f->media_thumb[$suffix] = sprintf($thumb_url,$suffix);
327                    } elseif ($alpha && file_exists(sprintf($thumb_alt,$suffix))) {
328                         $f->media_thumb[$suffix] = sprintf($thumb_url_alt,$suffix);
329                    }
330               }
331
332               if (isset($f->media_thumb['sq']) && $f->media_type == 'image') {
333                    $f->media_icon = $f->media_thumb['sq'];
334               }
335
336               return $f;
337          }
338
339          return null;
340     }
341
342
343     public function setFileSort($type='name')
344     {
345          if (in_array($type,array('name-asc','name-desc','date-asc','date-desc'))) {
346               $this->file_sort = $type;
347          }
348     }
349
350     protected function sortFileHandler($a,$b)
351     {
352          switch ($this->file_sort)
353          {
354               case 'date-asc':
355                    if ($a->media_dt == $b->media_dt) {
356                         return 0;
357                    }
358                    return ($a->media_dt < $b->media_dt) ? -1 : 1;
359               case 'date-desc':
360                    if ($a->media_dt == $b->media_dt) {
361                         return 0;
362                    }
363                    return ($a->media_dt > $b->media_dt) ? -1 : 1;
364               case 'name-desc':
365                    return strcasecmp($b->basename,$a->basename);
366               case 'name-asc':
367               default:
368                    return strcasecmp($a->basename,$b->basename);
369          }
370     }
371
372     /**
373     Gets current working directory content (using filesystem)
374
375     */
376     public function getFSDir()
377     {
378          parent::getDir();
379     }
380
381     /**
382     Gets current working directory content.
383
384     @param    type      <b>string</b>       Media type filter
385     */
386     public function getDir($type=null)
387     {
388          if ($type) {
389               $this->type = $type;
390          }
391
392          $media_dir = $this->relpwd ? $this->relpwd : '.';
393
394          $strReq =
395          'SELECT media_file, media_id, media_path, media_title, media_meta, media_dt, '.
396          'media_creadt, media_upddt, media_private, user_id '.
397          'FROM '.$this->table.' '.
398          "WHERE media_path = '".$this->path."' ".
399          "AND media_dir = '".$this->con->escape($media_dir)."' ";
400
401          if (!$this->core->auth->check('media_admin',$this->core->blog->id))
402          {
403               $strReq .= 'AND (media_private <> 1 ';
404
405               if ($this->core->auth->userID()) {
406                    $strReq .= "OR user_id = '".$this->con->escape($this->core->auth->userID())."'";
407               }
408               $strReq .= ') ';
409          }
410
411          $rs = $this->con->select($strReq);
412
413          parent::getDir();
414
415          $f_res = array();
416          $p_dir = $this->dir;
417
418          # If type is set, remove items from p_dir
419          if ($this->type)
420          {
421               foreach ($p_dir['files'] as $k => $f) {
422                    if ($f->type_prefix != $this->type) {
423                         unset($p_dir['files'][$k]);
424                    }
425               }
426          }
427
428          $f_reg = array();
429
430          while ($rs->fetch())
431          {
432               # File in subdirectory, forget about it!
433               if (dirname($rs->media_file) != '.' && dirname($rs->media_file) != $this->relpwd) {
434                    continue;
435               }
436
437               if ($this->inFiles($rs->media_file))
438               {
439                    $f = $this->fileRecord($rs);
440                    if ($f !== null) {
441                         if (isset($f_reg[$rs->media_file]))
442                         {
443                              # That media is duplicated in the database,
444                              # time to do a bit of house cleaning.
445                              $this->con->execute(
446                                   'DELETE FROM '.$this->table.' '.
447                                   "WHERE media_id = ".$this->fileRecord($rs)->media_id
448                              );
449                         } else {
450                              $f_res[] = $this->fileRecord($rs);
451                              $f_reg[$rs->media_file] = 1;
452                         }
453                    }
454               }
455               elseif (!empty($p_dir['files']) && $this->relpwd == '')
456               {
457                    # Physical file does not exist remove it from DB
458                    # Because we don't want to erase everything on
459                    # dotclear upgrade, do it only if there are files
460                    # in directory and directory is root
461                    $this->con->execute(
462                         'DELETE FROM '.$this->table.' '.
463                         "WHERE media_path = '".$this->con->escape($this->path)."' ".
464                         "AND media_file = '".$this->con->escape($rs->media_file)."' "
465                    );
466                    $this->callFileHandler(files::getMimeType($rs->media_file),'remove',$this->pwd.'/'.$rs->media_file);
467               }
468          }
469
470          $this->dir['files'] = $f_res;
471          foreach ($this->dir['dirs'] as $k => $v) {
472               $v->media_icon = sprintf($this->icon_img,($v->parent ? 'folder-up' : 'folder'));
473          }
474
475          # Check files that don't exist in database and create them
476          if ($this->core->auth->check('media,media_admin',$this->core->blog->id))
477          {
478               foreach ($p_dir['files'] as $f)
479               {
480                    if (!isset($f_reg[$f->relname])) {
481                         if (($id = $this->createFile($f->basename,null,false,null,false)) !== false) {
482                              $this->dir['files'][] = $this->getFile($id);
483                         }
484                    }
485               }
486          }
487          usort($this->dir['files'],array($this,'sortFileHandler'));
488     }
489
490     /**
491     Gets file by its id. Returns a filteItem object.
492
493     @param    id        <b>integer</b>      File ID
494     @return   <b>fileItem</b>
495     */
496     public function getFile($id)
497     {
498          $strReq =
499          'SELECT media_id, media_path, media_title, '.
500          'media_file, media_meta, media_dt, media_creadt, '.
501          'media_upddt, media_private, user_id '.
502          'FROM '.$this->table.' '.
503          "WHERE media_path = '".$this->path."' ".
504          'AND media_id = '.(integer) $id.' ';
505
506          if (!$this->core->auth->check('media_admin',$this->core->blog->id))
507          {
508               $strReq .= 'AND (media_private <> 1 ';
509
510               if ($this->core->auth->userID()) {
511                    $strReq .= "OR user_id = '".$this->con->escape($this->core->auth->userID())."'";
512               }
513               $strReq .= ') ';
514          }
515
516          $rs = $this->con->select($strReq);
517          return $this->fileRecord($rs);
518     }
519
520     /**
521     Search into media db (only).
522
523     @param    query          <b>string</b>       Search query
524     @return boolean     true or false if nothing found
525     */
526     public function searchMedia($query)
527     {
528          if ($query == '') {
529               return false;
530          }
531
532          $strReq =
533          'SELECT media_file, media_id, media_path, media_title, media_meta, media_dt, '.
534          'media_creadt, media_upddt, media_private, user_id '.
535          'FROM '.$this->table.' '.
536          "WHERE media_path = '".$this->path."' ".
537          "AND (media_title LIKE '%".$this->con->escape($query)."%' ".
538          "    OR media_file LIKE '%".$this->con->escape($query)."%' ".
539          "    OR media_meta LIKE '<Description>%".$this->con->escape($query)."%</Description>')";
540
541          if (!$this->core->auth->check('media_admin',$this->core->blog->id))
542          {
543               $strReq .= 'AND (media_private <> 1 ';
544
545               if ($this->core->auth->userID()) {
546                    $strReq .= "OR user_id = '".$this->con->escape($this->core->auth->userID())."'";
547               }
548               $strReq .= ') ';
549          }
550
551          $rs = $this->con->select($strReq);
552
553          $this->dir = array('dirs' => array(),'files' => array());
554          $f_res = array();
555          while ($rs->fetch())
556          {
557               $fr = $this->fileRecord($rs);
558               if ($fr) {
559                    $f_res[] = $fr;
560               }
561          }
562          $this->dir['files'] = $f_res;
563
564          try {
565               usort($this->dir['files'],array($this,'sortFileHandler'));
566          } catch (Exception $e) {}
567
568          return (count($f_res) > 0 ? true : false);
569     }
570
571     /**
572     Returns media items attached to a blog post. Result is an array containing
573     fileItems objects.
574
575     @param    post_id        <b>integer</b>      Post ID
576     @param    media_id  <b>integer</b>      Optionnal media ID
577     @param    link_type <b>string</b>       Optionnal link type
578     @return   <b>array</b> Array of fileItems
579     */
580     public function getPostMedia($post_id,$media_id=null,$link_type=null)
581     {
582          $params = array(
583               'post_id' => $post_id,
584               'media_path' => $this->path
585          );
586          if ($media_id) {
587               $params['media_id'] = (integer) $media_id;
588          }
589          if ($link_type) {
590               $params['link_type'] = $link_type;
591          }
592          $rs = $this->postmedia->getPostMedia($params);
593
594          $res = array();
595
596          while ($rs->fetch()) {
597               $f = $this->fileRecord($rs);
598               if ($f !== null) {
599                    $res[] = $f;
600               }
601          }
602
603          return $res;
604     }
605
606     /**
607     @deprecated since version 2.4
608     @see dcPostMedia::addPostMedia
609     */
610     public function addPostMedia($post_id,$media_id,$link_type='attachment')
611     {
612          $this->postmedia->addPostMedia($post_id,$media_id,$link_type);
613     }
614
615     /**
616     @deprecated since version 2.4
617     @see dcPostMedia::removePostMedia
618     */
619     public function removePostMedia($post_id,$media_id,$link_type='attachment')
620     {
621          $this->postmedia->removePostMedia($post_id,$media_id,$link_type);
622     }
623
624     /**
625     Rebuilds database items collection. Optional <var>$pwd</var> parameter is
626     the path where to start rebuild.
627
628     @param    pwd       <b>string</b>       Directory to rebuild
629     */
630     public function rebuild($pwd='')
631     {
632          if (!$this->core->auth->isSuperAdmin()) {
633               throw new Exception(__('You are not a super administrator.'));
634          }
635
636          $this->chdir($pwd);
637          parent::getDir();
638
639          $dir = $this->dir;
640
641          foreach ($dir['dirs'] as $d) {
642               if (!$d->parent) {
643                    $this->rebuild($d->relname,false);
644               }
645          }
646
647          foreach ($dir['files'] as $f) {
648               $this->chdir(dirname($f->relname));
649               $this->createFile($f->basename);
650          }
651
652          $this->rebuildDB($pwd);
653     }
654
655     protected function rebuildDB($pwd)
656     {
657          $media_dir = $pwd ? $pwd : '.';
658
659          $strReq =
660          'SELECT media_file, media_id '.
661          'FROM '.$this->table.' '.
662          "WHERE media_path = '".$this->path."' ".
663          "AND media_dir = '".$this->con->escape($media_dir)."' ";
664
665          $rs = $this->con->select($strReq);
666
667          $delReq = 'DELETE FROM '.$this->table.' '.
668                    'WHERE media_id IN (%s) ';
669          $del_ids = array();
670
671          while ($rs->fetch())
672          {
673               if (!is_file($this->root.'/'.$rs->media_file)) {
674                    $del_ids[] = (integer) $rs->media_id;
675               }
676          }
677
678          if (!empty($del_ids)) {
679               $this->con->execute(sprintf($delReq,implode(',',$del_ids)));
680          }
681     }
682
683     public function makeDir($d)
684     {
685          $d = files::tidyFileName($d);
686          parent::makeDir($d);
687     }
688
689     /**
690     Creates or updates a file in database. Returns new media ID or false if
691     file does not exist.
692
693     @param    name      <b>string</b>       File name (relative to working directory)
694     @param    title     <b>string</b>       File title
695     @param    private   <b>boolean</b>      File is private
696     @param    dt        <b>string</b>       File date
697     @return   <b>integer</b> New media ID
698     */
699     public function createFile($name,$title=null,$private=false,$dt=null,$force=true)
700     {
701          if (!$this->core->auth->check('media,media_admin',$this->core->blog->id)) {
702               throw new Exception(__('Permission denied.'));
703          }
704
705          $file = $this->pwd.'/'.$name;
706          if (!file_exists($file)) {
707               return false;
708          }
709
710          $media_file = $this->relpwd ? path::clean($this->relpwd.'/'.$name) : path::clean($name);
711          $media_type = files::getMimeType($name);
712
713          $cur = $this->con->openCursor($this->table);
714
715          $strReq = 'SELECT media_id '.
716                    'FROM '.$this->table.' '.
717                    "WHERE media_path = '".$this->con->escape($this->path)."' ".
718                    "AND media_file = '".$this->con->escape($media_file)."' ";
719
720          $rs = $this->con->select($strReq);
721
722          if ($rs->isEmpty())
723          {
724               $this->con->writeLock($this->table);
725               try
726               {
727                    $rs = $this->con->select('SELECT MAX(media_id) FROM '.$this->table);
728                    $media_id = (integer) $rs->f(0) + 1;
729
730                    $cur->media_id = $media_id;
731                    $cur->user_id = (string) $this->core->auth->userID();
732                    $cur->media_path = (string) $this->path;
733                    $cur->media_file = (string) $media_file;
734                    $cur->media_dir = (string) dirname($media_file);
735                    $cur->media_creadt = date('Y-m-d H:i:s');
736                    $cur->media_upddt = date('Y-m-d H:i:s');
737
738                    $cur->media_title = !$title ? (string) $name : (string) $title;
739                    $cur->media_private = (integer) (boolean) $private;
740
741                    if ($dt) {
742                         $cur->media_dt = (string) $dt;
743                    } else {
744                         $cur->media_dt = strftime('%Y-%m-%d %H:%M:%S',filemtime($file));
745                    }
746
747                    try {
748                         $cur->insert();
749                    } catch (Exception $e) {
750                         @unlink($name);
751                         throw $e;
752                    }
753                    $this->con->unlock();
754               }
755               catch (Exception $e)
756               {
757                    $this->con->unlock();
758                    throw $e;
759               }
760          }
761          else
762          {
763               $media_id = (integer) $rs->media_id;
764
765               $cur->media_upddt = date('Y-m-d H:i:s');
766
767               $cur->update('WHERE media_id = '.$media_id);
768          }
769
770          $this->callFileHandler($media_type,'create',$cur,$name,$media_id,$force);
771
772          return $media_id;
773     }
774
775     /**
776     Updates a file in database.
777
778     @param    file      <b>fileItem</b>     Current fileItem object
779     @param    newFile   <b>fileItem</b>     New fileItem object
780     */
781     public function updateFile($file,$newFile)
782     {
783          if (!$this->core->auth->check('media,media_admin',$this->core->blog->id)) {
784               throw new Exception(__('Permission denied.'));
785          }
786
787          $id = (integer) $file->media_id;
788
789          if (!$id) {
790               throw new Exception('No file ID');
791          }
792
793          if (!$this->core->auth->check('media_admin',$this->core->blog->id)
794          && $this->core->auth->userID() != $file->media_user) {
795               throw new Exception(__('You are not the file owner.'));
796          }
797
798          $cur = $this->con->openCursor($this->table);
799
800          # We need to tidy newFile basename. If dir isn't empty, concat to basename
801          $newFile->relname = files::tidyFileName($newFile->basename);
802          if ($newFile->dir) {
803               $newFile->relname = $newFile->dir.'/'.$newFile->relname;
804          }
805
806          if ($file->relname != $newFile->relname) {
807               $newFile->file = $this->root.'/'.$newFile->relname;
808
809               if ($this->isFileExclude($newFile->relname)) {
810                    throw new Exception(__('This file is not allowed.'));
811               }
812
813               if (file_exists($newFile->file)) {
814                    throw new Exception(__('New file already exists.'));
815               }
816
817               $this->moveFile($file->relname,$newFile->relname);
818
819               $cur->media_file = (string) $newFile->relname;
820               $cur->media_dir = (string) dirname($newFile->relname);
821          }
822
823          $cur->media_title = (string) $newFile->media_title;
824          $cur->media_dt = (string) $newFile->media_dtstr;
825          $cur->media_upddt = date('Y-m-d H:i:s');
826          $cur->media_private = (integer) $newFile->media_priv;
827
828          $cur->update('WHERE media_id = '.$id);
829
830          $this->callFileHandler($file->type,'update',$file,$newFile);
831     }
832
833     /**
834     Uploads a file.
835
836     @param    tmp       <b>string</b>       Full path of temporary uploaded file
837     @param    name      <b>string</b>       File name (relative to working directory)
838     @param    title     <b>string</b>       File title
839     @param    private   <b>boolean</b>      File is private
840     */
841     public function uploadFile($tmp,$name,$title=null,$private=false,$overwrite=false)
842     {
843          if (!$this->core->auth->check('media,media_admin',$this->core->blog->id)) {
844               throw new Exception(__('Permission denied.'));
845          }
846
847          $name = files::tidyFileName($name);
848
849          parent::uploadFile($tmp,$name,$overwrite);
850
851          return $this->createFile($name,$title,$private);
852     }
853
854     /**
855     Creates a file from binary content.
856
857     @param    name      <b>string</b>       File name (relative to working directory)
858     @param    bits      <b>string</b>       Binary file content
859     */
860     public function uploadBits($name,$bits)
861     {
862          if (!$this->core->auth->check('media,media_admin',$this->core->blog->id)) {
863               throw new Exception(__('Permission denied.'));
864          }
865
866          $name = files::tidyFileName($name);
867
868          parent::uploadBits($name,$bits);
869
870          return $this->createFile($name,null,null);
871     }
872
873     /**
874     Removes a file.
875
876     @param    f         <b>fileItem</b>     fileItem object
877     */
878     public function removeFile($f)
879     {
880          if (!$this->core->auth->check('media,media_admin',$this->core->blog->id)) {
881               throw new Exception(__('Permission denied.'));
882          }
883
884          $media_file = $this->relpwd ? path::clean($this->relpwd.'/'.$f) : path::clean($f);
885
886          $strReq = 'DELETE FROM '.$this->table.' '.
887                    "WHERE media_path = '".$this->con->escape($this->path)."' ".
888                    "AND media_file = '".$this->con->escape($media_file)."' ";
889
890          if (!$this->core->auth->check('media_admin',$this->core->blog->id))
891          {
892               $strReq .= "AND user_id = '".$this->con->escape($this->core->auth->userID())."'";
893          }
894
895          $this->con->execute($strReq);
896
897          if ($this->con->changes() == 0) {
898               throw new Exception(__('File does not exist in the database.'));
899          }
900
901          parent::removeFile($f);
902
903          $this->callFileHandler(files::getMimeType($media_file),'remove',$f);
904     }
905
906     /**
907     * Root directories
908     *
909     * Returns an array of directory under {@link $root} directory.
910     *
911     * @uses fileItem
912     * @return array
913     */
914     public function getDBDirs()
915     {
916          $media_dir = $this->relpwd ? $this->relpwd : '.';
917
918          $strReq =
919          'SELECT distinct media_dir '.
920          'FROM '.$this->table.' '.
921          "WHERE media_path = '".$this->path."'";
922          $rs = $this->con->select($strReq);
923          while ($rs->fetch()) {
924               if (is_dir($this->root.'/'.$rs->media_dir))
925                    $dir[] = ($rs->media_dir == '.' ? '' : $rs->media_dir);
926          }
927
928          return $dir;
929     }
930
931     /**
932     Extract zip file in current location
933
934     @param    f         <b>fileRecord</b>   fileRecord object
935     */
936     public function inflateZipFile($f,$create_dir=true)
937     {
938          $zip = new fileUnzip($f->file);
939          $zip->setExcludePattern($this->exclude_pattern);
940          $zip->getList(false,'#(^|/)(__MACOSX|\.svn|\.DS_Store|\.directory|Thumbs\.db)(/|$)#');
941
942          if ($create_dir)
943          {
944               $zip_root_dir = $zip->getRootDir();
945               if ($zip_root_dir != false) {
946                    $destination = $zip_root_dir;
947                    $target = $f->dir;
948               } else {
949                    $destination = preg_replace('/\.([^.]+)$/','',$f->basename);
950                    $target = $f->dir.'/'.$destination;
951               }
952
953               if (is_dir($f->dir.'/'.$destination)) {
954                    throw new Exception(sprintf(__('Extract destination directory %s already exists.'),dirname($f->relname).'/'.$destination));
955               }
956          }
957          else
958          {
959               $target = $f->dir;
960               $destination = '';
961          }
962
963          $zip->unzipAll($target);
964          $zip->close();
965          return dirname($f->relname).'/'.$destination;
966     }
967
968     /**
969     Returns zip file content
970
971     @param    f         <b>fileRecord</b>   fileRecord object
972     @return <b>array</b>
973     */
974     public function getZipContent($f)
975     {
976          $zip = new fileUnzip($f->file);
977          $list = $zip->getList(false,'#(^|/)(__MACOSX|\.svn|\.DS_Store|\.directory|Thumbs\.db)(/|$)#');
978          $zip->close();
979          return $list;
980     }
981
982     /**
983     Calls file handlers registered for recreate event
984
985     @param    f    <b>fileItem</b>     fileItem object
986     */
987     public function mediaFireRecreateEvent($f)
988     {
989          $media_type = files::getMimeType($f->basename);
990          $this->callFileHandler($media_type,'recreate',null,$f->basename); // Args list to be completed as necessary (Franck)
991     }
992
993     /* Image handlers
994     ------------------------------------------------------- */
995     public function imageThumbCreate($cur,$f,$force=true)
996     {
997          $file = $this->pwd.'/'.$f;
998
999          if (!file_exists($file)) {
1000               return false;
1001          }
1002
1003          $p = path::info($file);
1004          $alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
1005          $thumb = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$p['dirname'],$p['base'],'%s');
1006
1007          try
1008          {
1009               $img = new imageTools();
1010               $img->loadImage($file);
1011
1012               $w = $img->getW();
1013               $h = $img->getH();
1014
1015               if ($force) $this->imageThumbRemove($f);
1016
1017               foreach ($this->thumb_sizes as $suffix => $s) {
1018                    $thumb_file = sprintf($thumb,$suffix);
1019                    if (!file_exists($thumb_file) && $s[0] > 0 &&
1020                         ($suffix == 'sq' || $w > $s[0] || $h > $s[0]))
1021                    {
1022                         $rate = ($s[0] < 100 ? 95 : ($s[0] < 600 ? 90 : 85));
1023                         $img->resize($s[0],$s[0],$s[1]);
1024                         $img->output(($alpha ? 'png' : 'jpeg'),$thumb_file,$rate);
1025                         $img->loadImage($file);
1026                    }
1027               }
1028               $img->close();
1029          }
1030          catch (Exception $e)
1031          {
1032               if ($cur === null) { # Called only if cursor is null (public call)
1033                    throw $e;
1034               }
1035          }
1036     }
1037
1038     protected function imageThumbUpdate($file,$newFile)
1039     {
1040          if ($file->relname != $newFile->relname)
1041          {
1042               $p = path::info($file->relname);
1043               $alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
1044               $thumb_old = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$p['dirname'],$p['base'],'%s');
1045
1046               $p = path::info($newFile->relname);
1047               $alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
1048               $thumb_new = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$p['dirname'],$p['base'],'%s');
1049
1050               foreach ($this->thumb_sizes as $suffix => $s) {
1051                    try {
1052                         parent::moveFile(sprintf($thumb_old,$suffix),sprintf($thumb_new,$suffix));
1053                    } catch (Exception $e) {}
1054               }
1055          }
1056     }
1057
1058     public function imageThumbRemove($f)
1059     {
1060          $p = path::info($f);
1061          $alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
1062          $thumb = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),'',$p['base'],'%s');
1063
1064          foreach ($this->thumb_sizes as $suffix => $s) {
1065               try {
1066                    parent::removeFile(sprintf($thumb,$suffix));
1067               } catch (Exception $e) {}
1068          }
1069     }
1070
1071     protected function imageMetaCreate($cur,$f,$id)
1072     {
1073          $file = $this->pwd.'/'.$f;
1074
1075          if (!file_exists($file)) {
1076               return false;
1077          }
1078
1079          $xml = new xmlTag('meta');
1080          $meta = imageMeta::readMeta($file);
1081          $xml->insertNode($meta);
1082
1083          $c = $this->core->con->openCursor($this->table);
1084          $c->media_meta = $xml->toXML();
1085
1086          if ($cur->media_title !== null && $cur->media_title == basename($cur->media_file))
1087          {
1088               if ($meta['Title']) {
1089                    $c->media_title = $meta['Title'];
1090               }
1091          }
1092
1093          if ($meta['DateTimeOriginal'] && $cur->media_dt === '')
1094          {
1095               # We set picture time to user timezone
1096               $media_ts = strtotime($meta['DateTimeOriginal']);
1097               if ($media_ts !== false) {
1098                    $o = dt::getTimeOffset($this->core->auth->getInfo('user_tz'),$media_ts);
1099                    $c->media_dt = dt::str('%Y-%m-%d %H:%M:%S',$media_ts+$o);
1100               }
1101          }
1102
1103          $c->update('WHERE media_id = '.$id);
1104     }
1105
1106     /**
1107     Returns HTML code for audio player (HTML5 and if possible fallback Flash player)
1108
1109     @param  type        <b>string</b>       audio mime type
1110     @param    url            <b>string</b>       audio URL to play
1111     @param    player         <b>string</b>       Player URL (flash player fallback)
1112     @param    args      <b>array</b>        Player parameters (flash player fallback)
1113     @param  fallback    <b>boolean</b>      Include Flash player fallback
1114     @return   <b>string</b>
1115     */
1116     public static function audioPlayer($type,$url,$player=null,$args=null,$fallback=true)
1117     {
1118          $audio =
1119               '<audio controls preload="auto">'.
1120               '<source src="'.$url.'">';
1121
1122          if ($fallback && $type == 'audio/mpeg3') {
1123               // Include Flash player fallback
1124               if (!$player) {
1125                    $player = 'player_mp3.swf';
1126               }
1127
1128               if (!is_array($args))
1129               {
1130                    $args = array(
1131                         'showvolume' => 1,
1132                         'loadingcolor' => 'ff9900',
1133                         'bgcolor1' => 'eeeeee',
1134                         'bgcolor2' => 'cccccc',
1135                         'buttoncolor' => '0066cc',
1136                         'buttonovercolor' => 'ff9900',
1137                         'slidercolor1' => 'cccccc',
1138                         'slidercolor2' => '999999',
1139                         'sliderovercolor' => '0066cc'
1140                    );
1141               }
1142
1143               $args['mp3'] = $url;
1144
1145               if (empty($args['width'])) {
1146                    $args['width'] = 200;
1147               }
1148               if (empty($args['height'])) {
1149                    $args['height'] = 20;
1150               }
1151
1152               $vars = array();
1153               foreach ($args as $k => $v) {
1154                    $vars[] = $k.'='.$v;
1155               }
1156
1157               $audio .=
1158                    '<object type="application/x-shockwave-flash" '.
1159                    'data="'.$player.'" '.
1160                    'width="'.$args['width'].'" height="'.$args['height'].'">'.
1161                    '<param name="movie" value="'.$player.'" />'.
1162                    '<param name="wmode" value="transparent" />'.
1163                    '<param name="FlashVars" value="'.implode('&amp;',$vars).'" />'.
1164                    __('Embedded Audio Player').
1165                    '</object>';
1166          }
1167
1168          $audio .=
1169               '</audio>';
1170
1171          return $audio;
1172     }
1173
1174     /**
1175     Returns HTML code for video player (HTML5 and if possible fallback Flash player)
1176
1177     @param  type        <b>string</b>       video mime type
1178     @param    url            <b>string</b>       video URL to play
1179     @param    player         <b>string</b>       Player URL (flash player fallback)
1180     @param    args      <b>array</b>        Player parameters (flash player fallback)
1181     @param  fallback    <b>boolean</b>      Include Flash player fallback (if not .flv)
1182     @return   <b>string</b>
1183     */
1184     public static function videoPlayer($type,$url,$player=null,$args=null,$fallback=true)
1185     {
1186          $video = '';
1187
1188          // Cope with width and height, if given
1189          $width = 400;
1190          $height = 300;
1191          if (is_array($args)) {
1192               if (!empty($args['width']) && $args['width']) {
1193                    $width = (int) $args['width'];
1194               }
1195               if (!empty($args['height']) && $args['height']) {
1196                    $height = (int) $args['height'];
1197               }
1198          }
1199
1200          if ($type != 'video/x-flv') {
1201               $video =
1202                    '<video controls preload="auto"'.($width ? ' width="'.$width.'"' : '').($height ? ' height="'.$height.'"' : '').'>'.
1203                    '<source src="'.$url.'">';
1204          }
1205
1206          if ($type == 'video/x-flv' || ($fallback && ($type == 'video/mp4' || $type == 'video/x-m4v')))
1207          {
1208               // Include Flash player fallback
1209               if (!$player) {
1210                    $player = 'player_flv.swf';
1211               }
1212
1213               if (!is_array($args))
1214               {
1215                    $args = array(
1216                         'margin' => 1,
1217                         'showvolume' => 1,
1218                         'showtime' => 1,
1219                         'showfullscreen' => 1,
1220                         'buttonovercolor' => 'ff9900',
1221                         'slidercolor1' => 'cccccc',
1222                         'slidercolor2' => '999999',
1223                         'sliderovercolor' => '0066cc'
1224                    );
1225               }
1226
1227               $args['flv'] = $url;
1228
1229               if (empty($args['width'])) {
1230                    $args['width'] = 400;
1231               }
1232               if (empty($args['height'])) {
1233                    $args['height'] = 300;
1234               }
1235
1236               $vars = array();
1237               foreach ($args as $k => $v) {
1238                    $vars[] = $k.'='.$v;
1239               }
1240
1241               $video .=
1242                    '<object type="application/x-shockwave-flash" '.
1243                    'data="'.$player.'" '.
1244                    'width="'.$args['width'].'" height="'.$args['height'].'">'.
1245                    '<param name="movie" value="'.$player.'" />'.
1246                    '<param name="wmode" value="transparent" />'.
1247                    '<param name="allowFullScreen" value="true" />'.
1248                    '<param name="FlashVars" value="'.implode('&amp;',$vars).'" />'.
1249                    __('Embedded Video Player').
1250                    '</object>';
1251          }
1252
1253          if ($type != 'video/x-flv') {
1254               $video .=
1255                    '</video>';
1256          }
1257
1258          return $video;
1259     }
1260
1261     /**
1262     Returns HTML code for MP3 player
1263
1264     @param    url            <b>string</b>       MP3 URL to play
1265     @param    player         <b>string</b>       Player URL
1266     @param    args      <b>array</b>        Player parameters
1267     @param  fallback    <b>boolean</b>      Include Flash player fallback
1268     @return   <b>string</b>
1269     */
1270     public static function mp3player($url,$player=null,$args=null,$fallback=true)
1271     {
1272          if (!$player) {
1273               $player = 'player_mp3.swf';
1274          }
1275
1276          if (!is_array($args))
1277          {
1278               $args = array(
1279                    'showvolume' => 1,
1280                    'loadingcolor' => 'ff9900',
1281                    'bgcolor1' => 'eeeeee',
1282                    'bgcolor2' => 'cccccc',
1283                    'buttoncolor' => '0066cc',
1284                    'buttonovercolor' => 'ff9900',
1285                    'slidercolor1' => 'cccccc',
1286                    'slidercolor2' => '999999',
1287                    'sliderovercolor' => '0066cc'
1288               );
1289          }
1290
1291          $args['mp3'] = $url;
1292
1293          if (empty($args['width'])) {
1294               $args['width'] = 200;
1295          }
1296          if (empty($args['height'])) {
1297               $args['height'] = 20;
1298          }
1299
1300          $vars = array();
1301          foreach ($args as $k => $v) {
1302               $vars[] = $k.'='.$v;
1303          }
1304
1305          return
1306          '<audio controls preload="auto">'.
1307          '<source src="'.$url.'" type="audio/mpeg">'.
1308          ($fallback ?
1309               '<object type="application/x-shockwave-flash" '.
1310               'data="'.$player.'" '.
1311               'width="'.$args['width'].'" height="'.$args['height'].'">'.
1312               '<param name="movie" value="'.$player.'" />'.
1313               '<param name="wmode" value="transparent" />'.
1314               '<param name="FlashVars" value="'.implode('&amp;',$vars).'" />'.
1315               __('Embedded Audio Player').
1316               '</object>' : '').
1317          '</audio>';
1318     }
1319
1320     /**
1321     Returns HTML code for FLV player
1322
1323     @param    url       <b>string</b>       FLV URL to play
1324     @param    player    <b>string</b>       Player URL
1325     @param    args      <b>array</b>        Player parameters
1326     @return   <b>string</b>
1327     */
1328     public static function flvplayer($url,$player=null,$args=null)
1329     {
1330          if (!$player) {
1331               $player = 'player_flv.swf';
1332          }
1333
1334          if (!is_array($args))
1335          {
1336               $args = array(
1337                    'margin' => 1,
1338                    'showvolume' => 1,
1339                    'showtime' => 1,
1340                    'showfullscreen' => 1,
1341                    'buttonovercolor' => 'ff9900',
1342                    'slidercolor1' => 'cccccc',
1343                    'slidercolor2' => '999999',
1344                    'sliderovercolor' => '0066cc'
1345               );
1346          }
1347
1348          $args['flv'] = $url;
1349
1350          if (empty($args['width'])) {
1351               $args['width'] = 400;
1352          }
1353          if (empty($args['height'])) {
1354               $args['height'] = 300;
1355          }
1356
1357          $vars = array();
1358          foreach ($args as $k => $v) {
1359               $vars[] = $k.'='.$v;
1360          }
1361
1362          return
1363          '<object type="application/x-shockwave-flash" '.
1364          'data="'.$player.'" '.
1365          'width="'.$args['width'].'" height="'.$args['height'].'">'.
1366          '<param name="movie" value="'.$player.'" />'.
1367          '<param name="wmode" value="transparent" />'.
1368          '<param name="allowFullScreen" value="true" />'.
1369          '<param name="FlashVars" value="'.implode('&amp;',$vars).'" />'.
1370          __('Embedded Video Player').
1371          '</object>';
1372     }
1373}
Note: See TracBrowser for help on using the repository browser.

Sites map