From e89c86a82b7dac1c1b0db2c21c1e36e8c7f06d4d Mon Sep 17 00:00:00 2001 From: Axel Krysztofiak Date: Fri, 13 Sep 2024 14:46:28 +0200 Subject: [PATCH] =?UTF-8?q?Namespace-=C3=84nderung=20(#37)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Namespace-Angleichng an den FOR-Standard * Namespace-Anpassung auch für den CLI-Command * Der Format-Parameter bei den Formattern ist eher verwirrend. Nur weil in den EXIF-Daten z.B. als Auslösezeit 0.025 (wäre Format RAW). Das will man das nicht so ausgeben. Als Angabe erwartet man 1/40 (Format READABLE). Wozu auch den Parameter mitschleifen, wenn er meistens gar nicht genutzt wird? (wie z.B. bei den GEO-Daten) Wird also nicht gebraucht. * Deprecation Warnung optimieren. a) War bisher viel zu unübersichtlich. b) Wurde auf eine Verwendung innerhalb des Addons verwiesen. Der Ort sollte die erste Stelle außerhalb sein. Also da wo der Benutzer den Code schreibt * Deprecations nicht als Attribut einsetzen * null-Parameter, gefunden via phpunit * Autoload callback ist eine void-Funktion. * FormatInterface ist eigentlich eine Basis-Klasse. Also wäre FormatBase der bessere Name. * Da FormatBase noch nicht verwendet werden kann, kann dort auch die neue API komplett umgesetzt sein. Das alte FormartInterface muss es erstmal weiter bis v4 unterstützen * Echtes FormtterInterface als alternative zur abstrakten Klasse. Vorteil: Das Daten-Array kann vom Entwickler selbst bestimmt werden. * Bugfix: Fehlerhafte Anzeigen, bei Belichtungszeiten über 1 sek. Fehlerhafte Beispiele: "1/1 s" statt "1 s" "13/1 s" statt "13 s" "3/5 s" statt "0,6 s" "1/2 s" statt "0,5 s" * Formatter für Geodaten in Grad-Schreibweise * Version aus Datei-Kommentaren entfernen, das hat mit der Realität kaum was zu tun * phpUnit-Dateien ausschließen * Fehlerbereinigung mit phpUnit * phpStan --- .gitignore | 2 + boot.php | 11 +- lib/Autoload.php | 86 ++++++++++++++ lib/Cli/Read.php | 9 +- lib/Enum/Format.php | 9 +- lib/Enum/IptcDefinitions.php | 2 +- lib/Enum/MediaFetchMode.php | 8 +- lib/Enum/ReturnMode.php | 8 +- lib/Exception/InvalidClassException.php | 19 +-- lib/Exception/InvalidFormatExcption.php | 12 +- lib/Exception/IptcException.php | 12 +- lib/Exception/NotFoundException.php | 3 +- lib/Exif.php | 9 +- lib/ExifData.php | 78 ++++++++++--- lib/Format/Camera.php | 66 ++--------- lib/Format/Camera/Aperture.php | 17 +-- lib/Format/Camera/Exposure.php | 22 +--- lib/Format/Camera/Iso.php | 7 +- lib/Format/Camera/Length.php | 18 +-- lib/Format/FormatBase.php | 73 ++++++++++++ lib/Format/FormatInterface.php | 83 +++++++------- lib/Format/Geo.php | 5 +- lib/Formatter/Camera.php | 46 ++++++++ lib/Formatter/Camera/Aperture.php | 36 ++++++ lib/Formatter/Camera/Exposure.php | 39 +++++++ lib/Formatter/Camera/Iso.php | 35 ++++++ lib/Formatter/Camera/Length.php | 38 ++++++ lib/Formatter/Geo.php | 74 ++++++++++++ lib/Formatter/GeoDegree.php | 108 ++++++++++++++++++ .../Interface/ArrayFormatterInterface.php | 25 ++++ .../Interface/FormatterInterface.php | 22 ++++ .../Interface/StandardFormtterInterface.php | 23 ++++ lib/MediapoolExif.php | 26 +++-- package.yml | 4 +- 34 files changed, 793 insertions(+), 242 deletions(-) create mode 100644 .gitignore create mode 100644 lib/Autoload.php create mode 100644 lib/Format/FormatBase.php create mode 100644 lib/Formatter/Camera.php create mode 100644 lib/Formatter/Camera/Aperture.php create mode 100644 lib/Formatter/Camera/Exposure.php create mode 100644 lib/Formatter/Camera/Iso.php create mode 100644 lib/Formatter/Camera/Length.php create mode 100644 lib/Formatter/Geo.php create mode 100644 lib/Formatter/GeoDegree.php create mode 100644 lib/Formatter/Interface/ArrayFormatterInterface.php create mode 100644 lib/Formatter/Interface/FormatterInterface.php create mode 100644 lib/Formatter/Interface/StandardFormtterInterface.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c220ea --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.phpunit.cache +_docs diff --git a/boot.php b/boot.php index 0e29a60..c9978e5 100644 --- a/boot.php +++ b/boot.php @@ -1,6 +1,13 @@ $item) { + if (isset($backtrace[$key]['file']) && isset($backtrace[$key]['line'])) { + if (stristr($backtrace[$key]['file'], '/mediapool_exif/')) { + continue; + } + + $backtraceText = ' in '.$backtrace[$key]['file'].': '.$backtrace[$key]['line']; + break; + } + $i++; + } + + $msg = "Deprecated class name found: ".$oldName.$backtraceText.PHP_EOL.'New class: '.$newName; + + class_alias($newName, $oldName); + + user_error($msg, E_USER_DEPRECATED); + $name = $newName; + } + + + if (!stristr($name, __NAMESPACE__)) { + return; + } + + if (class_exists($name) || interface_exists($name)) { + return; + } + + //namespace parts not in directory structure. + $name = str_replace(__NAMESPACE__, '', $name); + + $filename = self::getBaseDir().'/'.str_replace('\\', '/', $name).'.php'; + if (file_exists($filename)) { + require $filename; + return; + } +// throw new \Exception($filename.' not found'); + return; + } +} diff --git a/lib/Cli/Read.php b/lib/Cli/Read.php index 619faef..4f44416 100644 --- a/lib/Cli/Read.php +++ b/lib/Cli/Read.php @@ -3,14 +3,13 @@ /** * Datei für ... * - * @version 1.0 / 2020-06-08 * @author akrys */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Cli; +namespace FriendsOfRedaxo\MediapoolExif\Cli; -use FriendsOfRedaxo\addon\MediapoolExif\Enum\MediaFetchMode; -use FriendsOfRedaxo\addon\MediapoolExif\Exif; -use FriendsOfRedaxo\addon\MediapoolExif\MediapoolExif; +use FriendsOfRedaxo\MediapoolExif\Enum\MediaFetchMode; +use FriendsOfRedaxo\MediapoolExif\Exif; +use FriendsOfRedaxo\MediapoolExif\MediapoolExif; use rex_console_command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; diff --git a/lib/Enum/Format.php b/lib/Enum/Format.php index 6e5a767..d81d80c 100644 --- a/lib/Enum/Format.php +++ b/lib/Enum/Format.php @@ -1,22 +1,17 @@ format === null) { $this->format = Format::UNDEFINED; @@ -45,6 +42,7 @@ public function __construct( /** * Formatname * @return Format|null + * @deprecated since version 3.1 */ public function getFormat(): ?Format { diff --git a/lib/Exception/IptcException.php b/lib/Exception/IptcException.php index dc48615..4691560 100644 --- a/lib/Exception/IptcException.php +++ b/lib/Exception/IptcException.php @@ -1,19 +1,13 @@ exif = []; @@ -95,19 +96,66 @@ public function get(string $index = null): mixed /** * Formatierungsalgorithmus anstoßen - * @param string $className + * @param string|FormatterInterface $objectParam * @param Format $format * @return mixed */ - public function format(string $className, Format $format = null): mixed - { + public function format( + string|FormatterInterface $objectParam, + /** @deprecated since version 3.1 */ Format $format = Format::READABLE + ): mixed { try { - if (!class_exists($className)) { - //fallback, old call - $className = '\\FriendsOfRedaxo\\addon\\MediapoolExif\\Format\\'.ucfirst($className); + /** @var FormatterInterface $object */ + $object = null; + /** @var string $className */ + $className = null; + + if (is_object($objectParam)) { + $object = $objectParam; + $className = get_class($object); + } + + if (is_string($objectParam)) { + $className = $objectParam; + if (!class_exists($objectParam)) { + //fallback, old call internal formatter without namespace + $className = '\\FriendsOfRedaxo\\MediapoolExif\\Format\\'.ucfirst($objectParam); + } + } + +// print $className; +// print '
';
+//			var_dump([
+//				'classname' => $className,
+//				'class_parents' => class_parents($className, true),
+//				'class_implements' => class_implements($className, true),
+//			]);
+//			print '
'; + + if(!class_exists($className)) { + //phpdoc warnings class_parents() with not existing class names + throw new InvalidClassException($className); + } + + // @codeCoverageIgnoreStart + // deprected + if (isset(class_parents($className)[FormatInterface::class])) { + return FormatInterface::get($this->exif, $className, $format)->format(); + } + // @codeCoverageIgnoreEnd + + if (isset(class_parents($className)[FormatBase::class])) { + return FormatBase::get($this->exif, $className)->format(); + } + + if (isset(class_implements($className)[FormatterInterface::class])) { + $object = new $className(); + if (is_a($object, FormatterInterface::class)) { + return $object->format($this->exif); + } } - return FormatInterface::get($this->exif, $className, $format)->format(); + throw new InvalidClassException($className); } catch (Exception $e) { return $this->handleExcption($e); } diff --git a/lib/Format/Camera.php b/lib/Format/Camera.php index f799055..58e4dae 100644 --- a/lib/Format/Camera.php +++ b/lib/Format/Camera.php @@ -3,33 +3,28 @@ /** * Datei für ... * - * @version 1.0 / 2020-06-13 * @author akrys */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Format; +namespace FriendsOfRedaxo\MediapoolExif\Format; use Exception; -use FriendsOfRedaxo\addon\MediapoolExif\Enum\Format; -use FriendsOfRedaxo\addon\MediapoolExif\Exception\InvalidFormatExcption; -use FriendsOfRedaxo\addon\MediapoolExif\Format\Camera\Aperture; -use FriendsOfRedaxo\addon\MediapoolExif\Format\Camera\Exposure; -use FriendsOfRedaxo\addon\MediapoolExif\Format\Camera\Iso; -use FriendsOfRedaxo\addon\MediapoolExif\Format\Camera\Length; -use FriendsOfRedaxo\addon\MediapoolExif\Format\FormatInterface; +use FriendsOfRedaxo\MediapoolExif\Format\Camera\Aperture; +use FriendsOfRedaxo\MediapoolExif\Format\Camera\Exposure; +use FriendsOfRedaxo\MediapoolExif\Format\Camera\Iso; +use FriendsOfRedaxo\MediapoolExif\Format\Camera\Length; /** * Description of Camera * * @author akrys */ -class Camera extends FormatInterface +class Camera extends FormatBase { /** * Daten formatieren * @return array * @throws Exception - * @throws InvalidFormatExcption */ public function format(): array { @@ -37,54 +32,13 @@ public function format(): array throw new Exception('No camera data found'); } - if ($this->format === null) { - $this->format = Format::READABLE; - } - $formatValue = $this->format->value; - - /** @phpstan-ignore-next-line */ - if (!is_callable([$this, $formatValue])) { - // @codeCoverageIgnoreStart - throw new InvalidFormatExcption($this->format); - // @codeCoverageIgnoreEnd - } - - return $this->$formatValue(); - } - - /** - * Daten lesbar anzeigen - * @return array - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) - * -> zugriff via $this->$formatValue - */ - private function readable(): array - { - return [ - 'make' => $this->data['Make'], - 'model' => $this->data['Model'], - 'iso' => (new Iso($this->data, $this->format))->format(), - 'aperture' => (new Aperture($this->data, $this->format))->format(), - 'exposure' => (new Exposure($this->data, $this->format))->format(), - 'length' => (new Length($this->data, $this->format))->format(), - ]; - } - - /** - * Daten nummerisch anzeigen - * @return array - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) - * -> zugriff via $this->$formatValue - */ - private function numeric(): array - { return [ 'make' => $this->data['Make'], 'model' => $this->data['Model'], - 'iso' => (new Iso($this->data, $this->format))->format(), - 'aperture' => (new Aperture($this->data, $this->format))->format(), - 'exposure' => (new Exposure($this->data, $this->format))->format(), - 'length' => (new Length($this->data, $this->format))->format(), + 'iso' => (new Iso($this->data))->format(), + 'aperture' => (new Aperture($this->data))->format(), + 'exposure' => (new Exposure($this->data))->format(), + 'length' => (new Length($this->data))->format(), ]; } } diff --git a/lib/Format/Camera/Aperture.php b/lib/Format/Camera/Aperture.php index 73da205..edddf7a 100644 --- a/lib/Format/Camera/Aperture.php +++ b/lib/Format/Camera/Aperture.php @@ -3,22 +3,19 @@ /** * Datei für ... * - * @version 1.0 / 2020-06-13 * @author akrys */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Format\Camera; +namespace FriendsOfRedaxo\MediapoolExif\Format\Camera; use Exception; -use FriendsOfRedaxo\addon\MediapoolExif\Enum\Format; -use FriendsOfRedaxo\addon\MediapoolExif\Exception\InvalidFormatExcption; -use FriendsOfRedaxo\addon\MediapoolExif\Format\FormatInterface; +use FriendsOfRedaxo\MediapoolExif\Format\FormatBase; /** * Description of Aperture * * @author akrys */ -class Aperture extends FormatInterface +class Aperture extends FormatBase { /** @@ -33,12 +30,6 @@ public function format(): string } $data = explode('/', $this->data['FNumber']); - switch ($this->format) { - case Format::READABLE: - return 'f/'.number_format((float) $data[0] / (float) $data[1], 1); - case Format::RAW: - default: - return number_format((float) $data[0] / (float) $data[1], 1); - } + return 'f/'.number_format((float) $data[0] / (float) $data[1], 1); } } diff --git a/lib/Format/Camera/Exposure.php b/lib/Format/Camera/Exposure.php index 41f7c8c..11572b1 100644 --- a/lib/Format/Camera/Exposure.php +++ b/lib/Format/Camera/Exposure.php @@ -3,21 +3,19 @@ /** * Datei für ... * - * @version 1.0 / 2020-06-13 * @author akrys */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Format\Camera; +namespace FriendsOfRedaxo\MediapoolExif\Format\Camera; use Exception; -use FriendsOfRedaxo\addon\MediapoolExif\Enum\Format; -use FriendsOfRedaxo\addon\MediapoolExif\Format\FormatInterface; +use FriendsOfRedaxo\MediapoolExif\Format\FormatBase; /** * Description of Exposure * * @author akrys */ -class Exposure extends FormatInterface +class Exposure extends FormatBase { /** @@ -31,18 +29,10 @@ public function format(): string throw new Exception('No exposure time found'); } - $return = ''; $data = explode('/', $this->data['ExposureTime']); - switch ($this->format) { - case Format::READABLE: - $return= $data[0].'/'.$data[1].' s'; - break; - case Format::RAW: - default: - $tmp = (float) $data[0] / (float) $data[1]; - $return = (string) $tmp; - break; + if ($data[0] !== '1' || ($data[0] === '1' && $data[1] < 3)) { + return preg_replace('/,0$/', '', number_format((int)$data[0] / (int)$data[1], 1, ',', '.')).' s'; } - return $return; + return $data[0].'/'.$data[1].' s'; } } diff --git a/lib/Format/Camera/Iso.php b/lib/Format/Camera/Iso.php index 5835520..7c1f6e1 100644 --- a/lib/Format/Camera/Iso.php +++ b/lib/Format/Camera/Iso.php @@ -3,20 +3,19 @@ /** * Datei für ... * - * @version 1.0 / 2020-06-13 * @author akrys */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Format\Camera; +namespace FriendsOfRedaxo\MediapoolExif\Format\Camera; use Exception; -use FriendsOfRedaxo\addon\MediapoolExif\Format\FormatInterface; +use FriendsOfRedaxo\MediapoolExif\Format\FormatBase; /** * Description of Iso * * @author akrys */ -class Iso extends FormatInterface +class Iso extends FormatBase { /** diff --git a/lib/Format/Camera/Length.php b/lib/Format/Camera/Length.php index 8a94e42..6a41828 100644 --- a/lib/Format/Camera/Length.php +++ b/lib/Format/Camera/Length.php @@ -5,17 +5,14 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Format\Camera; +namespace FriendsOfRedaxo\MediapoolExif\Format\Camera; use Exception; -use FriendsOfRedaxo\addon\MediapoolExif\Enum\Format; -use FriendsOfRedaxo\addon\MediapoolExif\Exception\InvalidFormatExcption; -use FriendsOfRedaxo\addon\MediapoolExif\Format\FormatInterface; +use FriendsOfRedaxo\MediapoolExif\Format\FormatBase; /** * Datei für ... * - * @version 1.0 / 2020-06-13 * @author akrys */ @@ -24,7 +21,7 @@ * * @author akrys */ -class Length extends FormatInterface +class Length extends FormatBase { /** @@ -40,12 +37,7 @@ public function format(): string $data = explode('/', $this->data['FocalLength']); $value = (float) $data[0] / (float) $data[1]; - switch ($this->format) { - case Format::READABLE: - return $value.' mm'; - case Format::RAW: - default: - return (string) $value; - } + + return $value.' mm'; } } diff --git a/lib/Format/FormatBase.php b/lib/Format/FormatBase.php new file mode 100644 index 0000000..76d54c8 --- /dev/null +++ b/lib/Format/FormatBase.php @@ -0,0 +1,73 @@ + $data Exif-Daten + */ + public function __construct( + protected array $data + ) { + + } + + /** + * Daten holen + * + * Hinweise zu Parametern: + * + * $data: + * Die hier hinein gegebenen EXIF-Daten kommen i.d.R. aus der Datenbank (Spalte rex_media.exif). + * Es kann aber auch sein, dass sie direkt aus der Datei stammen. z.B. für die automatische Koordinaten-Errechnung. + * Im Prinzip spielt es aber keine Rolle, wo die Daten genau her kommen. Wichtig ist nur, dass sie hier ankommen. + * + * $className: + * Bei ClassName geht es um die Formatter-Klasse, die verwendet werden soll. Wichtig ist, dass sie das + * FormatInterface implementiert. Damit kann die Funktion format immer aufgerufen werden. + * + * @param array $data exif-Daten-Array + * @param string $className Formatter Namespace + * @throws InvalidClassException + */ + public static function get( + $data, + string $className = '' + ): FormatBase + { + if (class_exists($className)) { + $object = new $className($data); + if (is_a($object, FormatBase::class)) { + return $object; + } + } + throw new InvalidClassException($className); + } + + /** + * Formatierung der Daten. + * + * Hier ist der Algorithmus hinterlegt, nach welchem der bzw. die Werte formatiert werden + * + * Die Rückgabe kann bei einzelwerten ein string, sont ein array sein. + * + * @return string|array + */ + abstract public function format(): string|array; +} diff --git a/lib/Format/FormatInterface.php b/lib/Format/FormatInterface.php index cf25a11..051fa05 100644 --- a/lib/Format/FormatInterface.php +++ b/lib/Format/FormatInterface.php @@ -3,42 +3,52 @@ /** * Datei für ... * - * @version 1.0 / 2020-06-12 * @author akrys */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Format; +namespace FriendsOfRedaxo\MediapoolExif\Format; -use FriendsOfRedaxo\addon\MediapoolExif\Enum\Format; -use FriendsOfRedaxo\addon\MediapoolExif\Exception\InvalidClassException; +use FriendsOfRedaxo\MediapoolExif\Enum\Format; +use FriendsOfRedaxo\MediapoolExif\Exception\InvalidClassException; /** * Description of FormatBase * * @author akrys + * @deprecated Das hier ist kein Interface, es ist eine abstrakte Basis-Klasse. FormatBase ist der bessere Name */ -abstract class FormatInterface +abstract class FormatInterface extends FormatBase // remove in v4 { - /** - * Exif-Daten - * @var array - */ - protected array $data; - - /** - * Formatierung - * @var Format|null - */ - protected ?Format $format; /** * Konstruktor - * @param array $data - * @param ?Format $format + * @param array $data Exif-Daten + * @param Format $format Formatierung (deprected) */ - public function __construct(array $data, ?Format $format = null) - { - $this->data = $data; - $this->format = $format; + public function __construct( + array $data, protected /** @deprecated since version 3.1 */ Format $format = Format::READABLE + ) { + parent::__construct($data); + + $backtrace = debug_backtrace(); + $backtraceText = ''; + $i = 0; + foreach ($backtrace as $key => $item) { + if (isset($backtrace[$key]['file']) && isset($backtrace[$key]['line'])) { + if (stristr($backtrace[$key]['file'], '/mediapool_exif/')) { + continue; + } + + $backtraceText = 'in '.$backtrace[$key]['file'].': '.$backtrace[$key]['line']; + break; + } + $i++; + } + + $msg = FormatInterface::class.' is deprected. Use '.FormatBase::class.' for extension.'; + if ($backtraceText) { + $msg .= '('.$backtraceText.')'; + } + user_error($msg, E_USER_DEPRECATED); } /** @@ -66,33 +76,22 @@ public function __construct(array $data, ?Format $format = null) *
    * * @param array $data exif-Daten-Array - * @param ?string $className Formatter Namespace - * @param Format|null $format Format-Parameter - * @return FormatInterface + * @param string $className Formatter Namespace + * @param Format $format Format-Parameter (deprected) + * @return FormatBase * @throws InvalidClassException + * @deprecated since version 3.1 */ - public static function get($data, ?string $className = null, ?Format $format = null): FormatInterface - { - if ($className === null) { - $className = ''; - } + public static function get( + $data, string $className = '', + /** @deprecated since version 3.1 */ Format $format = Format::READABLE + ): FormatBase { if (class_exists($className)) { $object = new $className($data, $format); - if (is_a($object, FormatInterface::class)) { + if (is_a($object, FormatBase::class)) { return $object; } } throw new InvalidClassException($className); } - - /** - * Formatierung der Daten. - * - * Hier ist der Algorithmus hinterlegt, nach welchem der bzw. die Werte formatiert werden - * - * Die Rückgabe kann bei einzelwerten ein string, sont ein array sein. - * - * @return string|array - */ - abstract public function format(): string|array; } diff --git a/lib/Format/Geo.php b/lib/Format/Geo.php index 58722e4..ff17971 100644 --- a/lib/Format/Geo.php +++ b/lib/Format/Geo.php @@ -3,10 +3,9 @@ /** * Datei für GEO * - * @version 1.0 / 2020-06-12 * @author akrys */ -namespace FriendsOfRedaxo\addon\MediapoolExif\Format; +namespace FriendsOfRedaxo\MediapoolExif\Format; use Exception; @@ -15,7 +14,7 @@ * * @author akrys */ -class Geo extends FormatInterface +class Geo extends FormatBase { /** diff --git a/lib/Formatter/Camera.php b/lib/Formatter/Camera.php new file mode 100644 index 0000000..c98772e --- /dev/null +++ b/lib/Formatter/Camera.php @@ -0,0 +1,46 @@ + $data + * @return array + * @throws Exception + */ + public function format(array $data): array + { + if (!isset($data['Make']) && !isset($data['Model'])) { + throw new Exception('No camera data found'); + } + + return [ + 'make' => $data['Make'], + 'model' => $data['Model'], + 'iso' => (new Iso($data))->format(), + 'aperture' => (new Aperture($data))->format(), + 'exposure' => (new Exposure($data))->format(), + 'length' => (new Length($data))->format(), + ]; + } +} diff --git a/lib/Formatter/Camera/Aperture.php b/lib/Formatter/Camera/Aperture.php new file mode 100644 index 0000000..23f0d30 --- /dev/null +++ b/lib/Formatter/Camera/Aperture.php @@ -0,0 +1,36 @@ + $exif + * @return string + * @throws Exception + */ + public function format(array $exif): string + { + if (!isset($exif['FNumber'])) { + throw new Exception('No aperture found'); + } + + $data = explode('/', $exif['FNumber']); + return 'f/'.number_format((float) $data[0] / (float) $data[1], 1); + } +} diff --git a/lib/Formatter/Camera/Exposure.php b/lib/Formatter/Camera/Exposure.php new file mode 100644 index 0000000..2268888 --- /dev/null +++ b/lib/Formatter/Camera/Exposure.php @@ -0,0 +1,39 @@ + $exif + * @return string + * @throws Exception + */ + public function format(array $exif): string + { + if (!isset($exif['ExposureTime'])) { + throw new Exception('No exposure time found'); + } + + $data = explode('/', $exif['ExposureTime']); + if ($data[0] !== '1' || ($data[0] === '1' && $data[1] < 3)) { + return preg_replace('/,0$/', '', number_format((int)$data[0] / (int)$data[1], 1, ',', '.')).' s'; + } + return $data[0].'/'.$data[1].' s'; + } +} diff --git a/lib/Formatter/Camera/Iso.php b/lib/Formatter/Camera/Iso.php new file mode 100644 index 0000000..7553881 --- /dev/null +++ b/lib/Formatter/Camera/Iso.php @@ -0,0 +1,35 @@ + $data + * @return string + * @throws Exception + */ + public function format(array $data): string + { + if (!isset($data['ISOSpeedRatings'])) { + throw new Exception('No iso setting found'); + } + + return $data['ISOSpeedRatings']; + } +} diff --git a/lib/Formatter/Camera/Length.php b/lib/Formatter/Camera/Length.php new file mode 100644 index 0000000..93f18a4 --- /dev/null +++ b/lib/Formatter/Camera/Length.php @@ -0,0 +1,38 @@ + $data + * @return string + * @throws Exception + */ + public function format(array $data): string + { + if (!isset($data['FocalLength'])) { + throw new Exception('No focial length found'); + } + + $data = explode('/', $data['FocalLength']); + $value = (float) $data[0] / (float) $data[1]; + + return $value.' mm'; + } +} diff --git a/lib/Formatter/Geo.php b/lib/Formatter/Geo.php new file mode 100644 index 0000000..301fde0 --- /dev/null +++ b/lib/Formatter/Geo.php @@ -0,0 +1,74 @@ + $data + * @return array + * @throws Exception + */ + public function format(array $data): array + { + if (!isset($data['GPSLatitude']) || + !isset($data['GPSLatitudeRef']) || + !isset($data['GPSLongitude']) || + !isset($data['GPSLongitudeRef'])) { + throw new Exception('GPS not found'); + } + + $GPSLatitude = $data['GPSLatitude']; + $GPSLatitude_Ref = $data['GPSLatitudeRef']; + $GPSLongitude = $data['GPSLongitude']; + $GPSLongitude_Ref = $data['GPSLongitudeRef']; + + $GPSLatfaktor = 1; //N + if ($GPSLatitude_Ref == 'S') { + $GPSLatfaktor = -1; + } + + $GPSLongfaktor = 1; //E + if ($GPSLongitude_Ref == 'W') { + $GPSLongfaktor = -1; + } + + $GPSLatitude_h = explode("/", $GPSLatitude[0]); + $GPSLatitude_m = explode("/", $GPSLatitude[1]); + $GPSLatitude_s = explode("/", $GPSLatitude[2]); + + $GPSLat_h = (float) $GPSLatitude_h[0] / (float) $GPSLatitude_h[1]; + $GPSLat_m = (float) $GPSLatitude_m[0] / (float) $GPSLatitude_m[1]; + $GPSLat_s = (float) $GPSLatitude_s[0] / (float) $GPSLatitude_s[1]; + + $GPSLatGrad = $GPSLatfaktor * ($GPSLat_h + ($GPSLat_m + ($GPSLat_s / 60)) / 60); + + $GPSLongitude_h = explode("/", $GPSLongitude[0]); + $GPSLongitude_m = explode("/", $GPSLongitude[1]); + $GPSLongitude_s = explode("/", $GPSLongitude[2]); + $GPSLong_h = (float) $GPSLongitude_h[0] / (float) $GPSLongitude_h[1]; + $GPSLong_m = (float) $GPSLongitude_m[0] / (float) $GPSLongitude_m[1]; + $GPSLong_s = (float) $GPSLongitude_s[0] / (float) $GPSLongitude_s[1]; + $GPSLongGrad = $GPSLongfaktor * ($GPSLong_h + ($GPSLong_m + ($GPSLong_s / 60)) / 60); + + return [ + 'lat' => number_format($GPSLatGrad, 6, '.', ''), + 'long' => number_format($GPSLongGrad, 6, '.', ''), + ]; + } +} diff --git a/lib/Formatter/GeoDegree.php b/lib/Formatter/GeoDegree.php new file mode 100644 index 0000000..d681daa --- /dev/null +++ b/lib/Formatter/GeoDegree.php @@ -0,0 +1,108 @@ +getLatSuffix und getLongSuffix: + * + * Diese Funktionen sind dazu da, um in einem eigenen Formatter überschreiben werden zu können. Damit ist es möglich, + * der die Suffixe auch in anderer Sprache darstellen zu können. + * + * Als Beispiel: + * Für das Deutsche ist eigentlich nur wichtig, dass das E (für East) zu O (für Osten) wird. + * Im Niederländischen müsste aber auch das S (für South) zu einem Z (für Zuid) werden. + * + * Daher werden alle Himmelsrichtungen angepasst, auch wenn dadurch 'S' zu 'S' und 'W' zu 'W' gemappt wird. + * + * @author akrys + */ +class GeoDegree implements ArrayFormatterInterface +{ + + /** + * Formatierung der Daten + * @return array + * @throws Exception + */ + public function format(array $data): array + { + if (!isset($data['GPSLatitude']) || + !isset($data['GPSLatitudeRef']) || + !isset($data['GPSLongitude']) || + !isset($data['GPSLongitudeRef'])) { + throw new Exception('GPS not found'); + } + + $GPSLatitude = $data['GPSLatitude']; + $GPSLatitude_Ref = $data['GPSLatitudeRef']; + $GPSLongitude = $data['GPSLongitude']; + $GPSLongitude_Ref = $data['GPSLongitudeRef']; + + $latSuffix = $this->getLatSuffix($GPSLatitude_Ref); + + $longSuffix = $this->getLongSuffix($GPSLongitude_Ref); + + $GPSLatitude_h = explode("/", $GPSLatitude[0]); + $GPSLatitude_m = explode("/", $GPSLatitude[1]); + $GPSLatitude_s = explode("/", $GPSLatitude[2]); + + $GPSLat_h = (float) $GPSLatitude_h[0] / (float) $GPSLatitude_h[1]; + $GPSLat_m = (float) $GPSLatitude_m[0] / (float) $GPSLatitude_m[1]; + $GPSLat_s = (float) $GPSLatitude_s[0] / (float) $GPSLatitude_s[1]; + + $GPSLongitude_h = explode("/", $GPSLongitude[0]); + $GPSLongitude_m = explode("/", $GPSLongitude[1]); + $GPSLongitude_s = explode("/", $GPSLongitude[2]); + + $GPSLong_h = (float) $GPSLongitude_h[0] / (float) $GPSLongitude_h[1]; + $GPSLong_m = (float) $GPSLongitude_m[0] / (float) $GPSLongitude_m[1]; + $GPSLong_s = (float) $GPSLongitude_s[0] / (float) $GPSLongitude_s[1]; + + return [ + 'lat' => $GPSLat_h.'° '.$GPSLat_m."' ".$GPSLat_s.'" '.$latSuffix, + 'long' => $GPSLong_h.'° '.$GPSLong_m."' ".$GPSLong_s.'" '.$longSuffix, + ]; + } + + /** + * Umformung in deutsche Suffixe für Nord, Süd + * + * Als eigene Funktion, damit man via Ableitung der Klasse eigene Suffixe (für andere Sprachen) einsetzen kann. + * + * @return string + */ + public function getLatSuffix(string $GPSLatitude_Ref): string + { + return match ($GPSLatitude_Ref) { + 'S' => 'S', + 'N' => 'N', + default => $GPSLatitude_Ref, + }; + } + + /** + * Umformung in deutsche Suffixe für Ost, West + * + * Als eigene Funktion, damit man via Ableitung der Klasse eigene Suffixe (für andere Sprachen) einsetzen kann. + * + * @return string + */ + public function getLongSuffix(string $GPSLatitude_Ref): string + { + return match ($GPSLatitude_Ref) { + 'W' => 'W', + 'E' => 'O', + default => $GPSLatitude_Ref, + }; + } +} diff --git a/lib/Formatter/Interface/ArrayFormatterInterface.php b/lib/Formatter/Interface/ArrayFormatterInterface.php new file mode 100644 index 0000000..9662ace --- /dev/null +++ b/lib/Formatter/Interface/ArrayFormatterInterface.php @@ -0,0 +1,25 @@ + $exifData + * @return array + */ + public function format(array $exifData): array; +} diff --git a/lib/Formatter/Interface/FormatterInterface.php b/lib/Formatter/Interface/FormatterInterface.php new file mode 100644 index 0000000..962c02d --- /dev/null +++ b/lib/Formatter/Interface/FormatterInterface.php @@ -0,0 +1,22 @@ + $exifData + * @reutrn mixed + */ + public function format(array $exifData): mixed; +} diff --git a/lib/Formatter/Interface/StandardFormtterInterface.php b/lib/Formatter/Interface/StandardFormtterInterface.php new file mode 100644 index 0000000..d55c638 --- /dev/null +++ b/lib/Formatter/Interface/StandardFormtterInterface.php @@ -0,0 +1,23 @@ + $exifData + * @return string + */ + public function format(array $exifData): string; +} diff --git a/lib/MediapoolExif.php b/lib/MediapoolExif.php index 48ebd43..5f94ad4 100644 --- a/lib/MediapoolExif.php +++ b/lib/MediapoolExif.php @@ -1,12 +1,12 @@ zu tief verschachtelt.... vllt. Funktionsauslagerung? * @SuppressWarnings(PHPMD.IfStatementAssignment) * -> bei Datenbankabfragen kaum anders zu machen - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ public static function processUploadedMedia(rex_extension_point $exp): void { @@ -112,9 +112,11 @@ public static function processUploadedMedia(rex_extension_point $exp): void /** @phpstan-ignore-next-line */ if ($sql->setQuery($qry)) { $names = ''.join(', ', array_keys($update)).''; - $names = preg_replace_callback('/\>[a-z]/', function ($match) { - return strtoupper($match[0]); - }, $names); + $names = preg_replace_callback( + '/\>[a-z]/', function ($match) { + return strtoupper($match[0]); + }, $names + ); $msg = $exp->getParam('msg').'
    '.rex_i18n::msg('exif_data_updated').' '.$names; $exp->setParam('msg', $msg); @@ -183,8 +185,8 @@ public static function getDataByFilename(string $filename): array * @return array * @SuppressWarnings(PHPMD.ElseExpression) * -> zu tief verschachtelt.... vllt. Funktionsauslagerung? - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ public static function getData(rex_media $media, string $key = null): array { diff --git a/package.yml b/package.yml index 8807f75..4abcd4d 100644 --- a/package.yml +++ b/package.yml @@ -1,10 +1,10 @@ package: mediapool_exif -version: '3.0.2' +version: '3.1' author: 'FriendsOfREDAXO' supportpage: https://github.com/FriendsOfREDAXO/mediapool_exif console_commands: - mediapool_exif:read: '\FriendsOfRedaxo\addon\MediapoolExif\Cli\Read' + mediapool_exif:read: '\FriendsOfRedaxo\MediapoolExif\Cli\Read' requires: