<commit_before><?php

namespace Napp\Core\Api\Transformers;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class ApiTransformer implements TransformerInterface
{
    /**
     * @var array
     */
    protected $apiMapping = [];

    /**
     * Strict mode removes keys that are
     * not specified in api mapping array.
     *
     * @var bool
     */
    protected $strict = false;

    /**
     * @param array|Model $apiMapping
     * @return void
     */
    public function setApiMapping($apiMapping)
    {
        $this->apiMapping = [];

        if (true === $apiMapping instanceof Model && true === property_exists($apiMapping, 'apiMapping')) {
            $this->apiMapping = $apiMapping->apiMapping;
        } elseif (true === \is_array($apiMapping)) {
            $this->apiMapping = $apiMapping;
        }
    }

    /**
     * @param array|Arrayable $data
     * @return array
     */
    public function transformInput($data): array
    {
        $input = [];

        $data = (true === \is_array($data)) ? $data : $data->toArray();
        foreach ($data as $key => $value) {
            $input[$this->findOriginalKey($key)] = $value;
        }

        return $input;
    }

    /**
     * @param array|Arrayable $data
     * @return array
     */
    public function transformOutput($data): array
    {
        $output = [];

        if (true === $data instanceof Collection) {
            foreach ($data as $item) {
                $output[] = $this->transformOutput($item);
            }
        } else {
            $data = (true === \is_array($data)) ? $data : $data->toArray();
            foreach ($data as $key => $value) {
                if (true === $this->strict && false === array_key_exists($key, $this->apiMapping)) {
                    continue;
                }
                $output[$this->findNewKey($key)] = $this->convertValueType($key, $value);
            }
        }

        return $output;
    }

    /**
     * @param string $newKey
     * @return string
     */
    protected function findOriginalKey(string $newKey)
    {
        foreach ($this->apiMapping as $key => $value) {
            if (true === \in_array($newKey, $value)) {
                return $key;
            }
        }

        return $newKey;
    }

    /**
     * @param string $originalKey
     * @return string
     */
    protected function findNewKey(string $originalKey): string
    {
        if (true === array_key_exists($originalKey, $this->apiMapping)) {
            return $this->apiMapping[$originalKey]['newName'];
        }

        return $originalKey;
    }

    /**
     * @param string $key
     * @param mixed $value
     * @return mixed
     */
    protected function convertValueType(string $key, $value)
    {
        $type = (true === array_key_exists($key, $this->apiMapping))
            ? $this->apiMapping[$key]['dataType']
            : 'string';

        foreach (static::normalizeType($type) as list($method, $parameters)) {
            if (true === empty($method)) {
                return $value;
            }

            if ('Nullable' === $method) {
                if (true === empty($value)) {
                    return null;
                }

                continue;
            }

            $method = "convert{$method}";

            if (false === method_exists(TransformerMethods::class, $method)) {
                return $value;
            }

            return TransformerMethods::$method($value, $parameters);
        }
    }

    protected static function parseStringDataType($type): array
    {
        $parameters = [];

        // The format for specifying validation rules and parameters follows an
        // easy {rule}:{parameters} formatting convention. For instance the
        // rule "Max:3" states that the value may only be three letters.
        if (mb_strpos($type, ':') !== false) {
            list($dataType, $parameter) = explode(':', $type, 2);

            $parameters = static::parseParameters($parameter);
        }

        $dataType = static::normalizeDataType(trim($dataType ?? $type));

        return [Str::studly($dataType), $parameters ?? []];
    }

    /**
     * Parse a parameter list.
     *
     * @param  string  $parameter
     * @return array
     */
    protected static function parseParameters($parameter): array
    {
        return str_getcsv($parameter);
    }

    protected static function parseManyDataTypes($type): array
    {
        $parsed = [];

        $dataTypes = explode('|', $type);

        foreach ($dataTypes as $dataType) {
            $parsed[] = static::parseStringDataType(trim($dataType));
        }

        return $parsed;
    }

    protected static function normalizeType($type): array
    {
        if (false !== mb_strpos($type, '|')) {
            return self::normalizeNullable(
                static::parseManyDataTypes($type)
            );
        }

        return [static::parseStringDataType($type)];
    }

    /**
     * @param $type
     * @return bool
     */
    protected static function hasParameters($type): bool
    {
        return false !== mb_strpos($type, ':');
    }

    /**<commit_msg>Correct docblock in code.<commit_after><?php

namespace Napp\Core\Api\Transformers;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class ApiTransformer implements TransformerInterface
{
    /**
     * @var array
     */
    protected $apiMapping = [];

    /**
     * Strict mode removes keys that are
     * not specified in api mapping array.
     *
     * @var bool
     */
    protected $strict = false;

    /**
     * @param array|Model $apiMapping
     * @return void
     */
    public function setApiMapping($apiMapping)
    {
        $this->apiMapping = [];

        if (true === $apiMapping instanceof Model && true === property_exists($apiMapping, 'apiMapping')) {
            $this->apiMapping = $apiMapping->apiMapping;
        } elseif (true === \is_array($apiMapping)) {
            $this->apiMapping = $apiMapping;
        }
    }

    /**
     * @param array|Arrayable $data
     * @return array
     */
    public function transformInput($data): array
    {
        $input = [];

        $data = (true === \is_array($data)) ? $data : $data->toArray();
        foreach ($data as $key => $value) {
            $input[$this->findOriginalKey($key)] = $value;
        }

        return $input;
    }

    /**
     * @param array|Arrayable $data
     * @return array
     */
    public function transformOutput($data): array
    {
        $output = [];

        if (true === $data instanceof Collection) {
            foreach ($data as $item) {
                $output[] = $this->transformOutput($item);
            }
        } else {
            $data = (true === \is_array($data)) ? $data : $data->toArray();
            foreach ($data as $key => $value) {
                if (true === $this->strict && false === array_key_exists($key, $this->apiMapping)) {
                    continue;
                }
                $output[$this->findNewKey($key)] = $this->convertValueType($key, $value);
            }
        }

        return $output;
    }

    /**
     * @param string $newKey
     * @return string
     */
    protected function findOriginalKey(string $newKey)
    {
        foreach ($this->apiMapping as $key => $value) {
            if (true === \in_array($newKey, $value)) {
                return $key;
            }
        }

        return $newKey;
    }

    /**
     * @param string $originalKey
     * @return string
     */
    protected function findNewKey(string $originalKey): string
    {
        if (true === array_key_exists($originalKey, $this->apiMapping)) {
            return $this->apiMapping[$originalKey]['newName'];
        }

        return $originalKey;
    }

    /**
     * @param string $key
     * @param mixed $value
     * @return mixed
     */
    protected function convertValueType(string $key, $value)
    {
        $type = (true === array_key_exists($key, $this->apiMapping))
            ? $this->apiMapping[$key]['dataType']
            : 'string';

        foreach (static::normalizeType($type) as list($method, $parameters)) {
            if (true === empty($method)) {
                return $value;
            }

            if ('Nullable' === $method) {
                if (true === empty($value)) {
                    return null;
                }

                continue;
            }

            $method = "convert{$method}";

            if (false === method_exists(TransformerMethods::class, $method)) {
                return $value;
            }

            return TransformerMethods::$method($value, $parameters);
        }
    }

    protected static function parseStringDataType($type): array
    {
        $parameters = [];

        // The format for transforming data-types and parameters follows an
        // easy {data-type}:{parameters} formatting convention. For instance the
        // data-type "float:3" states that the value will be converted to a float with 3 decimals.
        if (mb_strpos($type, ':') !== false) {
            list($dataType, $parameter) = explode(':', $type, 2);

            $parameters = static::parseParameters($parameter);
        }

        $dataType = static::normalizeDataType(trim($dataType ?? $type));

        return [Str::studly($dataType), $parameters ?? []];
    }

    /**
     * Parse a parameter list.
     *
     * @param  string  $parameter
     * @return array
     */
    protected static function parseParameters($parameter): array
    {
        return str_getcsv($parameter);
    }

    protected static function parseManyDataTypes($type): array
    {
        $parsed = [];

        $dataTypes = explode('|', $type);

        foreach ($dataTypes as $dataType) {
            $parsed[] = static::parseStringDataType(trim($dataType));
        }

        return $parsed;
    }

    protected static function normalizeType($type): array
    {
        if (false !== mb_strpos($type, '|')) {
            return self::normalizeNullable(
                static::parseManyDataTypes($type)
            );
        }

        return [static::parseStringDataType(trim($type))];
    }

    /**
     * @param $type
     * @return bool
     */
    protected static function hasParameters($type): bool
    {
        return false !== mb_strpos($type, ':');
    }

    /**
{'fraction_non_alphanumeric': 0.14119207808206197, 'fraction_numerical': 0.000473798919738463, 'mean_word_length': 1.9066372900027542, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2346636', 'n_tokens_mistral': 2926, 'n_tokens_neox': 2851, 'n_words': 656}