source: extensions/Tags2File/db_export_image_metadata_class.php @ 15907

Last change on this file since 15907 was 4620, checked in by Gotcha, 14 years ago

[Plugin] Tag2File - Last revision from author Eric B.

File size: 11.7 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Plugin Name : Export Image metadata                                   |
4// | Plugin Version : 0.1                                                  |
5// | Plugin Author: Eric                                                   |
6// | Plugin Description :                                                  |
7// | Ce module est base sur le module existant pour le telechargement,     |
8// | cette version permet le telechargement sur plusieurs pages.           |
9// +-----------------------------------------------------------------------+
10// | This program is free software; you can redistribute it and/or modify  |
11// | it under the terms of the GNU General Public License as published by  |
12// | the Free Software Foundation                                          |
13// |                                                                       |
14// | This program is distributed in the hope that it will be useful, but   |
15// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
16// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
17// | General Public License for more details.                              |
18// |                                                                       |
19// | You should have received a copy of the GNU General Public License     |
20// | along with this program; if not, write to the Free Software           |
21// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
22// | USA.               '                                                  |
23// +-----------------------------------------------------------------------+
24
25class ExportImageMetadata
26{
27  private $use_exiftool, $use_exiv2, $use_whole_desc, $isMSWin, $useUTF8_txt, $useUTF8_cp, $eol;
28  private $exiftoolDefaultCmd, $exiv2DefaultCmd, $nbfiles;
29  private $isTest = false, $test_img_id; 
30
31  function ExportImageMetadata($use_exiftool_p, $use_exiv2_p, $use_whole_desc_p, $useUTF8_txt)
32  {
33        $this->use_exiftool = $use_exiftool_p;
34        $this->use_exiv2 = $use_exiv2_p;
35        $this->use_whole_desc = $use_whole_desc_p;
36        $this->isMSWin = stristr(php_uname(), 'windows');
37        $this->eol = $this->isMSWin ? "\r\n" : "\n";
38        $this->useUTF8_txt = $useUTF8_txt; // encoding of the batch file
39        $this->useUTF8_cp = false; // pb under windows xp for the author with this code page...
40  }
41
42  public function set_test_mode($test_mode, $test_img_id)
43  {
44          $this->isTest = $test_mode;
45          $this->test_img_id = $test_img_id;
46  }
47
48  public function set_tool_pathes($exiftoolPath, $exiv2path)
49  {
50        if ($this->use_exiftool)
51        {
52                $this->exiftoolDefaultCmd = $this->init_exif_tool_cmd_name($exiftoolPath, "exiftool");
53                if ($this->useUTF8_txt) {
54                        $this->exiftoolDefaultCmd .= " -IPTC:CodedCharacterSet=UTF8";
55                }
56                else {
57                        $this->exiftoolDefaultCmd .= " -L"; // convert to Latin1 internaly, see FAQ #10 at http://www.sno.phy.queensu.ca/~phil/exiftool/faq.html
58                }
59                $this->exiftoolDefaultCmd .= " -overwrite_original"; // no backup!
60        }
61        if ($this->use_exiv2)
62        {
63                $this->exiv2DefaultCmd = $this->init_exif_tool_cmd_name($exiv2path, "exiv2");
64                $this->exiv2DefaultCmd .= " -k"; // conserve original date
65        }
66  }
67
68  private function init_exif_tool_cmd_name($toolPath, $toolName)
69  {
70        return (file_exists($toolPath) && strpos(strtolower($toolPath), strtolower($toolName)) !== false) ? "\"".realpath($toolPath)."\"" : $toolName;
71  }
72
73  public function image_properties_to_file($destPath)
74  {             
75        $exiftoolScript = ""; $exiv2Script = "";
76        if ($this->use_exiftool)
77        {
78                $exiftoolScript = $destPath ."/writeTagsToIptcWithExifTool.cmd";
79                $fp_exiftool = $this->open_create_file($exiftoolScript);
80        }
81        if ($this->use_exiv2)
82        {
83                $exiv2Script = $destPath ."/writeTagsToIptcWithExiv2.cmd";
84                $fp_exiv2 = $this->open_create_file($exiv2Script);
85        }
86
87        $datas = $this->get_image_properties();
88        $this->nbfiles = 0;
89
90        while ($row = mysql_fetch_row($datas)) // row to avoid conflict with name
91        {               
92                $image_path = $row[5];
93                $has_high = $row[6] === 'true';
94               
95                if ($this->isTest || file_exists($image_path))
96                {
97                        if ($this->use_exiftool)
98                        {
99                                $cmd = $this->convert_row_to_file_exiftool($row);
100                                $this->write_exifCmd($cmd, $image_path, $has_high, $fp_exiftool);
101                        }
102                        if ($this->use_exiv2)
103                        {
104                                $cmd = $this->convert_row_to_file_exiv2($row);
105                                $this->write_exifCmd($cmd, $image_path, $has_high, $fp_exiv2);
106                        }
107                }
108        }
109
110        if ($this->use_exiftool && isset($fp_exiftool))
111        {
112                $this->close_file($fp_exiftool);
113        }
114        if ($this->use_exiv2 && isset($fp_exiv2))
115        {
116                $this->close_file($fp_exiv2);
117        }
118        if ($this->use_exiftool && $this->use_exiv2)
119        {
120                $this->nbfiles = $this->nbfiles / 2; // each picture counted twice
121        }
122
123        return $this->nbfiles; // incremented by write_exifCmd
124  }
125
126  // IO function
127  private function open_create_file($destPath)
128  {
129        // prepare output file
130        if(file_exists($destPath))
131        {
132                if (!$this->isMSWin) chmod($destPath, 0777);
133                unlink($destPath);
134        }
135        touch($destPath);
136        $fp = fopen($destPath,"w"); 
137        if ($this->isMSWin && isset($fp) )
138        {
139                // the default command prompt is stupid and won't display the correct character set, so we need to change the code page
140                if ($this->useUTF8_cp)
141                { fwrite($fp, "chcp 65001".$this->eol); } // UTF-8, prevent cmd to work, see perhaps http://blogs.msdn.com/michkap/archive/2006/03/06/544251.aspx
142                else
143                { fwrite($fp, "chcp 1252".$this->eol); }  // default Windows Latin1             
144        }
145        return $fp;
146  }
147
148  private function close_file($fp)
149  {
150        if (isset($fp))
151        {
152                if ($this->nbfiles > 0)
153                {
154                        fwrite($fp, $this->eol);
155                }
156                fclose($fp);
157        }
158  }
159
160  // prepare data for script
161  private function convert_row_to_file_exiv2($row)
162  {
163        if (!$this->use_exiv2)
164                return "exiv2 shall not be used";
165        $name =  $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[0], true)), 256);
166        $description = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[1], true)), 2000);
167        $author = $this->cutString($this->decode_html_string_to_unicode($row[2], true), 32);
168        //$date_creation = $this->decode_html_string_to_unicode($row[3], true);
169        $tags = $this->cutString($this->decode_html_string_to_unicode($row[4], true), 64);
170        $image_path = $row[5];
171        $has_high = $row[6] === 'true';
172       
173        $exiv2Cmd = $this->exiv2DefaultCmd;
174
175        if (strlen($name) > 0)
176        {
177                $exiv2Cmd .= " -M\"set Iptc.Application2.Headline ".$name."\"";
178                $exiv2Cmd .= " -M\"set Iptc.Application2.ObjectName ". $this->cutString($name, 64)."\"";
179        }
180        if (strlen($description) > 0)
181        {                                                       
182                $exiv2Cmd .= " -M\"set Iptc.Application2.Caption ".$description."\"";
183        }
184        if (strlen($author) > 0)
185        {
186                $exiv2Cmd .= " -M\"set Iptc.Application2.Writer ".$author."\"";
187        }       
188        if (strlen($tags) > 0)                 
189        {
190                $exiv2Cmd .= " -M\"add Iptc.Application2.Keywords ".$tags."\"";
191        }
192        return $exiv2Cmd;
193  }
194
195  private function convert_row_to_file_exiftool($row)
196  {
197        if (!$this->use_exiftool)
198                return "exiftool shall not be used";
199        $name = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[0], false)), 256);
200        $description = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[1], false)), 2000);
201        $author = $this->cutString($this->decode_html_string_to_unicode($row[2], false), 32);
202        //$date_creation = $this->decode_html_string_to_unicode($row[3], false);
203        $tags = $this->cutString($this->decode_html_string_to_unicode($row[4], false), 64);
204
205        $exiftoolCmd = $this->exiftoolDefaultCmd;       
206
207        // exiftool allow to set a field only if the field in the original file is empty
208        // as explained here: http://www.cpanforum.com/posts/10765
209
210        if (strlen($name) > 0)
211        {
212                $exiftoolCmd .= " -IPTC:Headline-= -IPTC:Headline=\"".$name."\"";
213                $exiftoolCmd .= " -IPTC:ObjectName-= -IPTC:ObjectName=\"".$this->cutString($name, 64)."\"";
214        }
215        if (strlen($description) > 0)
216        {                                                       
217                $exiftoolCmd .= " -IPTC:Caption-Abstract-= -IPTC:Caption-Abstract=\"".$description."\"";
218        }
219        if (strlen($author) > 0)
220        {
221                $exiftoolCmd .= " -IPTC:Writer-Editor-= -IPTC:Writer-Editor=\"".$author."\"";
222        }       
223        if (strlen($tags) > 0)                 
224        { // Keywords are overwritten, since they allow multiple entries, with "-=", given keywords will be added to the existing
225                $exiftoolCmd .= " -IPTC:Keywords=\"".$tags."\"";
226        }
227        return $exiftoolCmd;   
228  }
229
230  private function write_exifCmd($exifCmd, $image_path, $has_high, $fp)
231  {
232        $exifCmdN = $exifCmd ." ";
233        $exifCmdN .= $this->isTest ? $image_path : realpath(PHPWG_ROOT_PATH.$image_path);
234        $writeOK = fwrite($fp, $exifCmdN.$this->eol) !== FALSE;
235        if ($writeOK)  $this->nbfiles++;
236
237        if ($has_high)
238        {
239                $imageHigh = dirname($image_path) . "/pwg_high/" . basename($image_path);
240                if (file_exists($imageHigh)) 
241                {       $this->write_exifCmd($exifCmd, $imageHigh, false, $fp);  }
242        }
243  }
244
245  // html function
246  private function decode_html_string_to_unicode($string, $forceANSI) 
247  {
248        if (isset($string) && strlen($string) > 0)
249        {
250                $txt_encoding = ($this->useUTF8_txt && !$forceANSI) ? 'UTF-8' : 'ISO-8859-15';
251                $string = html_entity_decode(trim($string), ENT_QUOTES, $txt_encoding);
252                $string = stripslashes($string);
253        }
254        else $string = "";
255        return($string);
256  } 
257
258    // remove end of line char from desc and keep if required only the current language
259  private function explode_description($description)
260  {
261        if (!$this->use_whole_desc)
262        {
263                $description = $this->get_user_language_desc($description);     
264        }
265        return str_replace( array( '<br>', '<br />', "\n", "\r" ), array('', '', '', ''), $description );
266  }
267
268  private function cutString($description, $maxLen)
269  {
270        if (strlen($description) > $maxLen)
271        {
272                $description = substr($description, 0, $maxLen);
273        }
274        return $description;
275  }
276 
277  // Traite les balises [lang=xx], copy&paste from ExtendedDescription plugin, main.inc.php
278  private function get_user_language_desc($desc)
279  {
280        global $user;
281 
282        $user_lang = substr($user['language'], 0, 2);
283
284        if (!substr_count(strtolower($desc), '[lang=' . $user_lang . ']'))
285        {
286                $user_lang = 'default';
287        }
288 
289        if (substr_count(strtolower($desc), '[lang=' . $user_lang . ']'))
290        {
291                // la balise avec la langue de l'utilisateur a été trouvée
292                $patterns[] = '#(^|\[/lang\])(.*?)(\[lang=(' . $user_lang . '|all)\]|$)#is';
293                $replacements[] = '';
294                $patterns[] = '#\[lang=(' . $user_lang . '|all)\](.*?)\[/lang\]#is';
295                $replacements[] = '\\1';
296        }
297        else
298        {
299                // la balise avec la langue de l'utilisateur n'a pas été trouvée
300                // On prend tout ce qui est hors balise
301                $patterns[] = '#\[lang=all\](.*?)\[/lang\]#is';
302                $replacements[] = '\\1';
303                $patterns[] = '#\[lang=.*\].*\[/lang\]#is';
304                $replacements[] = '';
305        }
306        return preg_replace($patterns, $replacements, $desc);
307  }
308
309  // data access
310  private function get_image_properties() 
311  {
312        $query_path = $this->isTest ? 'img.file' : 'img.path';
313        $query_restriction = $this->isTest ? 'AND (img.id = '.$this->test_img_id.'))' : ')';
314        // get direct properties and tags, even if no tags, with either name, comment or tags not null
315        // restritive query with image.ID for tests with copied images with file instead of path
316        $img_query = 'SELECT img.name, img.comment, img.author, img.date_creation, GROUP_CONCAT(tags.name), '.$query_path.', has_high
317                FROM '.IMAGES_TABLE.' AS img
318                LEFT OUTER JOIN '.IMAGE_TAG_TABLE.' AS img_tag ON img_tag.image_id = img.id
319                LEFT OUTER JOIN '.TAGS_TABLE.' AS tags ON tags.id = img_tag.tag_id
320                WHERE ( ( LENGTH(img.name) > 0 OR LENGTH(img.comment) > 0 OR LENGTH(img.author) > 0 OR LENGTH(tags.name) > 0 ) '.$query_restriction.'
321                GROUP BY img.id, img.name, img.comment, img.author, '.$query_path.', has_high
322                ORDER BY img.id ASC; ';
323       
324        return pwg_query($img_query);
325  }
326}
Note: See TracBrowser for help on using the repository browser.