<commit_before><?php

use beatbox;

class :bb:form extends :bb:base implements beatbox\FragmentCallback {
	attribute
		:form,
		var validator,
		var handler;

	protected function compose() :form {
		return <form>
			{$this->getChildren()}
			<bb:form:csrf />
		</form>;
	}

	public function forFragment(Traversable $url, string $fragment) : :x:base {
		if(!$this->getAttribute('method')) {
			$this->setAttribute('method', 'post');
		}
		if($url[0] == '/') {
			$base = '/';
		} else {
			$base = implode('/', array_map('rawurlencode', $url));
		}
		if(!$this->getAttribute('action')) {
			$action = $base . '?fragments=' . rawurlencode($fragment);
			$this->setAttribute('action', $action);
		}
		if(is_get()) {
			$data = session_get('form.' . $this->getAttribute('action') . '.data');
			if($data) {
				$this->loadData($data, true);
				$this->validate();
				session_clear('form.' . $this->getAttribute('action') . '.data');
			}
		} else {
			$this->loadData($_POST, true);
			if(!$this->validate()) {
				if(!is_ajax()) {
					// Save session data
					session_set('form.' . $this->getAttribute('action') . '.data', $_POST);
					// Redirect back
					redirect_back($base);
				} else {
					// Fall back to the return
				}
			} else {
				$handler = $this->getAttribute('handler');
				if(!$handler || !is_callable($handler)) {
					throw new beatbox\errors\Exception('No handler provided or non-callable handler provided.');
				}
				return call_user_func($handler, $this, $this->getData());
			}
		}
		return $this;
	}

	protected function getFields(:x:base $base = null) : Generator {
		if(!$base) {
			$base = $this;
		}
		foreach($base->getChildren() as $field) {
			if($field instanceof :bb:form:field) {
				yield $field;
			} elseif($field instanceof :x:base) {
				foreach($this->getFields($field) as $f) yield $f;
			}
		}
	}

	protected static function add_to_map(Map $base, string $name, $value) {
		if(preg_match('#^(.+?)\[(.*?)\](.*)$#', $name, $matches)) {
			if(!$matches[2]) {
				if(!isset($base[$matches[1]])) {
					$base[$matches[1]] = Vector {};
				}
				$base[$matches[1]][] = $value;
			} else {
				if(!isset($base[$matches[1]])) {
					$base[$matches[1]] = Map {};
				}
				self::add_to_map($base[$matches[1]], $matches[2] . $matches[3], $value);
			}
		} else {
			$base[$name] = $value;
		}
	}

	protected function getData() {
		$data = Map {};
		foreach($this->getFields() as $field) {
			self::add_to_map($data, $field->getAttribute('name'), $field->getValue());
		}
		return $data;
	}

	protected static $load_count;

	protected static function get_value($data, $name, $base) {
		if(!$name) {
			return $data;
		} elseif(preg_match('#^(.+?)\[(.*?)\](.*)$#', $name, $matches)) {
			if(!$matches[2]) {
				$index = isset(self::$load_count[$base . $matches[1]]) ? self::$load_count[$base . $matches[1]] + 1 : 0;
				self::$load_count[$base . $matches[1]] = $index;

				if(isset($data[$matches[1]][$index])) {<commit_msg>Don't try getting data from nameless fields and recurse into form fields when getting all of them<commit_after><?php

use beatbox;

class :bb:form extends :bb:base implements beatbox\FragmentCallback {
	attribute
		:form,
		var validator,
		var handler;

	protected function compose() :form {
		return <form>
			{$this->getChildren()}
			<bb:form:csrf />
		</form>;
	}

	public function forFragment(Traversable $url, string $fragment) : :x:base {
		if(!$this->getAttribute('method')) {
			$this->setAttribute('method', 'post');
		}
		if($url[0] == '/') {
			$base = '/';
		} else {
			$base = implode('/', array_map('rawurlencode', $url));
		}
		if(!$this->getAttribute('action')) {
			$action = $base . '?fragments=' . rawurlencode($fragment);
			$this->setAttribute('action', $action);
		}
		if(is_get()) {
			$data = session_get('form.' . $this->getAttribute('action') . '.data');
			if($data) {
				$this->loadData($data, true);
				$this->validate();
				session_clear('form.' . $this->getAttribute('action') . '.data');
			}
		} else {
			$this->loadData($_POST, true);
			if(!$this->validate()) {
				if(!is_ajax()) {
					// Save session data
					session_set('form.' . $this->getAttribute('action') . '.data', $_POST);
					// Redirect back
					redirect_back($base);
				} else {
					// Fall back to the return
				}
			} else {
				$handler = $this->getAttribute('handler');
				if(!$handler || !is_callable($handler)) {
					throw new beatbox\errors\Exception('No handler provided or non-callable handler provided.');
				}
				return call_user_func($handler, $this, $this->getData());
			}
		}
		return $this;
	}

	protected function getFields(:x:base $base = null) : Generator {
		if(!$base) {
			$base = $this;
		}
		foreach($base->getChildren() as $field) {
			if($field instanceof :bb:form:field) {
				yield $field;
			}
			if($field instanceof :x:base) {
				foreach($this->getFields($field) as $f) yield $f;
			}
		}
	}

	protected static function add_to_map(Map $base, string $name, $value) {
		if(preg_match('#^(.+?)\[(.*?)\](.*)$#', $name, $matches)) {
			if(!$matches[2]) {
				if(!isset($base[$matches[1]])) {
					$base[$matches[1]] = Vector {};
				}
				$base[$matches[1]][] = $value;
			} else {
				if(!isset($base[$matches[1]])) {
					$base[$matches[1]] = Map {};
				}
				self::add_to_map($base[$matches[1]], $matches[2] . $matches[3], $value);
			}
		} else {
			$base[$name] = $value;
		}
	}

	protected function getData() {
		$data = Map {};
		foreach($this->getFields() as $field) {
			if(!$field->getAttribute('name')) {
				continue;
			}
			self::add_to_map($data, $field->getAttribute('name'), $field->getValue());
		}
		return $data;
	}

	protected static $load_count;

	protected static function get_value($data, $name, $base) {
		if(!$name) {
			return $data;
		} elseif(preg_match('#^(.+?)\[(.*?)\](.*)$#', $name, $matches)) {
			if(!$matches[2]) {
				$index = isset(self::$load_count[$base . $matches[1]]) ? self::$load_count[$base . $matches[1]] + 1 : 0;
				self::$load_count[$base . $matches[1]] = $index;

				if(isset($data[$matches[1]][$index])) {
{'fraction_non_alphanumeric': 0.22068283028203858, 'fraction_numerical': 0.005607784924954643, 'mean_word_length': 3.604403948367502, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 48, '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': '784467', 'n_tokens_mistral': 2499, 'n_tokens_neox': 2144, 'n_words': 406}