diff --git a/src/AbstractAuraForm.php b/src/AbstractAuraForm.php deleted file mode 100644 index d02dae7..0000000 --- a/src/AbstractAuraForm.php +++ /dev/null @@ -1,116 +0,0 @@ -builder = $builder; - $this->filter = $filter; - $this->options = $options; - $this->helper = $factory->newInstance(); - } - - public function __construct() - { - } - - /** - * @\Ray\Di\Di\PostConstruct - */ - public function postConstruct() - { - $this->init(); - if ($this->antiCsrf instanceof AntiCsrfInterface) { - $this->setAntiCsrf($this->antiCsrf); - } - } - - /** - * @var HelperLocator - */ - protected $helper; - - /** - * HTML - * - * @var string - */ - protected $string = '
'; - - /** - * @param AntiCsrfInterface $antiCsrf - */ - public function setCsrf(AntiCsrfInterface $antiCsrf) - { - $this->setAntiCsrf($antiCsrf); - } - - /** - * @inheritdoc - */ - public function input($input) - { - return $this->helper->input($this->get($input)); - } - - /** - * @inheritdoc - */ - public function error($input, $format = '%s', $layout = '%s') - { - $errorMessages = $this->getFilter()->getMessages($input); - array_filter($errorMessages, function (&$item) use ($format) { - $item = sprintf($format, $item); - }); - $errors = implode('', $errorMessages); - - return sprintf($layout, $errors); - } - - /** - * @param array $attr Attributes for the form tag. - * - * @return string - * - * @throws \Aura\Html\Exception\HelperNotFound - * @throws \Aura\Input\Exception\NoSuchInput - */ - public function form($attr = []) - { - $form = $this->helper->form($attr); - if (isset($this->inputs['__csrf_token'])) { - $form .= $this->helper->input($this->get('__csrf_token')); - } - - return $form; - } -} diff --git a/src/AbstractForm.php b/src/AbstractForm.php index 911c2e1..1294bad 100644 --- a/src/AbstractForm.php +++ b/src/AbstractForm.php @@ -11,11 +11,11 @@ use Aura\Html\HelperLocator; use Aura\Html\HelperLocatorFactory; use Aura\Input\AntiCsrfInterface; -use Aura\Input\Builder; use Aura\Input\BuilderInterface; -use Aura\Input\Form; +use Aura\Input\Fieldset; +use Ray\WebFormModule\Exception\CsrfViolationException; -abstract class AbstractForm extends Form implements FormInterface +abstract class AbstractForm extends Fieldset implements FormInterface { /** * @var SubjectFilter @@ -45,25 +45,22 @@ abstract class AbstractForm extends Form implements FormInterface * @\Ray\Di\Di\Inject */ public function setBaseDependencies( - BuilderInterface $builder = null, - FilterFactory $filterFactory = null, - HelperLocatorFactory $helperFactory = null + BuilderInterface $builder, + FilterFactory $filterFactory, + HelperLocatorFactory $helperFactory ) { - $this->builder = $builder ?: new Builder; - $this->filter = $filterFactory ? $filterFactory->newSubjectFilter() : (new FilterFactory)->newSubjectFilter(); - $this->helper = $helperFactory ? $helperFactory->newInstance() : (new HelperLocatorFactory)->newInstance(); + $this->builder = $builder; + $this->filter = $filterFactory->newSubjectFilter(); + $this->helper = $helperFactory->newInstance(); } public function __construct() { } - /** - * @param AntiCsrfInterface $antiCsrf - */ - public function setCsrf(AntiCsrfInterface $antiCsrf) + public function setAntiCsrf(AntiCsrfInterface $antiCsrf) { - $this->setAntiCsrf($antiCsrf); + $this->antiCsrf = $antiCsrf; } /** @@ -73,7 +70,7 @@ public function postConstruct() { $this->init(); if ($this->antiCsrf instanceof AntiCsrfInterface) { - $this->setAntiCsrf($this->antiCsrf); + $this->antiCsrf->setField($this); } } @@ -131,29 +128,39 @@ public function form($attr = []) */ public function apply(array $data) { + if ($this->antiCsrf && ! $this->antiCsrf->isValid($data)) { + throw new CsrfViolationException; + } $isValid = $this->filter->apply($data); return $isValid; } /** - * Gets the filter messages. - * - * @param string $name The input name to get the filter message for; if - * empty, gets all messages for all inputs. + * Returns all failure messages for all fields. * - * @return array The filter messages. + * @return array */ - public function getMessages($name = null) + public function getFailureMessages() { $messages = $this->filter->getFailures()->getMessages(); - if ($name && isset($messages[$name])) { - return $messages[$name]; - } return $messages; } + + /** + * + * Returns all the fields collection + * + * @return \ArrayIterator + * + */ + public function getIterator() + { + return new \ArrayIterator($this->inputs); + } + public function __clone() { $this->filter = clone $this->filter; diff --git a/src/AntiCsrf.php b/src/AntiCsrf.php index d6e6150..6537002 100644 --- a/src/AntiCsrf.php +++ b/src/AntiCsrf.php @@ -16,14 +16,31 @@ final class AntiCsrf implements AntiCsrfInterface const TOKEN_KEY = '__csrf_token'; + /** + * @var bool + */ + private $isCli; + + /** + * $_POST + * + * @var array + */ + private $post; + /** * @var Session */ private $session; - public function __construct(Session $session) + /** + * @param Session $session + * @param bool|null $isCli +s */ + public function __construct(Session $session, $isCli = null) { $this->session = $session; + $this->isCli = is_bool($isCli) ? $isCli : PHP_SAPI === 'cli'; } public function setField(Fieldset $fieldset) @@ -39,19 +56,19 @@ public function setField(Fieldset $fieldset) */ public function isValid(array $data) { - if (PHP_SAPI === 'cli') { + if ($this->isCli) { return true; } - if (isset($_POST[self::TOKEN_KEY])) { - $data[self::TOKEN_KEY] = $_POST[self::TOKEN_KEY]; - } return isset($data[self::TOKEN_KEY]) && $data[self::TOKEN_KEY] == $this->getToken(); } + /** + * @return string + */ private function getToken() { - $value = PHP_SAPI === 'cli' ? self::TEST_TOKEN : $this->session->getCsrfToken()->getValue(); + $value = $this->isCli ? self::TEST_TOKEN : $this->session->getCsrfToken()->getValue(); return $value; } diff --git a/src/AuraInputInterceptor.php b/src/AuraInputInterceptor.php index 67f1af9..a61e59d 100644 --- a/src/AuraInputInterceptor.php +++ b/src/AuraInputInterceptor.php @@ -13,7 +13,6 @@ use Ray\WebFormModule\Annotation\FormValidation; use Ray\WebFormModule\Exception\InvalidArgumentException; use Ray\WebFormModule\Exception\InvalidFormPropertyException; -use Ray\WebFormModule\Exception\LogicException; class AuraInputInterceptor implements MethodInterceptor { @@ -48,7 +47,7 @@ public function invoke(MethodInvocation $invocation) $formValidation = $this->reader->getMethodAnnotation($invocation->getMethod(), FormValidation::class); $form = $this->getFormProperty($formValidation, $object); $data = $object instanceof SubmitInterface ? $object->submit() : $this->getNamedArguments($invocation); - $isValid = $this->isValidForm($data, $form); + $isValid = $this->isValid($data, $form); if ($isValid === true) { // validation success return $invocation->proceed(); @@ -85,22 +84,11 @@ private function getNamedArguments(MethodInvocation $invocation) * * @throws \Aura\Input\Exception\CsrfViolation */ - public function isValidForm(array $submit, Form $form) + public function isValid(array $submit, AbstractForm $form) { - if ($form instanceof AbstractAuraForm) { - $form->fill($submit); - $isValid = $form->filter(); + $isValid = $form->apply($submit); - return $isValid; - } - - if ($form instanceof AbstractForm) { - $isValid = $form->apply($submit); - - return $isValid; - } - - throw new LogicException('invalid form type'); + return $isValid; } /** @@ -109,7 +97,7 @@ public function isValidForm(array $submit, Form $form) * @param FormValidation $formValidation * @param object $object * - * @return AbstractAuraForm + * @return AbstractForm */ private function getFormProperty(FormValidation $formValidation, $object) { @@ -119,7 +107,7 @@ private function getFormProperty(FormValidation $formValidation, $object) $prop = (new \ReflectionClass($object))->getProperty($formValidation->form); $prop->setAccessible(true); $form = $prop->getValue($object); - if (! $form instanceof FormInterface) { + if (! $form instanceof AbstractForm) { throw new InvalidFormPropertyException($formValidation->form); } diff --git a/src/AuraInputModule.php b/src/AuraInputModule.php index 59c3bbb..57846a5 100644 --- a/src/AuraInputModule.php +++ b/src/AuraInputModule.php @@ -6,6 +6,7 @@ */ namespace Ray\WebFormModule; +use Aura\Filter\FilterFactory; use Aura\Html\HelperLocatorFactory; use Aura\Input\AntiCsrfInterface; use Aura\Input\Builder; @@ -30,9 +31,10 @@ protected function configure() $this->bind(Reader::class)->to(AnnotationReader::class)->in(Scope::SINGLETON); $this->bind(BuilderInterface::class)->to(Builder::class); $this->bind(FilterInterface::class)->to(Filter::class); - $this->bind(HelperLocatorFactory::class); $this->bind(AntiCsrfInterface::class)->to(AntiCsrf::class)->in(Scope::SINGLETON); $this->bind(FailureHandlerInterface::class)->to(OnFailureMethodHandler::class); + $this->bind(HelperLocatorFactory::class); + $this->bind(FilterFactory::class); $this->bindInterceptor( $this->matcher->any(), $this->matcher->annotatedWith(FormValidation::class), diff --git a/src/Exception/CsrfViolationException.php b/src/Exception/CsrfViolationException.php new file mode 100644 index 0000000..5a396aa --- /dev/null +++ b/src/Exception/CsrfViolationException.php @@ -0,0 +1,13 @@ +getArguments(); diff --git a/src/SetAntiCsrfTrait.php b/src/SetAntiCsrfTrait.php index a18223d..e1b1af2 100644 --- a/src/SetAntiCsrfTrait.php +++ b/src/SetAntiCsrfTrait.php @@ -15,7 +15,7 @@ trait SetAntiCsrfTrait * * @\Ray\Di\Di\Inject */ - public function injectAntiCsrf(AntiCsrfInterface $antiCsrf) + public function setAntiCsrf(AntiCsrfInterface $antiCsrf) { $this->antiCsrf = $antiCsrf; } diff --git a/src/VndErrorHandler.php b/src/VndErrorHandler.php index 0be71d5..cf32f1d 100644 --- a/src/VndErrorHandler.php +++ b/src/VndErrorHandler.php @@ -28,7 +28,7 @@ public function __construct(Reader $reader) /** * {@inheritdoc} */ - public function handle(FormValidation $formValidation, MethodInvocation $invocation, Form $form) + public function handle(FormValidation $formValidation, MethodInvocation $invocation, AbstractForm $form) { unset($formValidation); $vndError = $this->reader->getMethodAnnotation($invocation->getMethod(), VndError::class); @@ -38,11 +38,11 @@ public function handle(FormValidation $formValidation, MethodInvocation $invocat throw $e; } - private function makeVndError(Form $form, VndError $vndError = null) + private function makeVndError(AbstractForm $form, VndError $vndError = null) { $body = ['message' => 'Validation failed']; $body['path'] = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; - $body['validation_messages'] = $form->getMessages(); + $body['validation_messages'] = $form->getFailureMessages(); $body = $vndError ? $this->optionalAttribute($vndError) + $body : $body; return $body; diff --git a/tests/AbstractAuraFormTest.php b/tests/AbstractAuraFormTest.php index e3d5c26..e8f30b3 100644 --- a/tests/AbstractAuraFormTest.php +++ b/tests/AbstractAuraFormTest.php @@ -9,16 +9,14 @@ class AbstractAuraFormTest extends \PHPUnit_Framework_TestCase { /** - * @var AbstractAuraForm + * @var AbstractForm */ private $form; public function setUp() { parent::setUp(); - $this->form = new FakeForm; - $this->form->setBaseDependencies(new Builder, new Filter, new HelperLocatorFactory); - $this->form->postConstruct(); + $this->form = (new FormFactory)->newInstance(FakeForm::class); } public function testForm() @@ -29,7 +27,8 @@ public function testForm() public function testAntiCsrfForm() { - $this->form->setCsrf(new FakeAntiCsrf); + $this->form->setAntiCsrf(new FakeAntiCsrf); + $this->form->postConstruct(); $formHtml = $this->form->form(); $this->assertSame('