<?php
namespace Moto\Filter; use Moto; use Closure; class SanitizeFileName extends Moto\Filter\AbstractFilter { const FILE_NAME = 'name'; const FILE_EXTENSION = 'extension'; const DEFAULT_NAME = 'file'; const DEFAULT_EXTENSION = 'tmp'; protected static $_defaultGenerators = [ 'transliterator' => null, 'valueGenerator' => null, ]; protected $_options = [ 'transliterator' => null, 'valueGenerator' => null, 'generateName' => true, 'generateExtension' => false, ]; protected $_value; public function setTransliteratorGenerator($value = null) { if ($value === null || $value instanceof Closure) { $this->_options['transliterator'] = $value; return $this; } throw new \InvalidArgumentException('Option "transliterator" : invalid value'); } public function setValueGenerator($value = null) { if ($value === null || $value instanceof Closure) { $this->_options['valueGenerator'] = $value; return $this; } throw new \InvalidArgumentException('Option "valueGenerator" : invalid value'); } public function setGenerateName($value) { $this->_options['generateName'] = (boolean) $value; return $this; } public function setGenerateExtension($value) { $this->_options['generateExtension'] = (boolean) $value; return $this; } public function filter($value) { if (!is_string($value)) { return null; } $value = trim($value); $value = trim($value, '.'); if ($value === '') { return null; } $value = Moto\Util::sanitizePath($value); if (strpos($value, '/') !== false) { return null; } $this->_value = $value; $info = pathinfo($value); return $this->sanitizeValue($info['filename'], static::FILE_NAME) . '.' . $this->sanitizeValue(Moto\Util::getValue($info, 'extension', ''), static::FILE_EXTENSION); } protected function sanitizeValue($value, $part) { if (!is_string($value)) { return null; } $transliterator = $this->getTransliterator(); $value = $transliterator($value, $part); $value = preg_replace('/[^a-z0-9_\-\.]/i', '', $value); $value = preg_replace('/([_\-\.])(\\1+)/', '$1', $value); $value = trim($value); $value = strtolower($value); if ($part && $value === '' && $this->getOption('generate' . ucfirst(strtolower($part)))) { $generator = $this->getValueGenerator(); $value = trim((string) $generator($this->_value, $part)); $value = $this->sanitizeValue($value, null); if ($value === '' && $part === static::FILE_NAME) { throw new \RuntimeException('Value generator return empty value for file name'); } } return $value; } protected function getTransliterator() { $generator = $this->getOption('transliterator'); if (!$generator) { $generator = $this->getDefaultTransliterator(); } return $generator; } protected function getDefaultTransliterator() { if (!static::$_defaultGenerators['transliterator']) { static::$_defaultGenerators['transliterator'] = function ($value) { $filter = new Moto\Filter\Transliterate(); return $filter->filter($value); }; } return static::$_defaultGenerators['transliterator']; } protected function getValueGenerator() { $generator = $this->getOption('valueGenerator'); if (!$generator) { $generator = $this->getDefaultValueGenerator(); } return $generator; } protected function getDefaultValueGenerator() { if (!static::$_defaultGenerators['valueGenerator']) { static::$_defaultGenerators['valueGenerator'] = function ($value, $part) { if ($part === static::FILE_EXTENSION) { return static::DEFAULT_EXTENSION; } $value = trim($value); if ($value === '') { return static::DEFAULT_NAME; } return static::DEFAULT_NAME . '_' . substr(md5($value), 0, 8); }; } return static::$_defaultGenerators['valueGenerator']; } } 