<commit_before><?php
namespace verbb\feedme\fields;

use verbb\feedme\FeedMe;
use verbb\feedme\base\Field;
use verbb\feedme\base\FieldInterface;
use verbb\feedme\helpers\BaseHelper;
use verbb\feedme\helpers\DateHelper;

use Craft;
use craft\helpers\Localization;

use Cake\Utility\Hash;

class Table extends Field implements FieldInterface
{
    // Properties
    // =========================================================================

    public static $name = 'Table';
    public static $class = 'craft\fields\Table';


    // Templates
    // =========================================================================

    public function getMappingTemplate()
    {
        return 'feed-me/_includes/fields/table';
    }


    // Public Methods
    // =========================================================================

    public function parseField()
    {
        $parsedData = [];
        $preppedData = [];
        $rowCounter = [];

        $columns = Hash::get($this->fieldInfo, 'fields');

        foreach ($this->feedData as $nodePath => $value) {
            foreach ($columns as $columnHandle => $columnInfo) {

                // Strip out array numbers in the feed path like: MatrixBlock/0/Images/0. We use this to get the field
                // its supposed to match up with, which is stored in the DB like MatrixBlock/Images
                $feedPath = preg_replace('/(\/\d+\/)/', '/', $nodePath);
                $feedPath = preg_replace('/^(\d+\/)|(\/\d+)/', '', $feedPath);

                $node = Hash::get($columnInfo, 'node');
                $handle = Hash::get($columnInfo, 'handle');
                $type = Hash::get($columnInfo, 'type');

                if ($feedPath == $node || $nodePath == $node) {
                    if (!isset($rowCounter[$columnHandle])) {
                        $rowCounter[$columnHandle] = 0;
                    } else {
                        $rowCounter[$columnHandle]++;
                    }

                    $parsedValue = $this->_handleSubField($type, $value);

                    $parsedData[$rowCounter[$columnHandle]][$columnHandle] = $parsedValue;
                }
            }
        }

        $dataDelimiter = FeedMe::$plugin->service->getConfig('dataDelimiter') ?? '|';

        foreach ($parsedData as $rowKey => $row) {
            foreach ($row as $columnKey => $column) {
                if (is_string($column)) {
                    $columnValues = explode($dataDelimiter, $column);

                    if (count($columnValues) > 1) {
                        foreach ($columnValues as $splitRowKey => $columnValue) {
                            $preppedData[$splitRowKey][$columnKey] = $columnValue;
                        }
                    } else {
                        $preppedData[$rowKey][$columnKey] = $column;
                    }
                } else {
                    $preppedData[$rowKey][$columnKey] = $column;
                }
            }
        }

        // Fix keys for columns to be in correct order
        foreach ($preppedData as $key => &$columnData) {
            ksort($columnData, SORT_NATURAL);
        }

        return $preppedData;
    }


    // Private Methods
    // =========================================================================

    private function _handleSubField($type, $value)
    {
        if ($type == 'checkbox') {
            return BaseHelper::parseBoolean($value);
        } else if ($type == 'color') {

        } else if ($type == 'date') {
            return DateHelper::parseString($value);
        } else if ($type == 'lightswitch') {
            return BaseHelper::parseBoolean($value);
        } else if ($type == 'multiline') {

        } else if ($type == 'number') {
            return Localization::normalizeNumber($value);
        } else if ($type == 'singleline') {

        } else if ($type == 'time') {

        }

        return $value;
    }

}<commit_msg>Table - protect against array values importing into fields<commit_after><?php
namespace verbb\feedme\fields;

use verbb\feedme\FeedMe;
use verbb\feedme\base\Field;
use verbb\feedme\base\FieldInterface;
use verbb\feedme\helpers\BaseHelper;
use verbb\feedme\helpers\DateHelper;

use Craft;
use craft\helpers\Localization;

use Cake\Utility\Hash;

class Table extends Field implements FieldInterface
{
    // Properties
    // =========================================================================

    public static $name = 'Table';
    public static $class = 'craft\fields\Table';


    // Templates
    // =========================================================================

    public function getMappingTemplate()
    {
        return 'feed-me/_includes/fields/table';
    }


    // Public Methods
    // =========================================================================

    public function parseField()
    {
        $parsedData = [];
        $preppedData = [];
        $rowCounter = [];

        $columns = Hash::get($this->fieldInfo, 'fields');

        foreach ($this->feedData as $nodePath => $value) {
            foreach ($columns as $columnHandle => $columnInfo) {

                // Strip out array numbers in the feed path like: MatrixBlock/0/Images/0. We use this to get the field
                // its supposed to match up with, which is stored in the DB like MatrixBlock/Images
                $feedPath = preg_replace('/(\/\d+\/)/', '/', $nodePath);
                $feedPath = preg_replace('/^(\d+\/)|(\/\d+)/', '', $feedPath);

                $node = Hash::get($columnInfo, 'node');
                $handle = Hash::get($columnInfo, 'handle');
                $type = Hash::get($columnInfo, 'type');

                if ($feedPath == $node || $nodePath == $node) {
                    if (!isset($rowCounter[$columnHandle])) {
                        $rowCounter[$columnHandle] = 0;
                    } else {
                        $rowCounter[$columnHandle]++;
                    }

                    $parsedValue = $this->_handleSubField($type, $value);

                    $parsedData[$rowCounter[$columnHandle]][$columnHandle] = $parsedValue;
                }
            }
        }

        $dataDelimiter = FeedMe::$plugin->service->getConfig('dataDelimiter') ?? '|';

        foreach ($parsedData as $rowKey => $row) {
            foreach ($row as $columnKey => $column) {
                if (is_string($column)) {
                    $columnValues = explode($dataDelimiter, $column);

                    if (count($columnValues) > 1) {
                        foreach ($columnValues as $splitRowKey => $columnValue) {
                            $preppedData[$splitRowKey][$columnKey] = $columnValue;
                        }
                    } else {
                        $preppedData[$rowKey][$columnKey] = $column;
                    }
                } else {
                    $preppedData[$rowKey][$columnKey] = $column;
                }
            }
        }

        // Fix keys for columns to be in correct order
        foreach ($preppedData as $key => &$columnData) {
            ksort($columnData, SORT_NATURAL);
        }

        return $preppedData;
    }


    // Private Methods
    // =========================================================================

    private function _handleSubField($type, $value)
    {
        if ($type == 'checkbox') {
            return BaseHelper::parseBoolean($value);
        } else if ($type == 'color') {

        } else if ($type == 'date') {
            return DateHelper::parseString($value);
        } else if ($type == 'lightswitch') {
            return BaseHelper::parseBoolean($value);
        } else if ($type == 'multiline') {

        } else if ($type == 'number') {
            return Localization::normalizeNumber($value);
        } else if ($type == 'singleline') {

        } else if ($type == 'time') {

        }

        // Protect against array values
        if (is_array($value)) {
            $value = '';
        }

        return $value;
    }

}
{'fraction_non_alphanumeric': 0.20198881292728402, 'fraction_numerical': 0.0009944064636420136, 'mean_word_length': 1.9120521172638436, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, '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': '5860495', 'n_tokens_mistral': 2129, 'n_tokens_neox': 1992, 'n_words': 456}