use_exiftool = $use_exiftool_p;
$this->use_exiv2 = $use_exiv2_p;
$this->use_whole_desc = $use_whole_desc_p;
$this->isMSWin = stristr(php_uname(), 'windows');
$this->eol = $this->isMSWin ? "\r\n" : "\n";
$this->useUTF8_txt = $useUTF8_txt; // encoding of the batch file
$this->useUTF8_cp = false; // pb under windows xp for the author with this code page...
}
public function set_test_mode($test_mode, $test_img_id)
{
$this->isTest = $test_mode;
$this->test_img_id = $test_img_id;
}
public function set_tool_pathes($exiftoolPath, $exiv2path)
{
if ($this->use_exiftool)
{
$this->exiftoolDefaultCmd = $this->init_exif_tool_cmd_name($exiftoolPath, "exiftool");
if ($this->useUTF8_txt) {
$this->exiftoolDefaultCmd .= " -IPTC:CodedCharacterSet=UTF8";
}
else {
$this->exiftoolDefaultCmd .= " -L"; // convert to Latin1 internaly, see FAQ #10 at http://www.sno.phy.queensu.ca/~phil/exiftool/faq.html
}
$this->exiftoolDefaultCmd .= " -overwrite_original"; // no backup!
}
if ($this->use_exiv2)
{
$this->exiv2DefaultCmd = $this->init_exif_tool_cmd_name($exiv2path, "exiv2");
$this->exiv2DefaultCmd .= " -k"; // conserve original date
}
}
private function init_exif_tool_cmd_name($toolPath, $toolName)
{
return (file_exists($toolPath) && strpos(strtolower($toolPath), strtolower($toolName)) !== false) ? "\"".realpath($toolPath)."\"" : $toolName;
}
public function image_properties_to_file($destPath)
{
$exiftoolScript = ""; $exiv2Script = "";
if ($this->use_exiftool)
{
$exiftoolScript = $destPath ."/writeTagsToIptcWithExifTool.cmd";
$fp_exiftool = $this->open_create_file($exiftoolScript);
}
if ($this->use_exiv2)
{
$exiv2Script = $destPath ."/writeTagsToIptcWithExiv2.cmd";
$fp_exiv2 = $this->open_create_file($exiv2Script);
}
$datas = $this->get_image_properties();
$this->nbfiles = 0;
while ($row = mysql_fetch_row($datas)) // row to avoid conflict with name
{
$image_path = $row[5];
$has_high = $row[6] === 'true';
if ($this->isTest || file_exists($image_path))
{
if ($this->use_exiftool)
{
$cmd = $this->convert_row_to_file_exiftool($row);
$this->write_exifCmd($cmd, $image_path, $has_high, $fp_exiftool);
}
if ($this->use_exiv2)
{
$cmd = $this->convert_row_to_file_exiv2($row);
$this->write_exifCmd($cmd, $image_path, $has_high, $fp_exiv2);
}
}
}
if ($this->use_exiftool && isset($fp_exiftool))
{
$this->close_file($fp_exiftool);
}
if ($this->use_exiv2 && isset($fp_exiv2))
{
$this->close_file($fp_exiv2);
}
if ($this->use_exiftool && $this->use_exiv2)
{
$this->nbfiles = $this->nbfiles / 2; // each picture counted twice
}
return $this->nbfiles; // incremented by write_exifCmd
}
// IO function
private function open_create_file($destPath)
{
// prepare output file
if(file_exists($destPath))
{
if (!$this->isMSWin) chmod($destPath, 0777);
unlink($destPath);
}
touch($destPath);
$fp = fopen($destPath,"w");
if ($this->isMSWin && isset($fp) )
{
// the default command prompt is stupid and won't display the correct character set, so we need to change the code page
if ($this->useUTF8_cp)
{ 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
else
{ fwrite($fp, "chcp 1252".$this->eol); } // default Windows Latin1
}
return $fp;
}
private function close_file($fp)
{
if (isset($fp))
{
if ($this->nbfiles > 0)
{
fwrite($fp, $this->eol);
}
fclose($fp);
}
}
// prepare data for script
private function convert_row_to_file_exiv2($row)
{
if (!$this->use_exiv2)
return "exiv2 shall not be used";
$name = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[0], true)), 256);
$description = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[1], true)), 2000);
$author = $this->cutString($this->decode_html_string_to_unicode($row[2], true), 32);
//$date_creation = $this->decode_html_string_to_unicode($row[3], true);
$tags = $this->cutString($this->decode_html_string_to_unicode($row[4], true), 64);
$image_path = $row[5];
$has_high = $row[6] === 'true';
$exiv2Cmd = $this->exiv2DefaultCmd;
if (strlen($name) > 0)
{
$exiv2Cmd .= " -M\"set Iptc.Application2.Headline ".$name."\"";
$exiv2Cmd .= " -M\"set Iptc.Application2.ObjectName ". $this->cutString($name, 64)."\"";
}
if (strlen($description) > 0)
{
$exiv2Cmd .= " -M\"set Iptc.Application2.Caption ".$description."\"";
}
if (strlen($author) > 0)
{
$exiv2Cmd .= " -M\"set Iptc.Application2.Writer ".$author."\"";
}
if (strlen($tags) > 0)
{
$exiv2Cmd .= " -M\"add Iptc.Application2.Keywords ".$tags."\"";
}
return $exiv2Cmd;
}
private function convert_row_to_file_exiftool($row)
{
if (!$this->use_exiftool)
return "exiftool shall not be used";
$name = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[0], false)), 256);
$description = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[1], false)), 2000);
$author = $this->cutString($this->decode_html_string_to_unicode($row[2], false), 32);
//$date_creation = $this->decode_html_string_to_unicode($row[3], false);
$tags = $this->cutString($this->decode_html_string_to_unicode($row[4], false), 64);
$exiftoolCmd = $this->exiftoolDefaultCmd;
// exiftool allow to set a field only if the field in the original file is empty
// as explained here: http://www.cpanforum.com/posts/10765
if (strlen($name) > 0)
{
$exiftoolCmd .= " -IPTC:Headline-= -IPTC:Headline=\"".$name."\"";
$exiftoolCmd .= " -IPTC:ObjectName-= -IPTC:ObjectName=\"".$this->cutString($name, 64)."\"";
}
if (strlen($description) > 0)
{
$exiftoolCmd .= " -IPTC:Caption-Abstract-= -IPTC:Caption-Abstract=\"".$description."\"";
}
if (strlen($author) > 0)
{
$exiftoolCmd .= " -IPTC:Writer-Editor-= -IPTC:Writer-Editor=\"".$author."\"";
}
if (strlen($tags) > 0)
{ // Keywords are overwritten, since they allow multiple entries, with "-=", given keywords will be added to the existing
$exiftoolCmd .= " -IPTC:Keywords=\"".$tags."\"";
}
return $exiftoolCmd;
}
private function write_exifCmd($exifCmd, $image_path, $has_high, $fp)
{
$exifCmdN = $exifCmd ." ";
$exifCmdN .= $this->isTest ? $image_path : realpath(PHPWG_ROOT_PATH.$image_path);
$writeOK = fwrite($fp, $exifCmdN.$this->eol) !== FALSE;
if ($writeOK) $this->nbfiles++;
if ($has_high)
{
$imageHigh = dirname($image_path) . "/pwg_high/" . basename($image_path);
if (file_exists($imageHigh))
{ $this->write_exifCmd($exifCmd, $imageHigh, false, $fp); }
}
}
// html function
private function decode_html_string_to_unicode($string, $forceANSI)
{
if (isset($string) && strlen($string) > 0)
{
$txt_encoding = ($this->useUTF8_txt && !$forceANSI) ? 'UTF-8' : 'ISO-8859-15';
$string = html_entity_decode(trim($string), ENT_QUOTES, $txt_encoding);
$string = stripslashes($string);
}
else $string = "";
return($string);
}
// remove end of line char from desc and keep if required only the current language
private function explode_description($description)
{
if (!$this->use_whole_desc)
{
$description = $this->get_user_language_desc($description);
}
return str_replace( array( '
', '
', "\n", "\r" ), array('', '', '', ''), $description );
}
private function cutString($description, $maxLen)
{
if (strlen($description) > $maxLen)
{
$description = substr($description, 0, $maxLen);
}
return $description;
}
// Traite les balises [lang=xx], copy&paste from ExtendedDescription plugin, main.inc.php
private function get_user_language_desc($desc)
{
global $user;
$user_lang = substr($user['language'], 0, 2);
if (!substr_count(strtolower($desc), '[lang=' . $user_lang . ']'))
{
$user_lang = 'default';
}
if (substr_count(strtolower($desc), '[lang=' . $user_lang . ']'))
{
// la balise avec la langue de l'utilisateur a été trouvée
$patterns[] = '#(^|\[/lang\])(.*?)(\[lang=(' . $user_lang . '|all)\]|$)#is';
$replacements[] = '';
$patterns[] = '#\[lang=(' . $user_lang . '|all)\](.*?)\[/lang\]#is';
$replacements[] = '\\1';
}
else
{
// la balise avec la langue de l'utilisateur n'a pas été trouvée
// On prend tout ce qui est hors balise
$patterns[] = '#\[lang=all\](.*?)\[/lang\]#is';
$replacements[] = '\\1';
$patterns[] = '#\[lang=.*\].*\[/lang\]#is';
$replacements[] = '';
}
return preg_replace($patterns, $replacements, $desc);
}
// data access
private function get_image_properties()
{
$query_path = $this->isTest ? 'img.file' : 'img.path';
$query_restriction = $this->isTest ? 'AND (img.id = '.$this->test_img_id.'))' : ')';
// get direct properties and tags, even if no tags, with either name, comment or tags not null
// restritive query with image.ID for tests with copied images with file instead of path
$img_query = 'SELECT img.name, img.comment, img.author, img.date_creation, GROUP_CONCAT(tags.name), '.$query_path.', has_high
FROM '.IMAGES_TABLE.' AS img
LEFT OUTER JOIN '.IMAGE_TAG_TABLE.' AS img_tag ON img_tag.image_id = img.id
LEFT OUTER JOIN '.TAGS_TABLE.' AS tags ON tags.id = img_tag.tag_id
WHERE ( ( LENGTH(img.name) > 0 OR LENGTH(img.comment) > 0 OR LENGTH(img.author) > 0 OR LENGTH(tags.name) > 0 ) '.$query_restriction.'
GROUP BY img.id, img.name, img.comment, img.author, '.$query_path.', has_high
ORDER BY img.id ASC; ';
return pwg_query($img_query);
}
}