Collections functions
General functions
Node functions
Render functions
Theme permission functions
User functions
Resource functions

write_metadata()

Parameters

ColumnTypeDefaultDescription
$path
$ref
$uniqid ""

Location

include/resource_functions.php lines 4513 to 4702

Definition

 
function write_metadata($path$ref$uniqid="")
    {
    
debug_function_call('write_metadata'func_get_args());
    
// copys the file to tmp and runs exiftool on it
    // uniqid tells the tmp file to be placed in an isolated folder within tmp
    
global $exiftool_remove_existing$storagedir$exiftool_write$exiftool_write_option$exiftool_no_process$mysql_charset$exiftool_write_omit_utf8_conversion;

    
# Fetch file extension and resource type.
    
$resource_data=get_resource_data($ref);
    
$extension=$resource_data["file_extension"];

    
$exiftool_fullpath get_utility_path("exiftool");

    
# Check if an attempt to write the metadata shall be performed.
    
if(false != $exiftool_fullpath && $exiftool_write && $exiftool_write_option && !in_array($extension$exiftool_no_process))
        {
        
debug("[write_metadata()][ref={$ref}] Attempting to write metadata...");
        
// Trust Exiftool's list of writable formats
        
$writable_formats run_command("{$exiftool_fullpath} -listwf");
        
$writable_formats str_replace("\n"""$writable_formats);
        
$writable_formats_array explode(" "$writable_formats);
        if(!
in_array(strtoupper((string) $extension), $writable_formats_array))
            {
            
debug("[write_metadata()][ref={$ref}] Extension '{$extension}' not in writable_formats_array - " json_encode($writable_formats_array));
            return 
false;
            }

        
$tmpfile createTempFile($path$uniqid'');
        if(
$tmpfile === false)
            {
            
debug("[write_metadata()][ref={$ref}] Unable to create temp file!");
            return 
false;
            }

        
# Add the call to exiftool and some generic arguments to the command string.
        # Argument -overwrite_original: Now that we have already copied the original file, we can use exiftool's overwrite_original on the tmpfile.
        # Argument -E: Escape values for HTML. Used for handling foreign characters in shells not using UTF-8.
        # Arguments -EXIF:all= -XMP:all= -IPTC:all=: Remove the metadata in the tag groups EXIF, XMP and IPTC.
        
$command $exiftool_fullpath " -m -overwrite_original -E ";
        if(
$exiftool_remove_existing)
            {
            
$command stripMetadata(null) . ' ';
            
debug("[write_metadata()][ref={$ref}] Removing existing metadata. Command: "json_encode($command));
            }

        
$metadata_all=get_resource_field_data($reffalse,true,null,getval("k","")!=""); // Using get_resource_field_data means we honour field permissions
        
$read_only_fields array_column(array_filter($metadata_all, function($value) {
            return (bool) 
$value['read_only'] == true;
        }), 
'ref');

        
$write_to=array();
        foreach(
$metadata_all as $metadata_item)
            {
            if(
trim($metadata_item["exiftool_field"]??"") != "" && !in_array($metadata_item['ref'], $read_only_fields))
                {
                
$write_to[] = $metadata_item;
                }
            }

        
$writtenfields=array(); // Need to check if we are writing to an embedded field from more than one RS field, in which case subsequent values need to be appended, not replaced

        
for($i 0$i<count($write_to); $i++) # Loop through all the found fields.
        
{
            
$fieldtype $write_to[$i]['type'];
            
$writevalue $write_to[$i]['value']??"";
            
# Formatting and cleaning of the value to be written - depending on the RS field type.
            
switch ($fieldtype)
                {
                case 
2:
                case 
3:
                case 
9:
                case 
12:
                    
# Check box list, drop down, radio buttons or dynamic keyword list: remove initial comma if present
                    
$writevalue strip_leading_comma($writevalue);
                    break;
                case 
4:
                case 
6:
                case 
10:
                    
# Date / Expiry Date: write datetype fields in exiftool preferred format
                    
if($writevalue!='')
                        {
                        
$writevalue_to_time=strtotime($writevalue);
                        if(
$writevalue_to_time!='')
                            {
                            
$writevalue date("Y:m:d H:i:sP"strtotime($writevalue));
                            }
                        }
                    break;
                    
# Other types, already set
                
}
            
$filtervalue=hook("additionalmetadatafilter""", [$write_to[$i]["exiftool_field"], $writevalue]);
            if (
$filtervalue$writevalue=$filtervalue;
            
# Add the tag name(s) and the value to the command string.
            
$group_tags explode(","$write_to[$i]['exiftool_field']); # Each 'exiftool field' may contain more than one tag.
            
foreach ($group_tags as $group_tag)
                {
                
$group_tag strtolower($group_tag); # E.g. IPTC:Keywords -> iptc:keywords
                
if (strpos($group_tag,":")===false) {$tag $group_tag;} # E.g. subject -> subject
                
else {$tag substr($group_tagstrpos($group_tag,":")+1);} # E.g. iptc:keywords -> keywords
                
if(strpos($group_tag,"-") !== false && stripos($group_tag,"xmp") !== false)
                    {
                    
// Remove the XMP namespace for XMP data if included
                    
$group_tag substr($group_tag,0,(strpos($group_tag,"-")));
                    }
                
$exifappend=false// Need to replace values by default
                
if(isset($writtenfields[$group_tag]))
                    {
                    
// This embedded field is already being updated, we need to append values from this field
                    
$exifappend=true;
                    
debug("write_metadata - more than one field mapped to the tag '" $group_tag "'. Enabling append mode for this tag. ");
                    }

                switch (
$tag)
                    {
                    case 
"filesize":
                        
# Do nothing, no point to try to write the filesize.
                        
break;
                    case 
"filename":
                        
# Do nothing, no point to try to write the filename either as ResourceSpace controls this.
                        
break;
                    case 
"directory":
                        
# Do nothing, we don't want metadata to control this
                        
break;
                    case 
"keywords":
                        if(
substr($group_tag,0,3) != "xmp")
                            {
                            
# Only IPTC Keywords are a list type - these are written one at a time and not all together.
                            
if(!isset($writtenfields["keywords"])){$writtenfields["keywords"]="";}
                            
$keywords explode(","$writevalue); # "keyword1,keyword2, keyword3" (with or without spaces)
                            
if (implode(""$keywords) != "")
                                {
                                
# Only write non-empty keywords/ may be more than one field mapped to keywords so we don't want to overwrite with blank
                                
foreach ($keywords as $keyword)
                                    {
                                    
$keyword trim($keyword);
                                    if (
$keyword != "")
                                        {
                                        
debug("[write_metadata()][ref={$ref}] Writing keyword '{$keyword}'");
                                        
$writtenfields["keywords"].="," $keyword;
                                        
# Convert the data to UTF-8 if not already.
                                        
if (!$exiftool_write_omit_utf8_conversion && (!isset($mysql_charset) || (isset($mysql_charset) && strtolower($mysql_charset)!="utf8"))){$keyword mb_convert_encoding($keywordmb_detect_encoding($keyword), 'UTF-8');}
                                        
$command.= escapeshellarg("-" $group_tag "-=" htmlentities($keywordENT_QUOTES"UTF-8")) . " "// In case value is already embedded, need to manually remove it to prevent duplication
                                        
$command.= escapeshellarg("-" $group_tag "+=" htmlentities($keywordENT_QUOTES"UTF-8")) . " ";
                                        }
                                    }
                                }
                            break; 
// The break is in here so that Non-IPTC keywords continue to be handled by default
                            
}
                    default:
                        if(
$exifappend && ($writevalue=="" || ($writevalue!="" && strpos($writtenfields[$group_tag],$writevalue)!==false)))
                            {
                            
// The new value is blank or already included in what is being written, skip to next group tag
                            
continue 2# @see https://www.php.net/manual/en/control-structures.continue.php note
                            
}
                        
$writtenfields[$group_tag]=$writevalue;
                        
debug("[write_metadata()][ref={$ref}] Updating tag '{$group_tag}' with value '{$writevalue}'");
                        
# Write as is, convert the data to UTF-8 if not already.

                        
global $strip_rich_field_tags;
                        if (!
$exiftool_write_omit_utf8_conversion
                            
&& (!isset($mysql_charset)
                                || (isset(
$mysql_charset) && strtolower($mysql_charset)!="utf8")))
                            {
                            
$writevalue mb_convert_encoding($writevaluemb_detect_encoding($writevalue), 'UTF-8');
                            }
                            if (
$strip_rich_field_tags)
                            {
                                
$command.= escapeshellarg("-" $group_tag "=" trim(strip_tags(i18n_get_translated($writevalue)))) . " ";
                            }
                            else
                            {
                                
$command.= escapeshellarg("-" $group_tag "=" htmlentities(i18n_get_translated($writevalue), ENT_QUOTES"UTF-8")) . " ";
                            }
                    }
                }
            }

            
# Add the filename to the command string.
            
$command.= " " escapeshellarg($tmpfile);

            
# Perform the actual writing - execute the command string.
            
run_command($command);
        return 
$tmpfile;
       }
    else
        {
        
debug("[write_metadata()][ref={$ref}] Did not perform - write metadata!");
        return 
false;
        }
    }

This article was last updated 19th March 2024 06:05 Europe/London time based on the source file dated 11th March 2024 14:25 Europe/London time.