Generate values for multiple columns

@param mixed $value
@param string $error_name
@param array $values
@param array $parent_keys
@param array $options
@return array
766220
public function generateMultipleColumns($value, $error_name, $values, $parent_keys, $options = []) {
		if (!empty($value)) {
			if (!is_array($value)) {
				$value = [$value];
			}
			$result = [];
			$fields_key_holder = [];
			$this->generateDetailsPrimaryKey($fields_key_holder, 'reset', $values, $parent_keys, $options);
			foreach ($value as $k2 => $v2) {
				if (is_array($v2) && isset($v2[$options['options']['multiple_column']])) {
					$v2 = $v2[$options['options']['multiple_column']];
				}
				$temp = $this->validateDataTypesSingleValue($options['options']['multiple_column'], $options, $v2, $error_name);
				if (empty($temp['flag_error'])) {
					$temp_value_new = [
						$options['options']['multiple_column'] => $temp[$options['options']['multiple_column']]
					];
				} else {
					$temp_value_new = [
						$options['options']['multiple_column'] => $v2
					];
				}
				// process pk
				$this->generateDetailsPrimaryKey($fields_key_holder, 'pk', $temp_value_new, $parent_keys, $options);
				$k2 = $fields_key_holder['pk'];
				$result[$k2] = array_merge_hard($fields_key_holder['parent_pks'], $temp_value_new);
			}
			return $result;
		} else {
			return [];
		}
	}
19462
public function apply($value, $options = [])
    {
        $type = isset($options[0]) ? $options[0] : null;
        switch ($type) {
            case 'int':
            case 'integer':
                return (int) $value;
            case 'real':
            case 'float':
            case 'double':
                return (float) $value;
            case 'string':
                return (string) $value;
            case 'bool':
            case 'boolean':
                return (bool) $value;
            case 'object':
                return is_array($value) ? (object) $value : json_decode($value, false);
            case 'array':
                return json_decode($value, true);
            case 'collection':
                $array = is_array($value) ? $value : json_decode($value, true);
                return new Collection($array);
            default:
                throw new \InvalidArgumentException("Wrong Sanitizer casting format: {$type}.");
        }
    }
338759
public function renderListContainerDefaultOptions(array $options, $value, $neighbouring_values = []) {
		if (strpos($options['options_model'], '::') === false) $options['options_model'].= '::options';
		$params = $options['options_params'] ?? [];
		if (!empty($options['options_depends'])) {
			foreach ($options['options_depends'] as $k9 => $v9) {
				$params[$k9] = $neighbouring_values[$v9];
			}
		}
		$hash = sha1($options['options_model'] . serialize($params));
		if (!isset($this->cached_options[$hash])) {
			$method = \Factory::method($options['options_model'], null, true);
			$this->cached_options[$hash] = call_user_func_array($method, [['where' => $params, 'i18n' => true, 'skip_acl' => true]]); // skip acl is a must
		}
		if (is_array($value)) {
			$temp = [];
			foreach ($value as $v) {
				if (isset($this->cached_options[$hash][$v]['name'])) {
					$temp[]= $this->cached_options[$hash][$v]['name'];
				}
			}
			return implode(\Format::$symbol_comma . ' ', $temp);
		} else {
			return $this->cached_options[$hash][$value]['name'] ?? null;
		}
	}
966144
public function create ($table_name, array $values = [], array $options = []) {
		if (isset($options['create_filter']) && is_callable($options['create_filter'])) {
			$values = $options['create_filter']($values);
		}

		$columns = $this->getColumns($table_name);

		$column_name_list = array_keys($values[0]);
		$query = sprintf(
			'INSERT INTO %s (%s%s%s) VALUES (%s)',
			$table_name,
			static::IDENTIFIER,
			implode(static::IDENTIFIER.', '.static::IDENTIFIER, $column_name_list),
			static::IDENTIFIER,
			implode(', ', array_fill(0, count($column_name_list), '?'))
		);

		$ret = [];

//@TODO mode setting
		$log_flag = false;
		$execute_time = microtime(true);
		try {
			$stmt = $this->prepare($query);
			foreach ($values as $value) {
				$i = 1;
				foreach ($value as $column_name => $column_value) {
					$stmt->bindValue($i++, $column_value, $columns[$column_name]['pdo_param']);
				}
				if (!$stmt->execute()) {
					//@TODO mode setting
					if ($log_flag) {
						$execute_end_time = microtime(true);

						$parsed_execute_time = explode('.', $execute_time);

						$debug_dump_params = '';
						if ($log_flag) {
							ob_start();
							$stmt->debugDumpParams();
							$debug_dump_params = ob_get_clean();
						}

						$query_string = $stmt->queryString;

						$message = sprintf('[%s.%-4d] execute_time:%s query_string:%s dump:%s', date('Y-m-d H:i:s', $parsed_execute_time[0]), $parsed_execute_time[1], $execute_end_time - $execute_time, $query_string, $debug_dump_params);
						//				StaticLog::WriteLog('sql_log', $message);
						print $message;
					}
				}
				$ret[] = $this->lastInsertId();
			}
		} catch (\PDOException $pdo_e) {
			$execute_end_time = microtime(true);

			$parsed_execute_time = explode('.', $execute_time);

			$error_info = $stmt->errorInfo();

			//@TODO mode setting
			$debug_dump_params = '';
			if ($log_flag) {
				ob_start();
				$stmt->debugDumpParams();
				$debug_dump_params = ob_get_clean();
			}
			$query_string = $stmt->queryString;

			$message = sprintf(
					'[%s.%-4d] execute_time:%s SQLSTATE:%s code:%s message:%s query_string:%s dump:%s',
					date('Y-m-d H:i:s', $parsed_execute_time[0]),
					$parsed_execute_time[1],
					$execute_end_time - $execute_time,
					$error_info[0],
					$error_info[1],
					$error_info[2],
					$query_string,
					$debug_dump_params
			);
//print $message;
			StaticLog::WriteLog('sql_error', $message);

			throw $pdo_e;
		}

		return $ret;
	}
1292167
public static function Rule ($rule_name, $value, $options = [], $meta = []) {
		$rule_list = static::GetValidateRuleList();
		if ($rule = $rule_list[$rule_name] ?? false) {
			return (is_callable($rule[0]) || is_array($rule[0])) ? $rule[0]($value, $options, $meta) : preg_match($rule[0], $value) === 1;
		}
		throw CoreException::RaiseSystemError('Validation not found. Rule name:%s', [$rule_name]);
	}
27113
public function formatErrors(array $errors)
   {
      $tmp = [];
      $len = count($errors);
      if ($len === 0) {
         throw new InvalidArgumentException(
            "invalid value provided for 'errors'; expecting an array that ".
            "contains at least one instance of sndsgd\\field\\Error"
         );
      }

      $noun = ($len === 1) ? 'option' : 'options';
      $tmp = ["failed to process $noun"];
      foreach ($errors as $error) {
         $name = $error->getName();
         $message = $error->getMessage();
         if (!array_key_exists($name, $tmp)) {
            $tmp[$name] = " @[bold]$name@[reset] → $message";
         }
      }
      return implode(PHP_EOL, array_values($tmp)).PHP_EOL;
   }
386083
public function setValues($table_name, $id_row, Array $values)
	{
		$column_names = [];
		foreach ($values as $id_language=>$fields)
		{
			$column_names = array_merge($column_names, array_keys($fields));
		}
		$column_names = array_unique($column_names);
		if (sizeof($column_names) == 0) return;
		
		$resources = Resource::where('table_name', $table_name)
			->where('id_row', $id_row)
			->whereIn('column_name', $column_names)
			->get();
		
		foreach ($values as $id_language=>$value_item)
		{
			foreach ($value_item as $column_name=>$value)
			{
				$found = false;
				foreach ($resources as $resource)
				{
					if ($column_name == $resource->column_name && $id_language == $resource->id_language)
					{
						$resource->value = $value;
						$resource->save();
						
						$found = true;
						break;
					}
				}
				
				if (!$found)
				{
					$resource = new Resource();
					$resource->id_language = $id_language;
					$resource->table_name  = $table_name;
					$resource->column_name = $column_name;
					$resource->value       = $value;
					$resource->id_row      = $id_row;
					$resource->save();
				}
			}
		}
	}
633179
public function label($name, $value = null, $options = [])
    {
        return parent::label($name, $value, $this->appendErrors($name, $options));
    }
770981
public function parentKeysToErrorName($parent_keys) {
		$result = [];
		if (!is_array($parent_keys)) {
			$parent_keys = [$parent_keys];
		}
		foreach ($parent_keys as $v) {
			if (empty($result)) {
				$result[] = $v;
			} else {
				$result[] = '[' . $v . ']';
			}
		}
		return implode('', $result);
	}
632418
public function create ($table_name, array $values = [], array $options = []) {
		if (isset($options['create_filter']) && is_callable($options['create_filter'])) {
			$values = $options['create_filter']($values);
		}

		$column_name_list = array_keys($values[0]);
		$query = sprintf(
 			'INSERT INTO %s (%s%s%s) VALUES (%s)',
 			$table_name,
			static::IDENTIFIER,
 			implode(static::IDENTIFIER.', '.static::IDENTIFIER, $column_name_list),
			static::IDENTIFIER,
 			implode(', ', array_fill(0, count($column_name_list), '?'))
 		);

 		$ret = [];
 		try {
			$stmt = $this->prepare($query);
			foreach ($values as $value) {
				$i = 1;
				foreach ($value as $column_name => $column_value) {
					$stmt->bindValue($i++, $column_value);
				}
				if (!$stmt->execute()) {
					//
				}
				$ret[] = $this->lastInsertId();
			}
		} catch (\PDOException $pdo_e) {
			StaticLog::WriteLog('sql_error', implode(', ', $this->errorInfo()));

			StaticLog::WriteLog('sql_error', serialize($values));

			throw $pdo_e;
		}

		return $ret;
	}
1324977
public function errors($options = [])
    {
        $errors = [];
        $errored = false;
        foreach ($this as $entity) {
            $result = $entity->errors($options);
            $errors[] = $result;
            if ($result) {
                $errored = true;
            }
        }
        return $errored ? $errors : [];
    }
758274
public function textarea($name, $value = null, $options = [])
    {
        $this->addErrorClass($name, $options);
        $tags['input'] = parent::textarea($name, $value, $options);
        $tags['error'] = $this->getErrorTag($name);
        return $this->buildTags($tags);
    }
343101
public static function GetExtraReplaceValues ($rule_name, $value, array $options) {
		$rule_set = static::GetValidateRuleList()[$rule_name];
		if (!isset($rule_set[2])) {
			return [];
		}

		$rule_set = $rule_set[2];
		if (!is_array($rule_set)) {
			return [];
		}
		foreach ($rule_set as $rule_name => $replacement) {
			$rule_set[$rule_name] = (is_callable($replacement)) ? $replacement($value, $options) : $value;
		}
		return $rule_set;
	}
1298404
public function errors($options = [])
    {
        $defaults = ['embed' => true];
        $options += $defaults;

        if ($options['embed'] === true) {
            $options['embed'] = $this->hierarchy();
        }

        $schema = static::schema();
        $tree = $schema->treeify($options['embed']);
        $errors = $this->_errors;

        foreach ($tree as $field => $value) {
            if (!isset($this->{$field})) {
                continue;
            }
            $value = $value ? $value : ['embed' => false];
            if ($err = $this->{$field}->errors($value + $options)) {
                $errors[$field] = $err;
            }
        }
        return $errors;
    }
21594
public static function createFromArray($values, array $options = [])
    {
        $document = new static($options);
        foreach ($values as $key => $value) {
            $document->set($key, $value);
        }

        $document->setChanged(true);

        return $document;
    }
453790
private function checkOptionsModel(array $field, $value, string $error_name, array $neighbouring_values) {
		// we need to convert value
		if (!empty($field['json_contains'])) {
			$temp = [];
			foreach ($field['json_contains'] as $k31 => $v31) {
				$temp[$k31] = $neighbouring_values[$v31];
			}
			$value = \Object\Table\Options::optionJsonFormatKey($temp);
		}
		if (is_string($value) && $value === '') return;
		if (is_array($value) && empty($value)) return;
		if (empty($field['options_params'])) $field['options_params'] = [];
		if (empty($field['options_options'])) $field['options_options'] = [];
		$field['options_options']['i18n'] = false;
		if (empty($field['options_depends'])) $field['options_depends'] = [];
		// options depends & params
		$options = [];
		$this->processParamsAndDepends($field['options_depends'], $neighbouring_values, $options, true);
		$this->processParamsAndDepends($field['options_params'], $neighbouring_values, $options, false);
		$field['options_params'] = array_merge_hard($field['options_params'], $field['options_depends']);
		// call override method
		if (!empty($this->wrapper_methods['processOptionsModels']['main'])) {
			$model = $this->wrapper_methods['processOptionsModels']['main'][0];
			$model->{$this->wrapper_methods['processOptionsModels']['main'][1]}($this, $field['name'], $field['details_key'] ?? null, $field['details_parent_key'] ?? null, $field['options_params'], $neighbouring_values, [/* todo: __detail_values */]);
		}
		// we do not need options for autocomplete
		if (strpos(($field['method'] ?? ''), 'autocomplete') === false) {
			$skip_values = [];
			$existing_values = $value;
			if (!empty($field['multiple_column'])) {
				$existing_values = array_extract_values_by_key($value, $field['multiple_column']);
			}
			$field['options'] = \Object\Data\Common::processOptions($field['options_model'], $this, $field['options_params'], $existing_values, $skip_values, $field['options_options']);
		} else {
			$field['options'] = [];
		}
		// check if we have values
		if (!is_array($value)) $value = [$value];
		foreach ($value as $k => $v) {
			if (!empty($field['multiple_column'])) {
				$temp = $v[$field['multiple_column']];
			} else {
				$temp = $v;
			}
			if (empty($field['options'][$temp])) {
				$this->error('danger', \Object\Content\Messages::INVALID_VALUE, $error_name, [
					'replace' => [
						'[value]' => $temp
					]
				]);
			}
		}
	}
292546
public static function url($name, $value = null, array $options = [])
    {
        self::exclure($options);

        return self::input('url', $name, $value, $options);
    }