PageRenderTime 56ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/class.xfiledef.inc

https://github.com/jcplat/console-seolan
PHP | 1560 lines | 1383 code | 74 blank | 103 comment | 291 complexity | b6c21925187ad431547e037c84508d23 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /// Gestion d'un champ fichier, y compris images et videos
  3. class XFileDef extends XFieldDef {
  4. public $maxlength='';
  5. public $usealt=true;
  6. public $accept='.*';
  7. public $secured=false;
  8. public $crypt=false;
  9. public $sourcemodule=NULL;
  10. public $nocopydup=false;
  11. public $image_crop_ration='';
  12. public $image_geometry='640x480%3E';
  13. public $image_max_geometry=null;
  14. public $video_geometry='320x240%3E';
  15. public $video_bitrate='512';
  16. public $audio_geometry='300x30';
  17. public $audio_bitrate='128';
  18. public $autoplay=false;
  19. public $usemimehtml=false;
  20. public $viewlink=true;
  21. public $gzipped=false;
  22. public $indexable=true;
  23. public $auto_write_meta=false;
  24. static $html5_video_format = array(
  25. 'webm' => array('ffmpeg_opts' => FFMPEG_WEBM_OPTS),
  26. 'ogg' => array('ffmpeg_opts' => FFMPEG_OGG_OPTS),
  27. 'mp4' => array('ffmpeg_opts' => FFMPEG_MP4_OPTS),
  28. );
  29. function __construct($obj=NULL) {
  30. parent::__construct($obj);
  31. $this->thumb_geometry = TZR_THUMB_SIZE.'x'.TZR_THUMB_SIZE;
  32. $this->multivalued=false;
  33. if(empty($this->image_max_geometry) && defined('XFILEDEF_IMAGE_MAX_GEOMETRY')) $this->image_max_geometry=XFILEDEF_IMAGE_MAX_GEOMETRY;
  34. }
  35. /// Retourne l'extention d'un type mime
  36. static function mime2extension($mime) {
  37. $mimeClasse=XMimeTypes::getInstance();
  38. return $mimeClasse->get_extension($mime);
  39. }
  40. /// Retourne vrai si le type mime représente une image
  41. static public function isImage($mime){
  42. $mimeClasse=XMimeTypes::getInstance();
  43. return $mimeClasse->isImage($mime);
  44. }
  45. /// Retourne vrai si le type mime représente une vidéo
  46. static public function isVideo($mime){
  47. $mimeClasse=XMimeTypes::getInstance();
  48. return $mimeClasse->isVideo($mime);
  49. }
  50. /// Retourne vrai si le type mime représente un fichier audio
  51. static public function isAudio($mime){
  52. $mimeClasse = XMimeTypes::getInstance();
  53. return $mimeClasse->isAudio($mime);
  54. }
  55. /**
  56. * Function isEmpty
  57. * @return true si le champ n'est pas remplit
  58. */
  59. public function isEmpty($r) {
  60. if (property_exists($r, 'filename'))
  61. return empty($r->filename) && empty($r->externalUrl);
  62. else return true;
  63. }
  64. static function mkfilename($str, $mime) {
  65. $s=preg_replace('@([^\/0-9a-zA-Z_-]+)@','',$str);
  66. $mimeClasse = XMimeTypes::getInstance();
  67. $ext=$mimeClasse->get_extension($mime);
  68. return $s.'.'.$ext;
  69. }
  70. public function hasExternals() {
  71. return true;
  72. }
  73. /// Retourne le nom du fichier
  74. public function externals($value) {
  75. list($file,$mime,$originalname,$title)=explode(';',$value);
  76. $files=$this->filename($file,false,true);
  77. if(!empty($files)) return array($files);
  78. else return NULL;
  79. }
  80. /// Copie le fichier d'une fiche vers une autre fiche
  81. public function copyExternalsTo($value,$oidsrc,$oiddst,$upd=NULL) {
  82. if(empty($value) || empty($oiddst)) return NULL;
  83. if($value==TZR_UNCHANGED) return $value;
  84. @list($file,$mime,$originalname,$title) = explode(';',$value);
  85. if(strpos($file,'.')) list($lang)=explode('.',$file);
  86. $files=$this->filename($file,false,true);
  87. if(!empty($files) && file_exists($GLOBALS['DATA_DIR'].$files)) {
  88. list($table,$idd) = explode(':',$oiddst);
  89. if(!empty($lang)) $idd=$lang.'.'.$idd;
  90. // 1er appel : creation de l'arbo / 2eme appel : recupereation du nom du fichier
  91. $nfiles=$this->filename($idd,true,false,$upd);
  92. $nfiles=$this->filename($idd,false,false,$upd);
  93. copy($GLOBALS['DATA_DIR'].$files,$GLOBALS['DATA_DIR'].$nfiles);
  94. return $idd.';'.$mime.';'.$originalname.';'.$title;
  95. }else{
  96. return TZR_UNCHANGED;
  97. }
  98. }
  99. function initOptions() {
  100. parent::initOptions();
  101. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','xfileviewlink'), 'viewlink','boolean');
  102. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','usemimehtml'), 'usemimehtml','boolean');
  103. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','maxlength'), 'maxlength', 'text');
  104. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','usealt'), 'usealt', 'boolean');
  105. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','accept'), 'accept', 'text');
  106. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','browsemods'), 'browsemods', 'boolean');
  107. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','sourcemodule'), 'sourcemodule', 'module');
  108. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','secured'), 'secured', 'boolean');
  109. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','crypt'), 'crypt', 'boolean');
  110. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','image_crop_ratio'), 'image_crop_ratio', 'text');
  111. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','image_geometry'), 'image_geometry', 'text');
  112. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','image_max_geometry'), 'image_max_geometry', 'text');
  113. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','video_geometry'), 'video_geometry', 'text');
  114. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','video_bitrate'), 'video_bitrate', 'text');
  115. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','audio_bitrate'), 'audio_bitrate', 'text');
  116. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','autoplay'), 'autoplay', 'boolean');
  117. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','gzipped'), 'gzipped', 'boolean');
  118. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','allow_externalfile'), 'allow_externalfile', 'boolean');
  119. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','xfiledef_autowritemeta'),'auto_write_meta','boolean');
  120. $querygroup=XLabels::getSysLabel('general','query','text');
  121. $this->_options->setOpt(XLabels::getSysLabel('xfielddef.indexable'), 'indexable', 'boolean', NULL, true, $querygroup);
  122. }
  123. // Verification que les repertoires qui contiennent les fichiers n'existent pas, sinon on les cree
  124. function _checkDir() {
  125. global $DATA_DIR;
  126. umask(0000);
  127. $root=$DATA_DIR.$this->table.'/'.$this->field;
  128. if(!is_dir($root)) {
  129. if(!is_dir($DATA_DIR.$this->table)) {
  130. @mkdir($DATA_DIR.$this->table,0777);
  131. }
  132. if(!is_dir($DATA_DIR.$this->table.'/'.$this->field)) {
  133. @mkdir($DATA_DIR.$this->table.'/'.$this->field,0777);
  134. }
  135. }
  136. }
  137. /// Suppression du champ, i.e. suppression du repertoire et des donnees incluses dans ce repertoire
  138. function delfield() {
  139. global $DATA_DIR;
  140. XDir::unlink($DATA_DIR.$this->table.'/'.$this->field);
  141. }
  142. /// Ecriture dans un fichier excel
  143. function writeXLS(&$xl,$i,$j,&$value,$format=0,&$ss=NULL) {
  144. if(!empty($value->url)){
  145. $lab=$value->text;
  146. if(empty($lab)) $lab='Link';
  147. convert_charset($lab,TZR_INTERNAL_CHARSET,'UTF-8');
  148. $xl->setCellValueByColumnAndRow($j,$i,$lab);
  149. $xl->getCellByColumnAndRow($j,$i)->getHyperlink()->setUrl($GLOBALS['HOME_ROOT_URL'].$value->url);
  150. if(is_array($format)) $xl->getStyleByColumnAndRow($j,$i)->applyFromArray($format);
  151. }
  152. }
  153. /// Ecriture dans un csv
  154. function writeCSV(&$o,$textsep){
  155. return $textsep.$o->originalname.$textsep;
  156. }
  157. /// Affiche dans le mode parcourir
  158. function my_browse(&$value,&$options) {
  159. $r=&$this->my_display($value,$options);
  160. if($this->usemimehtml && !empty($options['admin'])) {
  161. $r->html=$r->html_preview;
  162. }
  163. return $r;
  164. }
  165. /// Retourne la taille du fichier
  166. function getFileSize($r){
  167. if(empty($r->filesize)) $r->filesize=filesize($r->filename);
  168. return $r->filesize;
  169. }
  170. /// Affichage du champ
  171. function my_display($value,&$options) {
  172. global $DATA_DIR;
  173. $langdata = XShell::getLangData();
  174. $resizer=TZR_RESIZER;
  175. $r=$this->_newXFieldVal($options, true);
  176. $r->type = NULL;
  177. $r->resizer = NULL;
  178. $r->mime = NULL;
  179. $r->isImage = false;
  180. $r->isVideo = false;
  181. if($value=='' || $value==TZR_UNCHANGED)
  182. return $r;
  183. @list($file,$mime,$originalname,$title) = explode(';',$value);
  184. if (strpos($file, ':') !== false)
  185. return $this->displayExternal($r, $file, $value, $options);
  186. if(empty($originalname)) {
  187. $originalname = 'download';
  188. $mimeClasse = XMimeTypes::getInstance();
  189. $originalname .= '.'.$mimeClasse->get_extension($mime);
  190. }
  191. $files=$this->filename($file,false,false,@$options['_archive']);
  192. if(!$files) return $r;
  193. $filename=$DATA_DIR.$files;
  194. $originalname_corrected=preg_replace('@([^\._a-zA-Z0-9-]+)@','_',$originalname);
  195. $downloader=$this->getDownloader($files, $mime, $originalname_corrected, $title, @$options['fmoid']);
  196. $r->filename=$filename;
  197. $r->shortfilename=$files;
  198. $r->mime=$mime;
  199. $r->title=$title;
  200. $r->originalname=$originalname;
  201. $r->raw=$value;
  202. $r->url=$downloader[0];
  203. $r->text=$r->title?$r->title:$r->originalname;
  204. $r->mimepicto=XLabels::getSysLabel('mime',$mime, 'both', 'mime', 'unknown/unknown');
  205. $r->html_default='<a bt-xpath="'.TZR_AJAX8.'?class=xfiledef&function=xfiledef_getfilesize&file='.$files.'&_='.XShell::uniqid().'" class="tzr-hottip-c tzr-file" href="'.$r->url.'" target="_self">'.$r->mimepicto.(empty($title)?$originalname:$title).'</a>';
  206. $r->html_preview=$r->html_default;
  207. $r->html=$r->html_default;
  208. if(XFileDef::isVideo($mime)) $this->displayVideo($r,$value,$options);
  209. elseif(XFileDef::isImage($mime)) $this->displayImage($r,$value,$options);
  210. elseif($mime=='application/pdf') $this->displayPDF($r,$value,$options);
  211. elseif(XFileDef::isAudio($mime)) $this->displayAudio($r,$value,$options);
  212. return $r;
  213. }
  214. /// Affichage d'un fichier externe
  215. function displayExternal(&$r, $file, $value, $options) {
  216. $r->file = $file;
  217. $r->raw = $value;
  218. list($r->type, $r->id) = explode(':', $file, 2);
  219. $r->isExternal = true;
  220. $displayFunction = 'display'.$r->type;
  221. if (method_exists($this, $displayFunction))
  222. return $this->$displayFunction($r, $options);
  223. $r->externalUrl = $r->id;
  224. return $r;
  225. }
  226. /* Image */
  227. /// Complete l'objet d'affichage dans le cas d'une image
  228. function displayImage(&$r,&$value,$options){
  229. $resizer=$this->getResizer($r->shortfilename,$r->mime,$r->originalname);
  230. if(!empty($resizer) && !empty($resizer['resizer'])) {
  231. $r->resizer=$resizer['resizer'];
  232. $r->weresizer=$resizer['weresizer'];
  233. }
  234. $r->isImage=true;
  235. if($this->usemimehtml){
  236. $r->html = '<img class="tzr-image" src="'.$r->resizer.'&geometry='.$this->image_geometry.'" alt="'.$r->title.'" title="'.$r->title.'">';
  237. if ($this->viewlink) $r->html.='<br>'.$r->html_default;
  238. }
  239. $r->html_preview = '<img class="tzr-image" src="'.$r->resizer.'&geometry='.TZR_THUMB_SIZE.'x'.TZR_THUMB_SIZE.'%3E" alt="'.$r->title.'" title="'.$r->title.'">';
  240. if ($this->viewlink) $r->html_preview.='<br>'.$r->html_default;
  241. }
  242. /// Retourne le code html du preview d'une image
  243. function html_previewImage($r, $options=array()) {
  244. $options = array_merge(array('title' => $r->title, 'geometry' => $this->thumb_geometry), $options);
  245. return $this->htmlImage($r, $options);
  246. }
  247. /// Retourne le code html d'une image
  248. function htmlImage($r, $options=array()) {
  249. $options = array_merge(array('title' => $r->title, 'geometry' => $this->image_geometry), $options);
  250. $geometry = $options['geometry'];
  251. $this->getImageSize($r);
  252. list($w, $h) = explode('x', str_replace('>', '', $geometry));
  253. $w = (integer)$w;
  254. $h = (integer)$h;
  255. $ratio = $r->fullheight / $r->fullwidth;
  256. if (isset($options['gravity'])) { // on peux croper
  257. $geometry = (integer)($ratio * $r->fullwidth).'x'.(integer)($ratio * $r->fullheight);
  258. $crop = '&amp;crop='.$w.'x'.$h.'&amp;gravity='.$options['gravity'];
  259. } else {
  260. if ($w < $r->fullwidth || $h < $r->fullheight) {
  261. if ($ratio < 1)
  262. $h = (integer)($w*$ratio);
  263. else
  264. $w = (integer)($h/$ratio);
  265. } else {
  266. $w = $r->fullwidth;
  267. $h = $r->fullheight;
  268. }
  269. $geometry = $w.'x'.$h;
  270. }
  271. return '<img class="tzr-image" src="'.$r->resizer.'&amp;geometry='.$geometry.@$crop.'" '.(isset($options['title']) ? ' alt="'.@$options['title'].'" title="'.@$options['title'].'"':'').(isset($w)?' width="'.$w.'" height="'.$h.'"':'').'>';
  272. }
  273. /// Retourne le code html
  274. function completeHTML($r, $options=array(), $alt){
  275. if (empty($r) || $r->raw == '')
  276. return '';
  277. if (is_string($options)) { // from template
  278. parse_str($options, $options);
  279. }
  280. if (count($options)==1 && current($options) == '') // compatibilité
  281. $options = array('geometry' => key($options));
  282. if ($r->isExternal) {
  283. $htmlFunction = 'html'.$r->type;
  284. if (method_exists($this, $htmlFunction))
  285. $html = $this->$htmlFunction($r, $options);
  286. }
  287. elseif ($r->isImage || $r->isPDF)
  288. $html = $this->htmlImage($r, $options);
  289. elseif ($r->isVideo)
  290. $html = $this->htmlVideo($r, $options);
  291. elseif ($r->isAudio)
  292. $html = $this->htmlAudio($r, $options, $alt);
  293. else
  294. $html = $r->html_default;
  295. return $html;
  296. }
  297. /// Retourne l'url des reiszer
  298. protected function getResizer($filename,$mime="null/null",$originalname=NULL){
  299. $mimedst=$mime;
  300. if($mime=='image/x-png') $mime=$mimedst='image/png';
  301. if(($mime!='image/gif') && ($mime!='image/png')) $mimedst='image/jpeg';
  302. $mimedst=rawurlencode($mimedst);
  303. $fmime = '';
  304. $mimeClasse=XMimeTypes::getInstance();
  305. if($mime=='application/pdf'){
  306. $fmime=$mime;
  307. }elseif($mimeClasse->isImage($mime)) {
  308. $fmime=$mimedst;
  309. }
  310. if(!empty($fmime)){
  311. $str = '?filename='.$filename.'&amp;mime='.$fmime.'&amp;';
  312. if($originalname) $str .= '&amp;originalname='.rawurlencode($originalname);
  313. $resizer=TZR_RESIZER.$str;
  314. $weresizer=TZR_WERESIZER.$str;
  315. }else{
  316. $resizer=$weresizer='';
  317. }
  318. return array('resizer'=>$resizer,'weresizer'=>$weresizer);
  319. }
  320. /// Retourne la taille en px d'une image
  321. function getImageSize($r,$dim=NULL){
  322. if(!isset($r->fullwidth)){
  323. if($r->isImage) $t=getimagesize($r->filename);
  324. elseif($r->isVideo) $t=getimagesize($r->filename.'-fullsizeimage');
  325. elseif($r->isPDF) {
  326. if (!file_exists($r->filename.'-fullsizeimage'))
  327. exec(TZR_MOGRIFY_RESIZER . ' ' . $r->filename . '[0] jpeg:' . $r->filename . '-fullsizeimage');
  328. $t=getimagesize($r->filename.'-fullsizeimage');
  329. }
  330. else $t=array(0,0);
  331. $r->fullwidth=$t[0];
  332. $r->fullheight=$t[1];
  333. }
  334. if($dim) return $r->$dim;
  335. }
  336. /// Recupere la largeur ou la hauteur finale d'une image en fonction d'une géométrie passée au resizer
  337. function getImageResize($r,$geometry,$dim){
  338. if(empty($r->_cache['size'][$geometry])){
  339. $this->getImageSize($r);
  340. $t=array($r->fullwidth,$r->fullheight);
  341. $oratio=$t[0]/$t[1];
  342. $size=explode('x',$geometry);
  343. if(!is_numeric($size[0])) $size[0]=0;
  344. if(empty($size[1]) || !is_numeric($size[1])) $size[1]=0;
  345. $ratio=$size[0]/$size[1];
  346. if(!empty($size[0]) && ($oratio>$ratio || empty($size[1]))){
  347. $w=$size[0];
  348. $h=round($t[1]*$size[0]/$t[0]);
  349. }else{
  350. $w=round($t[0]*$size[1]/$t[1]);
  351. $h=$size[1];
  352. }
  353. $r->_cache['size'][$geometry]=array('width'=>$w,'height'=>$h);
  354. }
  355. return $r->_cache['size'][$geometry][$dim];
  356. }
  357. /// Retourne une propriété iptc ou l'objet iptc de l'image
  358. function getIPTC($r,$prop=NULL){
  359. if($r->mime=='image/jpeg'){
  360. if(empty($r->meta_data)) $r->meta_data=XFileDef::loadMeta($r->filename);
  361. if(!$prop) return $r->meta_data;
  362. else return $r->meta_data->getIPTCProperty($prop);
  363. }
  364. return NULL;
  365. }
  366. /// Retourne une propriété exif ou l'objet exif de l'image
  367. function getEXIF($r,$prop=NULL){
  368. if($r->mime=='image/jpeg'){
  369. if(empty($r->exif_data)) $r->exif_data=exif_read_data($r->filename);
  370. if(!$prop) return $r->exif_data;
  371. else return $r->exif_data[$prop];
  372. }
  373. return NULL;
  374. }
  375. /// Retourne une propriété XMP ou l'objet XMP de l'image
  376. function getXMP($r,$prop=NULL){
  377. if($r->mime=='image/jpeg'){
  378. if(empty($r->meta_data)) $r->meta_data=XFileDef::loadMeta($r->filename);
  379. if(!$prop) return $r->meta_data;
  380. else return $r->meta_data->getXMPProperty($prop,array('Alt'=>array('lang'=>array(XShell::getLangData(),'x-default'))));
  381. }
  382. return NULL;
  383. }
  384. /// Charge l'objet meta du fichier
  385. static function loadMeta($file){
  386. return new MetaAnalyser($file);
  387. }
  388. /// Redimensione une image
  389. function resizeImage($file,$geo=null){
  390. if(!$geo) return false;
  391. // Verifie si l'image est plus grande qua la taille max ou pas
  392. $s=getimagesize($file);
  393. list($w,$h)=explode('x',$geo);
  394. if(!is_numeric($w)) $w=99999;
  395. if(empty($h) || !is_numeric($h)) $h=99999;
  396. if($s[0]<$w && $s[1]<$h) return false;
  397. // Redimensionne l'image
  398. $geo=rawurldecode($geo);
  399. exec(TZR_MOGRIFY_RESIZER.' -resize "'.$geo.'" '.$file.' '.$file);
  400. return true;
  401. }
  402. /// Applique rotate et flip à un fichier selon son orientation exif
  403. function rotateAndFlip($filename,$mime){
  404. $r=(object)array('filename'=>$filename,'mime'=>$mime);
  405. $o=$this->getExif($r,'Orientation');
  406. if(!empty($o) && $o!=1){
  407. switch ($o){
  408. case 2:
  409. $opt='-flop';
  410. break;
  411. case 3:
  412. $opt='-rotate 180';
  413. break;
  414. case 4:
  415. $opt='-flip';
  416. break;
  417. case 5:
  418. $opt='-flip -rotate "90"';
  419. break;
  420. case 6:
  421. $opt='-rotate "90"';
  422. break;
  423. case 7:
  424. $opt='-flop -rotate "90"';
  425. break;
  426. case 8:
  427. $opt='-rotate "-90"';
  428. break;
  429. }
  430. exec(TZR_MOGRIFY_RESIZER.' '.$opt.' '.$filename.' '.$filename);
  431. }
  432. }
  433. /* Video */
  434. /// Complete l'objet d'affichage dans le cas d'une video
  435. function displayVideo(&$r,&$value,&$options){
  436. $r->isVideo=true;
  437. $r->resizer=TZR_VIDEOCONVERT.'?filename='.$r->shortfilename;
  438. $r->preview=TZR_VIDEOCONVERT.'?preview=true&filename='.$r->shortfilename;
  439. if ($this->usemimehtml) {
  440. $r->html_preview = $this->html_previewVideo($r, $options);
  441. $r->html = $this->htmlVideo($r, $options);
  442. if ($this->viewlink) {
  443. $r->html .= '<br>'.$r->html_default;
  444. $r->html_preview .= '<br>'.$r->html_default;
  445. }
  446. } else
  447. $r->html = $r->html_preview;
  448. }
  449. /// Code html du preview d'une vidéo
  450. function html_previewVideo($r, $options=array()) {
  451. $options = array_merge(array('title' => $r->title, 'geometry' => $this->thumb_geometry), $options);
  452. $geometry = XFileDef::videoGetGeometry($r->filename, $options['geometry']);
  453. list($width, $height) = explode('x', $geometry);
  454. return '<img class="tzr-image" src="'.$r->preview.'&geometry='.$geometry.'" alt="'.$options['title'].'" title="'.$options['title'].'" width="'.$width.'" height="'.$height.'">';
  455. }
  456. /// Code html de l'affichage d'une vidéo
  457. function htmlVideo(&$r, $options=array(1=>1)) {
  458. global $DATA_URL;
  459. $options = array_merge(array('title' => $r->title, 'geometry' => $this->video_geometry, 'video_bitrate' => $this->video_bitrate, 'autoplay' => $this->autoplay, 'fullscreen' => 1), $options);
  460. $geometry = XFileDef::videoGetGeometry($r->filename, $options['geometry']);
  461. list($width, $height) = explode('x', $geometry);
  462. $r->video_bitrate = $options['video_bitrate'];
  463. if ($this->videoReady($r, $geometry, true, $options['video_bitrate'])) {
  464. if (defined('HTML5MEDIA')) {
  465. $html = '
  466. <div class="tzr-video-div">
  467. <video id="'.$r->varid.'" class="tzr-video" '.($options['autoplay'] ? ' autoplay="autoplay"' : '').' width="'.$width.'" height="'.$height.'" controls poster="'.$r->preview.'&geometry='.$geometry.'" preload="none">';
  468. foreach (XFileDef::$html5_video_format as $format => $opts) {
  469. $html .= '
  470. <source src="'.$r->resizer.'&geometry='.$geometry.'&bitrate='.$options['video_bitrate'].'&format='.$format.'&type=.'.$format.'" type="video/'.$format.'"/>';
  471. }
  472. $html .= '
  473. </video>
  474. <script type="text/javascript">
  475. jQuery("#'.$r->varid.'").mediaelementplayer({pluginPath: "'.TZR_SHARE_URL.'js/jmediaelement/"});
  476. </script>
  477. </div>';
  478. } else {
  479. $html = '<div style="width='.$width.'px;height:'.$height.'px"><div id="'.$r->varid.'"></div></div><script type="text/javascript">swfobject.embedSWF("'.TZR_SHARE_URL.'flash/player_flv_maxi.swf","'.$r->varid.'","'.$width.'","'.$height.'","8","",{flv:"'.urlencode($r->resizer.'&geometry='.$geometry.'&bitrate='.$options['video_bitrate']).'",startimage:"'.urlencode($r->preview.'&geometry='.$geometry).'",autoplay:'.($options['autoplay']?'1':'0').',showfullscreen:'.($options['fullscreen']?'1':'0').',margin:0,showstop:1,showvolume:1,showtime:1,ondoubleclick:"fullscreen"},{allowFullScreen:true, wmode:"transparent"});</script>';
  480. }
  481. }
  482. else {
  483. $html = '<img src="'.$r->preview.'&geometry='.$geometry.'" alt="'.$title.'" title="'.$title.'" width="'.$width.'" height="'.$height.'">';
  484. }
  485. return $html;
  486. }
  487. /// Determine si le fichier est directement disponible dans le format.
  488. /// Si 'force' a true et fichier non disponible, lance la tache de conversion.
  489. function videoReady($r,$geometry,$forceConvert=true) {
  490. if(!XFileDef::isVideo($r->mime))
  491. return false;
  492. $geometry=XFileDef::videoGetGeometry($r->filename,$geometry);
  493. $ready = true;
  494. $ffmpeg = '';
  495. if (defined('HTML5MEDIA')) { // html5 video tag
  496. foreach (XFileDef::$html5_video_format as $format => $opts) {
  497. $hash = md5($geometry.$r->video_bitrate.'video/'.$format);
  498. $filename_cache = $r->filename.'-'.$hash.'-cache';
  499. if (!file_exists($filename_cache) || (filemtime($filename)>filemtime($filename_cache))) {
  500. $ready = false;
  501. if ($forceConvert) {
  502. $ffmpeg .= FFMPEG." -y -i {$r->filename} {$opts['ffmpeg_opts']} -vb {$r->video_bitrate}k -s $geometry $filename_cache ;\n";
  503. }
  504. }
  505. }
  506. }
  507. else {
  508. $hash = md5($geometry.$r->video_bitrate.'video/x-flv');
  509. $filename_cache=$r->filename.'-'.$hash.'-cache';
  510. if (!file_exists($filename_cache) || (filemtime($filename)>filemtime($filename_cache))) {
  511. $ready = false;
  512. if ($forceConvert) {
  513. $ffmpeg .= FFMPEG." -y -i {$r->filename} -ab 64k -ar 22050 -f flv -vb {$r->video_bitrate}k -s $geometry $filename_cache ";
  514. }
  515. }
  516. }
  517. if ($ffmpeg) {
  518. $s=new XModScheduler(array('tplentry'=>TZR_RETURN_DATA));
  519. $s->createIdleShellJob(md5($ffmpeg),'Video encoding',$ffmpeg,'');
  520. }
  521. return $ready;
  522. }
  523. /// Affichage d'une video youtube
  524. function displayYoutube(&$r, $value, $options) {
  525. require_once 'Zend/Loader.php'; // the Zend dir must be in your include_path
  526. Zend_Loader::loadClass('Zend_Gdata_YouTube');
  527. $r->videoid = $r->id;
  528. $r->videourl = 'http://www.youtube.com/watch?v='.$r->videoid;
  529. $r->isVideo = true;
  530. $r->videoReady = true;
  531. $r->resizer = '';
  532. $yt = new Zend_Gdata_YouTube();
  533. $yt->setMajorProtocolVersion(2);
  534. try {
  535. $videoEntry = $yt->getVideoEntry($r->videoid);
  536. $r->externalUrl = $videoEntry->getVideoWatchPageUrl();
  537. $r->embedUrl = 'http://www.youtube.com/embed/' . $r->videoid;
  538. $thumbnails = $videoEntry->getVideoThumbnails();
  539. $r->flashplayer = $videoEntry->getFlashPlayerUrl();
  540. $r->preview = $thumbnails[0]; /// TODO: choose best size
  541. $r->title = $videoEntry->getVideoTitle();
  542. $r->text = $r->title;
  543. $r->error = false;
  544. } catch(Zend_Gdata_App_HttpException $e) {
  545. $r->error = true;
  546. XLogs::notice('XFileDef::displayYoutube', "Error : " . $e->getMessage());
  547. }
  548. $r->fullwidth = 1600;
  549. $r->fullheight = 900;
  550. $r->html_preview = $this->html_previewYoutube($r, $options);
  551. if ($this->usemimehtml)
  552. $r->html = $this->htmlYoutube($r, $options);
  553. else
  554. $r->html = $r->html_preview;
  555. return $r;
  556. }
  557. /// html du preview d'une video youtube
  558. function html_previewYoutube($r, $options=array()) {
  559. if ($r->error)
  560. return '';
  561. if (isset($options['geometry']))
  562. list($width, $height) = explode('x', str_replace('>', '', $options['geometry']));
  563. else
  564. $width = $height = TZR_THUMB_SIZE;
  565. $margin = (int) -($width * $r->preview['height']/$r->preview['width'] - $height) /2;
  566. return '<div style="width:'.$width.'px;height:'.$height.'px;overflow:hidden;display:inline"><img src="'.$r->preview['url'].'" alt="'.$r->title.'" width="'.$width.'" class="tzr-externalfile" rel="'.$r->file.'"'.($margin<0?'style="margin-top:'.$margin.'px"':'').'></div>';
  567. }
  568. /// html d'une video youtube
  569. function htmlYoutube($r, $options=array()) {
  570. if ($r->error)
  571. return '';
  572. $options = array_merge(array('autoplay' => $this->autoplay, 'geometry' => $this->video_geometry), $options);
  573. list($width, $height) = explode('x', str_replace('>', '', rawurldecode($options['geometry'])));
  574. return '<iframe id="'.$r->varid.'" width="'.$width.'" height="'.$height.'" style="width:'.$width.'px;height:'.$height.'px" src="'.$r->embedUrl.'?enablejsapi=1&origin='.$GLOBALS['TZR_SESSION_MANAGER']::makeDomainName().'&wmode=transparent'.($options['autoplay']?'&autoplay=1':'').'"></iframe>';
  575. }
  576. /// Affichage d'une video Daily Motion
  577. function displayDailyMotion(&$r, $file, $value, $options) {
  578. $videoid = substr($file, 12);
  579. $r->videoid = $r->id;
  580. $r->videourl = 'http://www.dailymotion.com/video/'.$r->videoid;
  581. $r->isVideo = true;
  582. $r->videoReady = true;
  583. $r->resizer = '';
  584. if (!$videoEntry = file_get_contents('https://api.dailymotion.com/video/'.$r->videoid.'?fields=allow_embed,url,embed_url,thumbnail_medium_url,title')) {
  585. XLogs::notice('XFileDef::displayDailyMotion', "Error : cannot retreive video information ");
  586. $r->error = true;
  587. return $r;
  588. }
  589. $videoEntry = json_decode($videoEntry);
  590. if ($videoEntry->error) {
  591. XLogs::notice('XFileDef::displayDailyMotion', "Error : " . $videoEntry->error->message);
  592. $r->error = true;
  593. return $r;
  594. }
  595. if (!$videoEntry->allow_embed) {
  596. XLogs::notice('XFileDef::displayDailyMotion', "Error : {$r->videoid} embed not allowed");
  597. return $r;
  598. }
  599. $r->preview = array(
  600. 'url' => $videoEntry->thumbnail_medium_url,
  601. 'width' => 160,
  602. 'height' => 120
  603. );
  604. $r->title = $videoEntry->title;
  605. $r->externalUrl = $videoEntry->url;
  606. $r->embedUrl = $videoEntry->embed_url;
  607. $r->html_preview = $this->html_previewDailyMotion($r, $options);
  608. if ($this->usemimehtml)
  609. $r->html = $this->htmlDailyMotion($r, $options);
  610. else
  611. $r->html = $r->html_preview;
  612. return $r;
  613. }
  614. /// html du preview d'une video Daily Motion
  615. function html_previewDailyMotion($r, $options=array()) {
  616. return $this->html_previewYoutube($r, $options=array());
  617. }
  618. /// html d'une video Daily Motion
  619. function htmlDailyMotion($r, $options=array()) {
  620. return $this->htmlYoutube($r, $options=array());
  621. }
  622. /// Gestion de la geometrie d'une video
  623. static function videoGetGeometry($filename,$geometry){
  624. if(strpos($filename,$GLOBALS['DATA_DIR'])===false) $filename=$GLOBALS['DATA_DIR'].$filename;
  625. $geometry=rawurldecode($geometry);
  626. if(substr($geometry,-1)=='>')
  627. $geometry=substr($geometry,0,-1);
  628. $filefullsizeimage=$filename.'-fullsizeimage';
  629. if(!($t=@getimagesize($filefullsizeimage))){
  630. exec(FFMPEG.' -y -i "'.$filename.'" -f image2 -vcodec mjpeg -vframes 1 -an "'.$filefullsizeimage.'"');
  631. $t=@getimagesize($filefullsizeimage);
  632. }
  633. $oratio=$t[0]/$t[1];
  634. $size=explode('x',$geometry);
  635. $ratio=$size[0]/$size[1];
  636. if (!$size[0] || !$size[1])
  637. XLogs::critical('videoGetGeometry geometry imcomplete definition: '.$size[0].'x'.$size[1], '', true);
  638. if($oratio>$ratio){
  639. $w=$size[0];
  640. $h=round($t[1]*$size[0]/$t[0]);
  641. }else{
  642. $w=round($t[0]*$size[1]/$t[1]);
  643. $h=$size[1];
  644. }
  645. if($w%2) $w--;
  646. if($h%2) $h--;
  647. $geometry=$w.'x'.$h;
  648. return $geometry;
  649. }
  650. /* Audio */
  651. /// Complete l'objet d'affichage dans le cas d'un fichier audio
  652. function displayAudio(&$r,&$value,&$options){
  653. global $DATA_URL;
  654. $r->isAudio=true;
  655. $r->audio_bitrate = $this->audio_bitrate;
  656. $r->prehear = TZR_AUDIOCONVERT.'?prehear=true&filename='.$r->shortfilename.'&type=.mp3';
  657. $r->fullaudio = TZR_AUDIOCONVERT.'?filename='.$r->shortfilename.'&type=.mp3';
  658. if (defined('HTML5MEDIA')) {
  659. $r->prehear_ogg = TZR_AUDIOCONVERT.'?mime=audio/ogg&prehear=true&filename='.$r->shortfilename.'&type=.ogg';
  660. $r->fullaudio_ogg = TZR_AUDIOCONVERT.'?mime=audio/ogg&filename='.$r->shortfilename.'&type=.ogg';
  661. }
  662. if ($this->usemimehtml) {
  663. $r->html_preview = $this->html_previewAudio($r, $options);
  664. $r->html = $this->htmlAudio($r, $options);
  665. if ($this->viewlink) {
  666. $r->html .= '<br>'.$r->html_default;
  667. $r->html_preview .= '<br>'.$r->html_default;
  668. }
  669. } else
  670. $r->html = $r->html_preview;
  671. return $r;
  672. }
  673. /// html preview audio, $alt est un media alternatif (image)
  674. function html_previewAudio($r, $options=array(), $alt) {
  675. $options = array_merge(array('title' => $r->title, 'geometry' => $this->thumb_geometry, 'img' => TZR_SHARE_URL.'ico/mime/big-mp3.gif'), $options);
  676. if ($alt && is_object($alt) && $alt->raw)
  677. return $this->html_previewImage($alt, $options);
  678. $html = '<img src="'.$options['img'].'" alt="'.$r->title.'">';
  679. return $html;
  680. }
  681. /// html audio, $alt est un media alternatif (image)
  682. function htmlAudio(&$r, $options=array(), $alt) {
  683. $options = array_merge(array('audio_bitrate' => $this->audio_bitrate, 'audio_geometry' => $this->audio_geometry, 'geometry' => $this->geometry, 'autoplay' => $this->autoplay), $options);
  684. list($width, $height) = explode('x', str_replace('>', '', $options['audio_geometry']));
  685. list($altwidth, $altheight) = explode('x', str_replace('>', '', $options['geometry']));
  686. if ($options['audio_bitrate'] != $this->audio_bitrate) {
  687. $r->audio_bitrate = $options['audio_bitrate'];
  688. $this->displayAudio($r);
  689. }
  690. if ($alt && is_object($alt) && $alt->raw) {
  691. $options['geometry'] = $altwidth.'x'.($altheight-$height);
  692. $img = '<div class="tzr-audio-alt">' . $this->htmlImage($alt, $options) . '</div>';
  693. }
  694. if (defined('HTML5MEDIA')) {
  695. if ($this->audioReady($r, true))
  696. $audio = '
  697. <audio id="'.$r->varid.'" class="tzr-audio" '.($options['autoplay'] ? ' autoplay="autoplay"' : '').' controls="controls" height="'.$height.'" width="'.$width.'" style="height:'.$height.'px;width:'.$width.'px" preload="none">
  698. <source src="'.$r->fullaudio_ogg.'" type="audio/ogg" />
  699. <source src="'.$r->fullaudio.'" type="audio/mp3" />
  700. </audio>';
  701. else
  702. $audio = '
  703. <audio id="'.$r->varid.'" class="tzr-audio" '.($options['autoplay'] ? ' autoplay="autoplay"' : '').' controls="controls" height="'.$height.'" width="'.$width.'" style="height:'.$height.'px;width:'.$width.'px">
  704. <source src="'.$r->prehear_ogg.'" type="audio/ogg" />
  705. <source src="'.$r->prehear.'" type="audio/mp3" />
  706. </audio>';
  707. $html = '
  708. <div class="tzr-audio-div">
  709. '.@$img.$audio.'
  710. <script type="text/javascript">
  711. jQuery("#'.$r->varid.'").mediaelementplayer({pluginPath: "'.TZR_SHARE_URL.'js/jmediaelement/build/"});
  712. </script>
  713. </div>';
  714. }
  715. else
  716. $html = @$img.'<div style="height:27px;width:'.$width.'px;"><div id="'.$r->varid.'"></div></div><script type="text/javascript">swfobject.embedSWF("'.TZR_SHARE_URL.'flash/mpw_player.swf","'.$r->varid.'","'.$width.'","27","8","",{mp3:"'.urlencode(($this->audioReady($r,true)?$r->fullaudio:$r->prehear.'&bitrate='.$r->audio_bitrate)).'",autoplay:'.($options['autoplay']?'1':'0').'},{bgcolor:"000000"});</script>';
  717. return $html;
  718. }
  719. /// Determine si le fichier est directement disponible dans la format. Si 'force' a true et fichier non disponible, lance la tache
  720. function audioReady($r, $forceConvert=true){
  721. if(!XFileDef::isAudio($r->mime))
  722. return false;
  723. $ready = true;
  724. $filename_cache = $r->filename.'-'.md5($r->audio_bitrate.'audio/mpeg').'-cache';
  725. if(!file_exists($filename_cache) || (filemtime($r->filename)>filemtime($filename_cache))){
  726. $ready = false;
  727. if($forceConvert){
  728. $ffmpeg = FFMPEG.' -y -i '.$r->filename.' -ab '.$r->audio_bitrate.'k -ar 44100 -f mp3 '.$filename_cache.';';
  729. }
  730. }
  731. if (defined('HTML5MEDIA')) {
  732. $filename_cache=$r->filename.'-'.md5($r->audio_bitrate.'audio/ogg').'-cache';
  733. if(!file_exists($filename_cache) || (filemtime($r->filename)>filemtime($filename_cache))){
  734. $ready = false;
  735. if($forceConvert){
  736. $ffmpeg .= FFMPEG.' -y-i '.$r->filename.' -ab '.$r->audio_bitrate.'k -acodec libvorbis -f ogg '.$filename_cache;
  737. }
  738. }
  739. }
  740. if ($ffmpeg) {
  741. $s=new XModScheduler(array('tplentry'=>TZR_RETURN_DATA));
  742. $s->createIdleShellJob(md5($ffmpeg),'Audio encoding',$ffmpeg,'');
  743. }
  744. return $ready;
  745. }
  746. /// Renvoie la duree d'une video ou d'un audio en secondes
  747. function getDuration($file,$mime){
  748. if(!$file || !file_exists($file)) return 0;
  749. elseif(XFileDef::isVideo($mime) || XFileDef::isAudio($mime)){
  750. $ffmpeg=exec(FFMPEG.' -i '.$file.' 2>&1|grep "Duration"|sed \'s/^.*Duration: \(.*\)\.[0-9],.*$/\1/\'');
  751. if(!empty($ffmpeg)) list($h,$m,$s)=explode(':',$ffmpeg);
  752. else return 0;
  753. if($h && $m && $s) return intval($h)*3600+intval($m)*60+intval($s);
  754. }
  755. return 0;
  756. }
  757. /* PDF */
  758. /// Complete l'objet d'affichage dans le cas d'une image
  759. function displayPDF(&$r,&$value,&$options){
  760. $resizer=$this->getResizer($r->shortfilename,$r->mime,$r->originalname);
  761. if(!empty($resizer) && !empty($resizer['resizer'])) {
  762. $r->resizer=$resizer['resizer'];
  763. $r->weresizer=$resizer['weresizer'];
  764. }
  765. $r->isPDF = true;
  766. $r->html = $r->html_default;
  767. return $r;
  768. }
  769. /// Affichage d'un pdf Calaméo
  770. function displayCalameo(&$r, $value, $options) {
  771. $book_id = substr($r->file, 8);
  772. $params = array(
  773. 'action' => 'API.getBookInfos',
  774. 'apikey' => CALAMEO_PUBLIC_KEY, // a définir dans le local.inc
  775. 'book_id' => $book_id,
  776. 'output' => 'PHP'
  777. );
  778. $url = 'http://api.calameo.com/1.0?';
  779. $signature = CALAMEO_SECRET_KEY; // a définir dans le local.inc
  780. foreach ($params as $key => $value) {
  781. $url .= "$key=$value&";
  782. $signature .= "$key$value";
  783. }
  784. $url .= 'signature=' . md5($signature);
  785. $response = unserialize(file_get_contents($url));
  786. $response = $response['response'];
  787. if ($response['status'] == 'error') {
  788. XLogs::notice(__CLASS__.'::'.__FUNCTION__, "error code {$response['error']['code']}, {$response['error']['message']}");
  789. $r->error = true;
  790. return $r;
  791. }
  792. $r->error = false;
  793. $r->isCalameo = true;
  794. $r->mime = 'application/pdf';
  795. $r->resizer = '';
  796. $r->preview = $response['content']['ThumbUrl'];
  797. $r->title = $response['content']['Name'];
  798. $r->text = $r->title;
  799. $r->externalUrl = $response['content']['ViewUrl'];
  800. $r->downloadUrl = str_replace('read', 'download', $response['content']['ViewUrl']);
  801. $r->fullwidth = $response['content']['Width'];
  802. $r->fullheight = $response['content']['Height'];
  803. $r->dltarget = 'calameo'; // target pour le lien download, si pdf non dispo
  804. $r->html_preview = $this->html_previewCalameo($r, $options);
  805. if ($this->usemimehtml)
  806. $r->html = $this->htmlCalameo($r, $options);
  807. else
  808. $r->html = $r->html_preview;
  809. return $r;
  810. }
  811. /// html preview calaméo
  812. function html_previewCalameo($r, $options=array()) {
  813. if ($r->error)
  814. return '';
  815. if (isset($options['geometry'])) {
  816. list($width, $height) = explode('x', str_replace('>', '', $options['geometry']));
  817. $width = (integer)$width;
  818. $height = (integer)$height;
  819. $ratio = min($width / $r->fullwidth, $height / $r->fullheight);
  820. $width = (integer)($ratio * $r->fullwidth);
  821. $height = (integer)($ratio * $r->fullwidth);
  822. } else {
  823. $width = TZR_THUMB_SIZE;
  824. $height = TZR_THUMB_SIZE;
  825. }
  826. return '<img src="'.$r->preview.'" width="'.$width.'" height="'.$height.'" alt="'.$r->title.'" class="tzr-externalfile" rel="'.$r->file.'">';
  827. }
  828. /// html calaméo
  829. function htmlCalameo($r, $options=array()) {
  830. if ($r->error)
  831. return '';
  832. $geometry = @$options['geometry'] ? $options['geometry'] : $this->image_geometry;
  833. list($width, $height) = explode('x', $geometry);
  834. $width = (integer)$width;
  835. $height = (integer)$height;
  836. return '<iframe id="'.$r->varid.'" src="'.$r->externalUrl.'" wmode="transparent" style="width:'.$width.'px;height:'.$height.'px"></iframe>';
  837. }
  838. /// Tag les valeurs IPTC/XMP d'un fichier via un tableau de donnée
  839. static function setFileMetaWithArray($data,$file,$tmpfile=NULL,$clean=false){
  840. if(empty($file)) return false;
  841. if($tmpfile=='auto'){
  842. $infos=pathinfo($file);
  843. $tmpfile=TZR_TMP_DIR.uniqid('metafile').'.'.$infos['extension'];
  844. copy($file,$tmpfile);
  845. }elseif($tmpfile){
  846. copy($file,$tmpfile);
  847. }else{
  848. $tmpfile=$file;
  849. }
  850. if($clean) XFileDef::cleanFileMeta($tmpfile);
  851. $mimeClasse=XMimeTypes::getInstance();
  852. $mime=$mimeClasse->getValidMime(NULL,$tmpfile,NULL);
  853. if($mime=='image/jpeg'){
  854. $meta=XFileDef::loadMeta($tmpfile);
  855. if(!empty($data['IPTC'])){
  856. foreach($data['IPTC'] as $tag=>$value){
  857. $meta->setIPTCProperty($tag,$value);
  858. }
  859. }
  860. if(!empty($data['XMP'])){
  861. foreach($data['XMP'] as $tag=>$value){
  862. $meta->setXMPProperty($tag,$value);
  863. }
  864. }
  865. $meta->save();
  866. }
  867. return $tmpfile;
  868. }
  869. /// Tag les valeurs IPTC/XMP d'un fichier via un template
  870. static function setFileMetaWithTemplate($tpl,$file,$tmpfile=NULL,$standards=array('IPTC','XMP'),$clean=false){
  871. if(empty($file)) return false;
  872. if($tmpfile=='auto'){
  873. $infos=pathinfo($file);
  874. $tmpfile=TZR_TMP_DIR.uniqid('metafile').'.'.$infos['extension'];
  875. copy($file,$tmpfile);
  876. }elseif($tmpfile){
  877. copy($file,$tmpfile);
  878. }else{
  879. $tmpfile=$file;
  880. }
  881. if($clean) XFileDef::cleanFileMeta($tmpfile);
  882. $mimeClasse=XMimeTypes::getInstance();
  883. $mime=$mimeClasse->getValidMime(NULL,$tmpfile,NULL);
  884. if($mime=='image/jpeg' && !empty($standards)){
  885. $tplmeta=XFileDef::loadMeta($tpl);
  886. $meta=XFileDef::loadMeta($tmpfile);
  887. // Traitement des tags IPTC
  888. if(in_array('IPTC',$standards)){
  889. $tags=$tplmeta->getIPTCAll();
  890. foreach($tags as $tag=>$value){
  891. $meta->setIPTCProperty($value['IPTC_Type'],$value['RecData']);
  892. }
  893. }
  894. // Traitement des tags XMP
  895. if(in_array('XMP',$standards)){
  896. $tags=$tplmeta->xmp_xpath->query($tplmeta->xmp_descr_path.'/'.$tplmeta->xmp_descr_node.'/*');
  897. foreach($tags as $tag){
  898. list($prefix,$foo)=explode(':',$tag->nodeName);
  899. if($prefix!='dc') continue;
  900. $n=$meta->xmp_xpath->query($meta->xmp_descr_path.'/'.$meta->xmp_descr_node.'/'.$tag->nodeName);
  901. if($n->length){
  902. $p=$n->parentNode;
  903. $p->removeChild($n);
  904. }else{
  905. $d=$meta->getXMPDescriptionFromPrefix($prefix);
  906. if(empty($d)) $d=$meta->addXMPDescription($prefix,$tag->parentNode->lookupNamespaceURI($prefix));
  907. $p=$d;
  908. }
  909. $p->appendChild($meta->xmp_dom->importNode($tag,true));
  910. }
  911. }
  912. $meta->save();
  913. }
  914. return $tmpfile;
  915. }
  916. /// Tag les valeurs IPTC/XMP d'un fichier via un display
  917. static function setFileMetaWithDisplay($d,$file,$tmpfile=NULL,$standards=array('IPTC','XMP'),$clean=false){
  918. if(empty($file)) return false;
  919. if($tmpfile=='auto'){
  920. $infos=pathinfo($file);
  921. $tmpfile=TZR_TMP_DIR.uniqid('metafile').'.'.$infos['extension'];
  922. copy($file,$tmpfile);
  923. }elseif($tmpfile){
  924. copy($file,$tmpfile);
  925. }else{
  926. $tmpfile=$file;
  927. }
  928. if($clean) XFileDef::cleanFileMeta($tmpfile);
  929. $mimeClasse=XMimeTypes::getInstance();
  930. $mime=$mimeClasse->getValidMime(NULL,$file,NULL);
  931. if($mime=='image/jpeg' && !empty($standards)){
  932. $meta=XFileDef::loadMeta($tmpfile);
  933. if(!isset($d['fields_object'])){
  934. foreach($d as $i=>&$dd){
  935. foreach($dd['fields_object'] as $i=>&$f){
  936. $fdef=&$f->fielddef;
  937. $fdef->setMetaFromValue($meta,$dd['o'.$fdef->field],$standards);
  938. }
  939. }
  940. }else{
  941. foreach($d['fields_object'] as $i=>&$f){
  942. $fdef=&$f->fielddef;
  943. $fdef->setMetaFromValue($meta,$d['o'.$fdef->field],$standards);
  944. }
  945. }
  946. $meta->save();
  947. }
  948. return $tmpfile;
  949. }
  950. /// Nettoie tous les metas d'un fichier
  951. static function cleanFileMeta($file){
  952. $mimeClasse=XMimeTypes::getInstance();
  953. $mime=$mimeClasse->getValidMime(NULL,$file,NULL);
  954. if($mime=='image/jpeg'){
  955. system(TZR_MOGRIFY_RESIZER.' +profile "*" '.$file.' '.$file.';'. TZR_MOGRIFY_RESIZER.' +profile "*" '.$file.'_ld '.$file.'_ld');
  956. }
  957. }
  958. // generation du nom du fichier
  959. //
  960. function filename($value,$test=false,$testfinal=false,$secondaryroot=NULL) {
  961. global $DATA_DIR;
  962. $ar=NULL;
  963. if($value=='') return NULL;
  964. if($value==TZR_UNCHANGED) return NULL;
  965. $langdata = XShell::getLangData();
  966. @list($file,$mime,$originalname) = @explode(';',$value);
  967. if($file=='') return NULL;
  968. if($test) $this->_checkDir();
  969. umask(0000);
  970. $root=$this->table;
  971. if(!empty($secondaryroot)) {
  972. $root='A_'.$this->table.'/'.$secondaryroot;
  973. }
  974. $root.='/'.$this->field;
  975. $subdir=md5($file);
  976. while(strlen($subdir)>=16) {
  977. $tmp=substr($subdir,0,2);
  978. $root.='/'.$tmp;
  979. $subdir=substr($subdir,16);
  980. }
  981. if($test) XDir::mkdir($DATA_DIR.$root, false);
  982. $filename=$root.'/'.$file;
  983. if($test || $testfinal) {
  984. if(file_exists($DATA_DIR.$filename)) {
  985. $ar=$filename;
  986. } elseif($test) {
  987. $ar=NULL;
  988. }
  989. } else {
  990. $ar=$filename;
  991. }
  992. return $ar;
  993. }
  994. /// Generation du champ pour modification du fichier
  995. function my_edit(&$value,&$options) {
  996. $lang = XShell::getLangUser();
  997. $r=$this->_newXFieldVal($options,true);
  998. if(isset($options['intable'])) {
  999. return $r;
  1000. $o = $options['intable'];
  1001. $fname=$this->field.'['.$o.']';
  1002. $hiddenname=$this->field.'_HID['.$o.']';
  1003. } elseif(!empty($options['fieldname'])) {
  1004. $fname=$options['fieldname'];
  1005. $hiddenname=$options['fieldname'].'_HID';
  1006. } else {
  1007. $fname=$this->field;
  1008. $hiddenname=$this->field.'_HID';
  1009. }
  1010. $r->raw=$value;
  1011. $this->_checkDir();
  1012. $varid=$r->varid;
  1013. $disp=$this->my_display($value,$options);
  1014. // Titre à part
  1015. $txt='<table class="tzr-xfiledef"><tr>';
  1016. if($this->usealt)
  1017. $txt.='<td><label>'.XLabels::getSysLabel('general','title','text').'</label></td><td id="'.$varid.'-tdtitle"><input type="text" name="'.$fname.'_title" value="'.$disp->title.'"/></td></tr><tr><td><label>'.XLabels::getSysLabel('xfielddef','xfiledef','text').'</label></td>';
  1018. // Input fichier + bouton parcourir console
  1019. $txt.='<td id="'.$varid.'-tdfile"'.($disp->isExternal?' style="display:none"':'').'><input type="file" name="'.$fname.'" accept="'.$this->accept.'"'.(!empty($this->maxlength)?' maxlength="'.$this->maxlength.'"':'').' id="'.$varid.'"><br/>';
  1020. if(XShell::admini_mode() && $this->browsemods) {
  1021. $url=$GLOBALS['TZR_SESSION_MANAGER']::complete_self().'moid='.XModule::getMoid(XMODADMIN_TOID).'&function=modulesList&tplentry=br&_nonav=1&_nohistory=1&template=basic/source-file.html'.
  1022. '&skip=1&ajaxurl='.rawurlencode($GLOBALS['TZR_SESSION_MANAGER']::complete_self().'&function=browseFiles&tplentry=br&template=basic/source-file-ajax.html'.
  1023. '&pagesize=20&skip=1&recipientid='.$varid.'&_nonav=1&_nohistory=1&selectedprops[published]=1'.
  1024. '&selectedtypes[]=XFileDef&selectedtypes[]=XFolderDef&selectedop=OR');
  1025. if($this->sourcemodule) $url.='&toid=xx&ajaxmoid='.$this->sourcemodule;
  1026. else $url.='&toid[]=25&toid[]=8001';
  1027. $txt.='<input type="button" value="'.XLabels::getSysLabel('xmodule','browsemods','text').'" onclick="window.open(\''.$url.'\',\'\',\'width=655,height=550,menubar=0,resizable=1,scrollbars=1\');">';
  1028. }
  1029. // Fichier externe
  1030. if ($this->allow_externalfile) {
  1031. $txt .= '<input type="button" value="'.XLabels::getSysLabel('xfielddef','externalfile').'" onclick="jQuery(\'#'.$r->varid.'-tdfile, #'.$r->varid.'-tdexternal, #'.$r->varid.'-trcancel\').toggle()">';
  1032. }
  1033. $txt.='</td>';
  1034. if (XShell::admini_mode() && $this->browsemods) {
  1035. $txt .= '<td id="'.$r->varid.'-tdbrowsemods"></td>';
  1036. }
  1037. if ($this->allow_externalfile) {
  1038. $txt .= '<td id="'.$r->varid.'-tdexternal"'.($disp->isExternal?'':' style="display:none"').'>'.XLabels::getSysLabel('xfielddef','externalfile').' : <input type="text" id="'.$r->varid.'-external" value="'.$disp->externalUrl.'" name="'.$hiddenname.'[external]" size="50" maxsize="200"/></td>';
  1039. }
  1040. $txt.='</tr>';
  1041. if (XShell::admini_mode() && $this->browsemods || $this->allow_externalfile) {
  1042. $txt.='<tr '.($disp->isExternal?'':' style="display:none"').' id="'.$r->varid.'-trcancel"><td colspan="4"><input type="button" value="'.XLabels::getSysLabel('general','cancel').'" onclick="jQuery(\'#'.$r->varid.'-tdexternal,#'.$r->varid.'-trcancel\').hide();jQuery(\'#'.$r->varid.'-tdbrowsemods\').html(\'\').hide();jQuery(\'#'.$r->varid.'-tdfile\').show();jQuery(\'#'.$r->varid.'-from, #'.$r->varid.'-external\').val(\'\')"></td></tr>';
  1043. }
  1044. $txt.='</tr></table>';
  1045. $txt.='<input type="hidden" id="'.$r->varid.'-old" name="'.$hiddenname.'[old]" value="'.$value.'"/>';
  1046. $txt.='<input id="'.$varid.'-from" type="hidden" name="'.$hiddenname.'[from]" value=""/>';
  1047. // Bouton de supression
  1048. if($disp->html!='' && !$this->compulsory)
  1049. $txt.=' '.XLabels::getSysLabel('xfielddef','detach_file').' : <input type="checkbox" name="'.$fname.'_del" class="checkbox"/><br/>';
  1050. if ($this->compulsory) {
  1051. $txt .= '<script type="text/javascript">TZR.addValidator(["'.$r->varid.'","","'.addslashes($this->label).'","'.XIni::get('error_color').'","XFileDef","","'.$this->browsemods.'","'.$this->allow_externalfile.'"]);</script>';
  1052. }
  1053. $r->html=$txt;
  1054. $r->originalname=$disp->originalname;
  1055. $r->filename=$disp->filename;
  1056. $r->mime=$disp->mime;
  1057. if(XFileDef::isImage($r->mime) || get_class($this)=='XImageDef')
  1058. $this->editImage($r,$value,$options,$disp,$fname,$hiddenname);
  1059. elseif($disp->mime=='text/html' || $disp->mime=='text/plain')
  1060. $this->editHTML($r,$value,$options,$disp,$fname,$hiddenname);
  1061. else
  1062. $r->html .= $disp->html_preview;
  1063. return $r;
  1064. }
  1065. /// Complete l'objet d'edition dans le cas d'une image
  1066. function editImage(&$r,&$value,&$options,&$disp,$fname,$hiddenname){
  1067. $r->isImage=true;
  1068. if(!empty($this->image_crop_ratio)){
  1069. $r->html.='<div id="'.$r->varid.'-cropinfo" class="tzr-xfiledef-cropinfo"><a href="#" onclick="return false;">'.XLabels::getSysLabel('xfielddef','image_crop').'</a></div>';
  1070. $r->html.='<script type="text/javascript">TZR.Image.activeCrop(\''.$r->varid.'\',\''.$this->image_crop_ratio.'\');</script>';
  1071. }
  1072. if($disp->html){
  1073. $px=' '.XLabels::getSysLabel('general','pixels','text');
  1074. $r->html='<table><tr><td colspan="2">'.$r->html.'</td></tr><tr><td><img src="'.$disp->resizer.'&geometry='.TZR_THUMB_SIZE.'x'.TZR_THUMB_SIZE.'%3E"></td><td>'.
  1075. $disp->html_default.'<br>'.
  1076. XLabels::getSysLabel('xfielddef','file_size').' : '.round($this->getFileSize($r)/1024).' Ko<br>'.
  1077. XLabels::getSysLabel('general','width','text').' : '.$this->getImageSize($r,'fullwidth').$px.'<br>'.
  1078. XLabels::getSysLabel('general','height','text').' : '.$this->getImageSize($r,'fullheight').$px.
  1079. '</td></tr></table>';
  1080. }
  1081. }
  1082. /// Complete l'objet d'édition dans le cas d'un fichier HTML
  1083. function editHTML(&$r,&$value,&$options,&$disp,$fname,$hiddenname){
  1084. if($options['fmoid']){
  1085. $edition='';
  1086. $tmpname=md5(session_id().$disp->table.$disp->field.$options['oid']);
  1087. copy($disp->filename, TZR_TMP_DIR.$tmpname);
  1088. $dla=$this->getDownloader($tmpname, $disp->mime, $disp->originalname, $disp->originalname, $options['fmoid']);
  1089. $dl=$dla[0].'&tmp=1&disp=inline';
  1090. $url=$GLOBALS['TZR_SESSION_MANAGER']::complete_self(true,true).'&function=edit&selectedfields[]='.$this->field.'&moid='.$options['fmoid'].'&template=popfileedit.html&field='.$this->field.'&tplentry=br&oid='.$options['oid'];
  1091. $upl=TZR_FILE_EDITOR_UPLOADER.'?moid='.$options['fmoid'].'&table='.$disp->table.'&field='.$disp->field.'&oid='.$options['oid'].'&moid='.$options['fmoid'];
  1092. $edition.='<input type="hidden" name="'.$hiddenname.'[editflag]" value="no"/>';
  1093. $edition.=' <a href="#" onclick="TZR.openhtmlfileeditor({uniqid:\''.XShell::uniqid().'\',url:\''.$url.'\',uploader:\''.$upl.'\', editflag:\''.$hiddenname.'[editflag]\'}); return false;">'.XLabels::getSysLabel('general','edit','text').'</a>';
  1094. $r->html.=$disp->html.$edition;
  1095. }else{
  1096. $r->html.=$disp->html;
  1097. }
  1098. }
  1099. function sqltype() {
  1100. return 'varchar(200)';
  1101. }
  1102. /// Suppression de la donnee
  1103. function delete($value, $oid) {
  1104. global $DATA_DIR;
  1105. $langdata = XShell::getLangData();
  1106. // calcul du nom du fichier associe
  1107. $filename= $this->filename($value,true);
  1108. if($filename) {
  1109. if(file_exists($DATA_DIR.$filename)) {
  1110. XLogs::debug('[XFileDef::delete]unlink('.$DATA_DIR.$filename.')');
  1111. @unlink($DATA_DIR.$filename);
  1112. }
  1113. }
  1114. return 1;
  1115. }
  1116. function post_edit($value,$options) {
  1117. global $DATA_DIR;
  1118. $p=new XParam($options,array('del'=>true));
  1119. $r=$this->_newXFieldVal($options);
  1120. $langdata=XShell::getLangData();
  1121. $hidden=$options[$this->field.'_HID'];
  1122. $del=$p->get('del');
  1123. $mimeClasse=XMimeTypes::getInstance();
  1124. // Verification que les repertoires existent
  1125. $oid=$p->get(

Large files files are truncated, but you can click here to view the full file