Creates target filename base on source and transform

@param LocalSourceImageModel $source
@param array                 $transform

@return string
553497
private function createTargetFilename($source, $transform): string
    {
        /** @var ConfigModel $settings */
        $config = ImagerService::getConfig();

        $useFilenamePattern = $config->getSetting('useFilenamePattern', $transform);
        $hashFilename = $config->getSetting('hashFilename', $transform);
        $shortHashLength = $config->getSetting('shortHashLength', $transform);

        $basename = $source->basename;
        $extension = $source->extension;

        if (isset($transform['format'])) {
            $extension = $transform['format'];
            unset($transform['format']);
        }

        if ($extension === '') {
            // todo : detect from mime type?
        }

        $this->extension = $extension;

        $transformFileString = ImagerHelpers::createTransformFilestring($transform).$config->getConfigOverrideString();

        // If $useFilenamePattern is false, use old behavior with hashFilename config setting.
        if (!$useFilenamePattern) { 
            if ($hashFilename) {
                if (\is_string($hashFilename) && $hashFilename === 'postfix') {
                    return $basename.'_'.md5($transformFileString).'.'.$extension;
                }

                return md5($basename.$transformFileString).'.'.$extension;
            }

            return $basename.$transformFileString.'.'.$extension;
        }

        // New behavior, uses filenamePattern config setting. Much joy.
        $transformFileString = ltrim($transformFileString, '_');
        $fullname = $basename.'_'.$transformFileString;

        $patternFilename = $config->getSetting('filenamePattern', $transform);
        $patternFilename = mb_ereg_replace('{extension}', $extension, $patternFilename);
        $patternFilename = mb_ereg_replace('{basename}', $basename, $patternFilename);
        $patternFilename = mb_ereg_replace('{fullname}', $fullname, $patternFilename);
        $patternFilename = mb_ereg_replace('{transformString}', $transformFileString, $patternFilename);

        $patternFilename = mb_ereg_replace('{basename\|hash}', md5($basename), $patternFilename);
        $patternFilename = mb_ereg_replace('{fullname\|hash}', md5($fullname), $patternFilename);
        $patternFilename = mb_ereg_replace('{transformString\|hash}', md5($transformFileString), $patternFilename);

        $patternFilename = mb_ereg_replace('{basename\|shorthash}', substr(md5($basename), 0, $shortHashLength), $patternFilename);
        $patternFilename = mb_ereg_replace('{fullname\|shorthash}', substr(md5($fullname), 0, $shortHashLength), $patternFilename);
        $patternFilename = mb_ereg_replace('{transformString\|shorthash}', substr(md5($transformFileString), 0, $shortHashLength), $patternFilename);

        return $patternFilename;
    }
388250
private function getFilterMethod($transform): string
    {
        /** @var ConfigModel $settings */
        $config = ImagerService::getConfig();

        return ImagerService::$imageDriver === 'imagick' ? ImagerService::$filterKeyTranslate[(string)$config->getSetting('resizeFilter', $transform)] : ImageInterface::FILTER_UNDEFINED;
    }
106653
protected function getDestinationPath(Transformation $transformation)
    {
        $artifact = $transformation->getTransformer()->getTarget()
            . DIRECTORY_SEPARATOR . $transformation->getArtifact();

        return $artifact;
    }
525043
protected function getImageSource($source, array &$parameter)
    {
        $fragments  = preg_split('%:%', $source, -1, PREG_SPLIT_NO_EMPTY);
        $parameter['source'] = array_shift($fragments);
        $this->parseImageFilter($fragments, $parameter);
    }
1184355
static function  rebasedFilename($file,$from,$to) {
		if (!Strings::startsWith($file, $from)) {
			throw new \InvalidArgumentException("File $file is not in directory $from");
		}
		$secondPart=Strings::substring($file, Strings::length($from));
		if ($secondPart[0]=="/") $secondPart=substr($secondPart,1);
		$newPath=$to."/".$secondPart;
		return $newPath;
	}
1363809
public function generateFilename(DNDataTransfer $dataTransfer) {
		$generator = new RandomGenerator();
		$filter = FileNameFilter::create();

		return sprintf(
			'%s-%s-%s-%s-%s',
			$filter->filter(strtolower($this->OriginalEnvironment()->Project()->Name)),
			$filter->filter(strtolower($this->OriginalEnvironment()->Name)),
			$dataTransfer->Mode,
			date('Ymd'),
			sha1($generator->generateEntropy())
		);
	}
544273
public static function transform(array &$target, array $placeholders)
    {
        $wrap = function (string & $value) {
            $value = sprintf('/%s/', $value);
        };
        array_walk_recursive($target, function (&$param) use ($wrap, $placeholders) {
            if (!\is_string($param)) { return; }
            if (preg_match('/^const\((.*)\)$/', $param, $matches)) {
                $param = \constant($matches[1]);
            } elseif (preg_match_all('/%(.+?)%/', $param, $matches)) {
                array_walk($matches[0], $wrap);
                $pattern = $matches[0];
                $replacement = array_intersect_key($placeholders, array_flip($matches[1]));
                $param = preg_replace($pattern, $replacement, $param);
            }
        });
    }
935363
private function transformLayer(&$layer, $transform, $sourceExtension)
    {
        /** @var ConfigModel $settings */
        $config = ImagerService::getConfig();

        // Apply any pre resize filters
        if (isset($transform['preEffects'])) {
            $this->applyEffects($layer, $transform['preEffects']);
        }

        try {
            // Get size and crop information
            $originalSize = $layer->getSize();
            $cropSize = ImagerHelpers::getCropSize($originalSize, $transform, $config->getSetting('allowUpscale', $transform));
            $resizeSize = ImagerHelpers::getResizeSize($originalSize, $transform, $config->getSetting('allowUpscale', $transform));
            $filterMethod = $this->getFilterMethod($transform);

            // Do the resize
            if (ImagerService::$imageDriver === 'imagick' && $config->getSetting('smartResizeEnabled', $transform)) {
                /** @var ImagickImage $layer */
                $layer->smartResize($resizeSize, (bool)Craft::$app->config->general->preserveImageColorProfiles, $config->getSetting('jpegQuality', $transform));
            } else {
                $layer->resize($resizeSize, $filterMethod);
            }

            // Do the crop
            if (!isset($transform['mode']) || mb_strtolower($transform['mode']) === 'crop' || mb_strtolower($transform['mode']) === 'croponly') {
                $cropPoint = ImagerHelpers::getCropPoint($resizeSize, $cropSize, $config->getSetting('position', $transform));
                $layer->crop($cropPoint, $cropSize);
            }
        } catch (InvalidArgumentException $e) {
            throw new ImagerException($e->getMessage(), $e->getCode(), $e);
        } catch (RuntimeException $e) {
            throw new ImagerException($e->getMessage(), $e->getCode(), $e);
        }

        // Letterbox, add padding
        if (isset($transform['mode']) && mb_strtolower($transform['mode']) === 'letterbox') {
            $this->applyLetterbox($layer, $transform);
        }

        // Apply post resize effects
        if (isset($transform['effects'])) {
            $this->applyEffects($layer, $transform['effects']);
        }

        // Interlace if true
        if ($config->getSetting('interlace', $transform)) {
            $interlaceVal = $config->getSetting('interlace', $transform);

            if (\is_string($interlaceVal)) {
                $layer->interlace(ImagerService::$interlaceKeyTranslate[$interlaceVal]);
            } else {
                $layer->interlace(ImagerService::$interlaceKeyTranslate['line']);
            }
        }

        // Apply watermark if enabled
        if (isset($transform['watermark'])) {
            $this->applyWatermark($layer, $transform['watermark']);
        }

        // Apply background color if enabled and applicable
        if (($sourceExtension !== 'jpg') && ($config->getSetting('bgColor', $transform) !== '')) {
            $this->applyBackgroundColor($layer, $config->getSetting('bgColor', $transform));
        }
    }
1064112
private function transformSchema(array $source)
    {
        $name = isset($source['name']) ? $source['name'] : 'anon';
        // keys common to both swagger and guzzle
        static $common = [
            '$ref' => 1,
            'type' => 1,
            'name' => 1,
            'enum' => 1,
            'items' => 1,
            'format' => 1,
            'minimum' => 1,
            'maximum' => 1,
            'required' => 1,
            'minLength' => 1,
            'maxLength' => 1,
            'properties' => 1,
            'description' => 1,

        ];
        // keys requiring translation
        static $trans = [
            'paramType' => 'location',
            'defaultValue' => 'default',
        ];
        // initial translation
        $target = $this->transformArray($source, $common, $trans) + ['type' => ''];

        // validate Swagger refs now. Resolve later as appropriate.
        if (isset($target['$ref'])) {
            if ($this->hasModel($target['$ref']) === false) {
                throw new \RuntimeException('Encountered $ref to "'.$target['$ref'].'" in '.$name.' but model not registered');
            }
            unset($target['type']);
            return $target;
        }

        // Validate data type
        $type = null;

        // handle array of types entities
        if (isset($target['items'])) {
            $type = 'array';
            if ($type !== $target['type']) {
                $this->debug('! %s %s declares items, coercing to "%s"', $target['type'] ?: 'untyped', $name, $type);
                $target['type'] = $type;
            }
            // resolve model reference ensuring model exists
            if (isset($target['items']['$ref'])) {
                $ref = $target['items']['$ref'];
                if ($this->hasModel($ref) === false) {
                    throw new \RuntimeException('"'.$ref.'" encountered as items $ref but not defined as a model');
                }
            }
            // Else define a literal model definition on the fly. 
            // Guzzle will resolve back to literals on output, but it helps us resolve typed arrays and such
            else {
                if (isset($target['items']['type']) && $this->transformSimpleType($target['items']['type']) !== null) {
                    $target['items'] = $this->transformSchema($target['items']);
                } else {
                    $model = $this->addModel($target['items']);
                    $target['items'] = [
                        '$ref' => $model->getName(),
                    ];
                }
            }
        }

        // Recurse into object properties
        if (isset($source['properties'])) {
            $type = 'object';
            if ($type !== $target['type']) {
                $this->debug('! %s %s declares properties, coercing to "%s"', $target['type'] ?: 'untyped', $name, $type);
                $target['type'] = $type;
            }
            $target['properties'] = $this->transformParams($source['properties']);
            // required params are an external array in Swagger, but applied individually as boolean in Guzzle
            if (isset($source['required']) && is_array($source['required'])) {
                foreach ($source['required'] as $prop) {
                    if (isset($target['properties'][$prop])) {
                        $target['properties'][$prop]['required'] = true;
                    }
                }
            }
        }

        if ($type === null) {
            $type = $originalType = $target['type'];
            if ($type && $this->hasModel($type)) {
                // param type is registered model
                $target['$ref'] = $type;
                unset($target['type']);
                return $target;
            }
            // else handle as primitive type
            $frmt = isset($target['format']) ? $target['format'] : null;
            $type = $target['type'] = $this->transformSimpleType($type, $frmt);
            // else fall back to a sensible default
            if (!$type) {
                $this->debug('! type "%s" unknown, defaulting to null', $originalType);
                $type = $target['type'] = 'null';
            }
        }

        // Guzzle and swagger have minimal format overlap
        if (isset($target['format'])) {
            $target['format'] = $this->transformTypeFormat($target['format']);
        }

        // ensure properties is set even if empty, which makes little sense.
        if ('object' === $type && empty($target['properties'])) {
            $this->debug('! object %s has empty properties', $name);
            $target['properties'] = [];
        }

        return $target;
    }
793192
protected function writeSource($filename, array $source)
    {
        $source = str_replace(['  ', "\n"], ["\t", "\n\t"], var_export($source, true));
        $source = <<<FILE
<?php
	return $source;
FILE;

        return @file_put_contents($filename, $source) != 0;
    }
395852
public static function copy($source, $target)
    {
        if (false === is_dir($source)) {
            return copy($source, $target);
        }

        self::mkdir($target);

        $dirSource = dir($source);

        while (false !== ($fileEntry = $dirSource->read())) {
            if (true === in_array($fileEntry, self::getDirSymbols())) {
                continue;
            }

            if (false === self::copy(sprintf('%s/%s', $source, $fileEntry), sprintf('%s/%s', $target, $fileEntry))) {
                return false;
            }

        }

        $dirSource->close();

        return true;
    }
599346
public function thumbnail(&$source, $target, array $action)
    {
        list($width, $height) = $action['value'];

        if ($this->image->set($source)->thumbnail($width, $height)->save($target)) {
            $source = $target;
            return true;
        }

        return false;
    }
14218
private function getQualityFromExtension($ext, $transform = null): string
    {
        /** @var ConfigModel $settings */
        $config = ImagerService::getConfig();

        switch ($ext) {
            case 'png':
                $pngCompression = $config->getSetting('pngCompressionLevel', $transform);

                return max(100 - ($pngCompression * 10), 1);

            case 'webp':
                return $config->getSetting('webpQuality', $transform);
        }

        return $config->getSetting('jpegQuality', $transform);
    }
555840
public function map($source, &$target)
    {
        $source = static::makeSource($source);
        $writer = static::makeWriter($target);

        foreach ($this->fields as $field) {
            try {
                $writer::set($target, $field->getName(), $field->getDefinition()->getValue($source));
            } catch (SourceFieldMissingException $e) {
                if ($this->ignoreAllMissing) {
                    continue;
                }
                throw $e;
            } catch (IgnoreFieldException $e) {
                continue;
            }
        }
    }
1090054
public static function copy($source, $target, $ignore = null)
    {
        $source = rtrim($source, '\\/');
        $target = rtrim($target, '\\/');

        if (!is_dir($source)) {
            throw new \RuntimeException('Cannot copy non-existing folder.');
        }

        // Make sure that path to the target exists before copying.
        self::create($target);

        $success = true;

        // Go through all sub-directories and copy everything.
        $files = self::all($source);
        foreach ($files as $file) {
            if ($ignore && preg_match($ignore, $file)) {
                continue;
            }
            $src = $source .'/'. $file;
            $dst = $target .'/'. $file;

            if (is_dir($src)) {
                // Create current directory (if it doesn't exist).
                if (!is_dir($dst)) {
                    $success &= @mkdir($dst, 0777, true);
                }
            } else {
                // Or copy current file.
                $success &= @copy($src, $dst);
            }
        }

        if (!$success) {
            $error = error_get_last();
            throw new \RuntimeException($error['message'] ?? 'Unknown error');
        }

        // Make sure that the change will be detected when caching.
        @touch(dirname($target));
    }
76860
protected function extractSourceFilename($source)
    {
        $sourceFIle = preg_replace("/'/", "", $source[1]);
        if (preg_match('/\#/', $sourceFIle)) {
            $sourceFIle = explode("#", $sourceFIle);
            $sourceFIle = $sourceFIle[0];
        }
        if (preg_match('/\?/', $sourceFIle)) {
            $sourceFIle = explode("?", $sourceFIle);
            $sourceFIle = $sourceFIle[0];
            return $sourceFIle;
        }
        return $sourceFIle;
    }
637793
public function moveImage($source, $dest)
    {
        $dir = dirname($dest);
        if(!file_exists($dir)){
            mkdir($dir, 0755, true);
        }
        return rename($source, $dest);
    }