<commit_before><?php

/**
 * This file is part of the Arachne
 *
 * Copyright (c) <NAME> (<EMAIL>)
 *
 * For the full copyright and license information, please view the file license.md that was distributed with this source code.
 */

namespace Arachne\Forms\Application;

use Nette\Application\Request;
use Nette\Application\UI\BadSignalException;
use Nette\Application\UI\ISignalReceiver;
use Nette\Application\UI\Presenter;
use Nette\ComponentModel\Container;
use Symfony\Bridge\Twig\Form\TwigRendererInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormErrorIterator;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Twig_Environment;

/**
 * @author <NAME> <<EMAIL>>
 */
class FormComponent extends Container implements ISignalReceiver
{

	/**
	 * Array of function(mixed $data, FormComponent $form); Occurs when the form is submitted and successfully validated.
	 * @var callable[]
	 */
	public $onSuccess;

	/**
	 * Array of function(mixed $data, FormComponent $form); Occurs when the form is submitted and is not valid.
	 * @var callable[]
	 */
	public $onError;

	/**
	 * Array of function(mixed $data, FormComponent $form); Occurs when the form is submitted.
	 * @var callable[]
	 */
	public $onSubmit;

	/**
	 * Array of function(FormView $view, FormComponent $form); Occurs when the form is rendered.
	 * @var callable[]
	 */
	public $onCreateView;

	/** @var FormInterface */
	protected $form;

	/** @var FormView */
	protected $view;

	/** @var TwigRendererInterface */
	protected $renderer;

	/**
	 * @param TwigRendererInterface $renderer
	 * @param Twig_Environment $twig
	 * @param FormInterface $form
	 */
	public function __construct(TwigRendererInterface $renderer, Twig_Environment $twig, FormInterface $form)
	{
		$this->renderer = $renderer;
		$renderer->setEnvironment($twig); // Cannot be in DIC setup because of cyclic reference.
		$this->form = $form;
	}

	/**
	 * @return TwigRendererInterface
	 */
	public function getRenderer()
	{
		return $this->renderer;
	}

	/**
	 * @return FormInterface
	 */
	public function getForm()
	{
		return $this->form;
	}

	/**
	 * @return FormView
	 */
	public function getView()
	{
		if (!$this->view) {
			$this->view = $this->getForm()->createView();
			$this->onCreateView($this->view, $this);
		}
		return $this->view;
	}

	public function render(array $variables = [])
	{
		$variables['component'] = $this->lookupPath('Nette\Application\UI\Presenter');
		echo $this->renderer->renderBlock($this->getView(), 'form', $variables);
	}

	/**
	 * Returns the presenter where this component belongs to.
	 * @param bool $need
	 * @return Presenter|null
	 */
	public function getPresenter($need = true)
	{
		return $this->lookup('Nette\Application\UI\Presenter', $need);
	}

	/**
	 * @param string $signal
	 * @throws BadSignalException
	 */
	public function signalReceived($signal)
	{
		$form = $this->getForm();
		$request = $this->getPresenter()->getRequest();

		if ($signal === 'submit') {
			$this->processSubmit($form, $request);

		} elseif ($signal === 'validate') {
			$this->processValidate($form, $request);

		} else {
			throw new BadSignalException("Missing handler for signal '$signal' in " . get_class($this) . ".");
		}
	}

	protected function processSubmit(FormInterface $form, Request $request)
	{
		if ($request->hasFlag(Request::RESTORED)) {
			return;
		}

		$form->handleRequest($request);
		if (!$form->isSubmitted()) {
			return;
		}

		$data = $form->getData();
		if ($form->isValid()) {
			$this->onSuccess($data, $this);
		} else {
			$this->onError($data, $this);
		}
		$this->onSubmit($data, $this);
	}

	protected function processValidate(FormInterface $form, Request $request)
	{
		$form->handleRequest($request);
		if (!$form->isSubmitted() || !$this->getPresenter()->isAjax()) {
			return;
		}

		$view = $this->getView();
		$errors = [];
		$this->walkErrors($form->getErrors(true, false), $view, function ($view) use (& $errors) {
			$errors[$view->vars['id']] = $this->renderer->searchAndRenderBlock($view, 'errors_content');
		});
		$this->getPresenter()->sendJson($errors);
	}

	private function walkErrors(FormErrorIterator $iterator, FormView $view, callable $callback)
	{
		$new = true;
		foreach ($iterator as $error) {
			if ($error instanceof FormErrorIterator) {
				$this->walkErrors($error, $view[$error->getForm()->getName()], $callback);
			} elseif ($new) {
				$callback($view);
				$new = false;
			}
		}
	}

}<commit_msg>Improve ajax validation<commit_after><?php

/**
 * This file is part of the Arachne
 *
 * Copyright (c) <NAME> (<EMAIL>)
 *
 * For the full copyright and license information, please view the file license.md that was distributed with this source code.
 */

namespace Arachne\Forms\Application;

use Nette\Application\Request;
use Nette\Application\UI\BadSignalException;
use Nette\Application\UI\ISignalReceiver;
use Nette\Application\UI\Presenter;
use Nette\ComponentModel\Container;
use Symfony\Bridge\Twig\Form\TwigRendererInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormErrorIterator;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Twig_Environment;

/**
 * @author <NAME> <<EMAIL>>
 */
class FormComponent extends Container implements ISignalReceiver
{

	/**
	 * Array of function(mixed $data, FormComponent $form); Occurs when the form is submitted and successfully validated.
	 * @var callable[]
	 */
	public $onSuccess;

	/**
	 * Array of function(mixed $data, FormComponent $form); Occurs when the form is submitted and is not valid.
	 * @var callable[]
	 */
	public $onError;

	/**
	 * Array of function(mixed $data, FormComponent $form); Occurs when the form is submitted.
	 * @var callable[]
	 */
	public $onSubmit;

	/**
	 * Array of function(FormView $view, FormComponent $form); Occurs when the form is rendered.
	 * @var callable[]
	 */
	public $onCreateView;

	/** @var FormInterface */
	protected $form;

	/** @var FormView */
	protected $view;

	/** @var TwigRendererInterface */
	protected $renderer;

	/**
	 * @param TwigRendererInterface $renderer
	 * @param Twig_Environment $twig
	 * @param FormInterface $form
	 */
	public function __construct(TwigRendererInterface $renderer, Twig_Environment $twig, FormInterface $form)
	{
		$this->renderer = $renderer;
		$renderer->setEnvironment($twig); // Cannot be in DIC setup because of cyclic reference.
		$this->form = $form;
	}

	/**
	 * @return TwigRendererInterface
	 */
	public function getRenderer()
	{
		return $this->renderer;
	}

	/**
	 * @return FormInterface
	 */
	public function getForm()
	{
		return $this->form;
	}

	/**
	 * @return FormView
	 */
	public function getView()
	{
		if (!$this->view) {
			$this->view = $this->getForm()->createView();
			$this->onCreateView($this->view, $this);
		}
		return $this->view;
	}

	public function render(array $variables = [])
	{
		$variables['component'] = $this->lookupPath('Nette\Application\UI\Presenter');
		echo $this->renderer->renderBlock($this->getView(), 'form', $variables);
	}

	/**
	 * Returns the presenter where this component belongs to.
	 * @param bool $need
	 * @return Presenter|null
	 */
	public function getPresenter($need = true)
	{
		return $this->lookup('Nette\Application\UI\Presenter', $need);
	}

	/**
	 * @param string $signal
	 * @throws BadSignalException
	 */
	public function signalReceived($signal)
	{
		$form = $this->getForm();
		$request = $this->getPresenter()->getRequest();

		if ($signal === 'submit') {
			$this->processSubmit($form, $request);

		} elseif ($signal === 'validate') {
			$this->processValidate($form, $request);

		} else {
			throw new BadSignalException("Missing handler for signal '$signal' in " . get_class($this) . ".");
		}
	}

	protected function processSubmit(FormInterface $form, Request $request)
	{
		if ($request->hasFlag(Request::RESTORED)) {
			return;
		}

		$form->handleRequest($request);
		if (!$form->isSubmitted()) {
			return;
		}

		$data = $form->getData();
		if ($form->isValid()) {
			$this->onSuccess($data, $this);
		} else {
			$this->onError($data, $this);
		}
		$this->onSubmit($data, $this);
	}

	protected function processValidate(FormInterface $form, Request $request)
	{
		$form->handleRequest($request);
		if (!$form->isSubmitted() || !$this->getPresenter()->isAjax()) {
			return;
		}

		$view = $this->getView();
		$errors = [];
		$this->walkErrors($form->getErrors(true, false), $view, function ($view) use (& $errors) {
			$errors[$view->vars['id']] = $this->renderer->searchAndRenderBlock($view, 'errors_content');
		});
		$this->getPresenter()->sendJson((object) [ 'errors' => $errors ]);
	}

	private function walkErrors(FormErrorIterator $iterator, FormView $view, callable $callback)
	{
		$new = true;
		foreach ($iterator as $error) {
			if ($error instanceof FormErrorIterator) {
				$this->walkErrors($error, $view[$error->getForm()->getName()], $callback);
			} elseif ($new) {
				$callback($view);
				$new = false;
			}
		}
	}

}
{'fraction_non_alphanumeric': 0.16092208799734012, 'fraction_numerical': 0.0, 'mean_word_length': 4.174311926605505, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 104, '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': '5757040', 'n_tokens_mistral': 3077, 'n_tokens_neox': 2839, 'n_words': 690}