Last active
April 25, 2019 20:35
-
-
Save vijinho/35061d2f8a9e70b4dcbd7ecf28221ccb to your computer and use it in GitHub Desktop.
Get the exif(tool) metadata for a file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* get-metadata.php - get metadata from files readable with exiftool | |
* creates 2 cache files, metadata.ser and metadata.old.ser | |
* where old.ser is the old version of metadata.ser for comparison | |
* | |
* https://www.sno.phy.queensu.ca/~phil/exiftool/#filename | |
* see https://www.sno.phy.queensu.ca/~phil/exiftool/exiftool_pod.html | |
* | |
* relies on command-line tools, tested on MacOS. | |
* | |
* @license GPLv3 (http://www.gnu.org/licenses/gpl-3.0.html) | |
*/ | |
define('DEBUG',0); | |
define('VERBOSE',1); | |
date_default_timezone_set('UTC'); | |
ini_set('default_charset', 'utf-8'); | |
ini_set('mbstring.encoding_translation', 'On'); | |
ini_set('mbstring.func_overload', 6); | |
ini_set('auto_detect_line_endings', TRUE); | |
// check CLI commands are available | |
$commands = getCommands(); | |
if (empty($commands)) exit; | |
// load or create $data of file meta data | |
$data = []; | |
$data_file = '.metadata.ser'; | |
$data = serialize_load($data_file); | |
if (!empty($data)) { | |
verbose("Loaded data file: $data_file"); | |
} else { | |
verbose("Creating data file: $data_file"); | |
eval('$data = ' . `exiftool -php -r -G *`); | |
serialize_save($data_file, $data); | |
} | |
// set index to filename for data files | |
foreach ($data as $i => $metadata) { | |
unset($data[$i]); | |
ksort($metadata); | |
$file = $metadata['SourceFile']; | |
$data[$file] = $metadata; | |
} | |
foreach ($data as $file => $metadata) { | |
print_r($metadata); | |
sleep(1); | |
} | |
//print_r($data); | |
exit; | |
//----------------------------------------------------------------------------- | |
// functions used above | |
/** | |
* Execute a command and return streams as an array of | |
* stdin, stdout, stderr | |
* | |
* @param string $cmd command to execute | |
* @return array|false array $streams | boolean false if failure | |
* @see https://secure.php.net/manual/en/function.proc-open.php | |
*/ | |
function shell_execute($cmd) | |
{ | |
$process = proc_open( | |
$cmd, | |
[ | |
['pipe', 'r'], | |
['pipe', 'w'], | |
['pipe', 'w'] | |
], $pipes | |
); | |
if (is_resource($process)) { | |
$streams = []; | |
foreach ($pipes as $p => $v) { | |
$streams[] = stream_get_contents($pipes[$p]); | |
} | |
proc_close($process); | |
return [ | |
'stdin' => $streams[0], | |
'stdout' => $streams[1], | |
'stderr' => $streams[2] | |
]; | |
} | |
return false; | |
} | |
/** | |
* Execute a command and return output of stdout or throw exception of stderr | |
* | |
* @param string $cmd command to execute | |
* @param boolean $split split returned results? default on newline | |
* @param string $exp regular expression to preg_split to split on | |
* @return mixed string $stdout | Exception if failure | |
* @see shell_execute($cmd) | |
*/ | |
function cmd_execute($cmd, $split = true, $exp = "/\n/") | |
{ | |
$result = shell_execute($cmd); | |
if (!empty($result['stderr'])) { | |
throw new Exception($result['stderr']); | |
} | |
$data = $result['stdout']; | |
if (empty($split) || empty($exp) || empty($data)) { | |
return $data; | |
} | |
return preg_split($exp, $data); | |
} | |
// check required commands installed and get path | |
function getCommands() | |
{ | |
static $commands = []; // cli command paths | |
if (!empty($commands)) { | |
return $commands; | |
} | |
$requirements = [ | |
'exiftool' => 'https://sno.phy.queensu.ca/~phil/exiftool/', | |
'cp' => 'copy system command - cp', | |
'mv' => 'move system command - mv', | |
'find' => 'system find commmand' | |
]; | |
$errors = []; | |
foreach ($requirements as $tool => $description) { | |
$cmd = cmd_execute("which $tool"); | |
if (empty($cmd)) { | |
$errors[] = "Error: Missing requirement: $tool - " . $description; | |
} else { | |
$commands[$tool] = $cmd[0]; | |
} | |
} | |
if (!empty($errors)) { | |
echo join("\n", $errors) . "\n"; | |
} | |
return $commands; | |
} | |
/** | |
* Return the memory used by the script, (current/peak) | |
* | |
* @return string memory used | |
*/ | |
function get_memory_used() | |
{ | |
return( | |
ceil(memory_get_usage() / 1024 / 1024) . '/' . | |
ceil(memory_get_peak_usage() / 1024 / 1024)); | |
} | |
/** | |
* Output string, to STDERR if available | |
* | |
* @param string { string to output | |
* @param boolean $STDERR write to stderr if it is available | |
*/ | |
function output($text, $STDERR = true) | |
{ | |
if (!empty($STDERR) && defined('STDERR')) { | |
fwrite(STDERR, $text); | |
} else { | |
echo $text; | |
} | |
} | |
/** | |
* Dump debug data if DEBUG constant is set | |
* | |
* @param optional string $string string to output | |
* @param optional mixed $data to dump | |
* @return boolean true if string output, false if not | |
*/ | |
function debug($string = '', $data = []) | |
{ | |
if (DEBUG) { | |
output(trim('[D ' . get_memory_used() . '] ' . $string) . "\n"); | |
if (!empty($data)) { | |
output(print_r($data, 1)); | |
} | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Output string if VERBOSE constant is set | |
* | |
* @param string $string string to output | |
* @param optional mixed $data to dump | |
* @return boolean true if string output, false if not | |
*/ | |
function verbose($string, $data = []) | |
{ | |
if (VERBOSE && !empty($string)) { | |
output(trim('[V' . ((DEBUG) ? ' ' . get_memory_used() : '') . '] ' . $string) . "\n"); | |
if (!empty($data)) { | |
output(print_r($data, 1)); | |
} | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Clear an array of empty values | |
* | |
* @param array $keys array keys to explicitly remove regardless | |
* @return array the trimmed down array | |
*/ | |
function array_clear($array, $keys = []) | |
{ | |
foreach ($array as $key => $value) { | |
if (is_array($value)) { | |
do { | |
$oldvalue = $value; | |
$value = array_clear($value, $keys); | |
} | |
while ($oldvalue !== $value); | |
$array[$key] = array_clear($value, $keys); | |
} | |
if (empty($value) && 0 !== $value) { | |
unset($array[$key]); | |
} | |
if (in_array($key, $keys, true)) { | |
unset($array[$key]); | |
} | |
} | |
return $array; | |
} | |
/** | |
* Encode array character encoding recursively | |
* | |
* @param mixed $data | |
* @param string $to_charset convert to encoding | |
* @param string $from_charset convert from encoding | |
* @return mixed | |
*/ | |
function to_charset($data, $to_charset = 'UTF-8', $from_charset = 'auto') | |
{ | |
if (is_numeric($data)) { | |
if (is_float($data)) { | |
return (float) $data; | |
} else { | |
return (int) $data; | |
} | |
} else if (is_string($data)) { | |
return mb_convert_encoding($data, $to_charset, $from_charset); | |
} else if (is_array($data)) { | |
foreach ($data as $key => $value) { | |
$data[$key] = to_charset($value, $to_charset, $from_charset); | |
} | |
} else if (is_object($data)) { | |
foreach ($data as $key => $value) { | |
$data->$key = to_charset($value, $to_charset, $from_charset); | |
} | |
} | |
return $data; | |
} | |
/** | |
* Load a serialized php data file and return it | |
* | |
* @param string $filename the json filename | |
* @return array $data | |
*/ | |
function serialize_load($file) | |
{ | |
if (file_exists($file)) { | |
$data = unserialize(file_get_contents($file)); | |
$data = array_clear($data); | |
} | |
return empty($data) ? [] : $data; | |
} | |
/** | |
* Save data array to a php serialized data | |
* | |
* @param string $filename the json filename | |
* @param array $data data to save | |
* @return boolean result | |
*/ | |
function serialize_save($file, $data) | |
{ | |
if (empty($data)) { | |
return 'No data to write to file.'; | |
} | |
$data = array_clear($data); | |
return file_put_contents($file, serialize($data)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment