/** * @group ZF2-5648 */ public function testCountZeroValidateInternalInputWithCollectionInputFilter() { $inputFilter = new InputFilter(); $inputFilter->add(new Input(), 'name'); $collection = new CollectionInputFilter(); $collection->setInputFilter($inputFilter); $collection->setCount(0); $this->filter->add($collection, 'people'); $data = array('people' => array(array('name' => 'Wanderson'))); $this->filter->setData($data); $this->assertTrue($this->filter->isvalid()); $this->assertSame($data, $this->filter->getValues()); }
private function setAllInputFilters() { $finalInputFilter = $this->createBaseInputFilter(); //set filters for entityProperties collection $propertyFieldset = new PropertyFieldset(); $propertiesFilter = new CollectionInputFilter(); $propertiesFilter->setInputFilter($propertyFieldset->getInputFilter()); $finalInputFilter->add($propertiesFilter, 'entityProperties'); //set filters for indexes collection $indexFieldset = new IndexFieldset(); $indexesFilter = new CollectionInputFilter(); $indexesFilter->setInputFilter($indexFieldset->getInputFilter()); $finalInputFilter->add($indexesFilter, 'indexes'); //set the completed input filter as the form's filter $this->setInputFilter($finalInputFilter); }
public function setInputFilter($inputFilter) { if (is_string($inputFilter)) { $inputFilters = $this->getFactory()->getInputFilterManager(); $inputFilter = $inputFilters->get($inputFilter); } return parent::setInputFilter($inputFilter); }
/** * @param Collection $collection */ protected function configureInputFilter(Collection $collection) { // Make it a collection input filter $inputFilter = new CollectionInputFilter(); $inputFilter->setIsRequired(false); // Add the input filter of the target document as the real input filter: $targetElement = $collection->getTargetElement(); if ($targetElement instanceof InputFilterProviderInterface) { $configuredFilter = $targetElement->getInputFilterSpecification(); $inputFilter->setInputFilter($configuredFilter); } // Replace the current input filter in the actual form: $collectionName = $collection->getName(); $formFilter = $this->form->getInputFilter(); $formFilter->remove($collectionName); $formFilter->add($inputFilter, $collectionName); }
public function testSetRequired() { $this->filter->setIsRequired(true); $this->assertEquals(true, $this->filter->getIsRequired()); }
/** * Add inputs to CollectionInputFilter * * @param CollectionInputFilter $inputFilter * @return CollectionInputFilter */ private function addInputsToCollectionInputFilter(CollectionInputFilter $inputFilter) { foreach ($inputFilter->getInputs() as $name => $input) { if (!$inputFilter->getInputFilter()->has($name)) { $inputFilter->getInputFilter()->add($input, $name); } } return $inputFilter; }
/** * Return a list of validation failure messages * * Should return an associative array of named input/message list pairs. * Pairs should only be returned for inputs that failed validation. * * @return array */ public function getMessages() { $messages = parent::getMessages(); return array_replace_recursive($messages, $this->collectionMessages); }
public function testNestedCollectionWithEmptyData() { $items_inputfilter = new BaseInputFilter(); $items_inputfilter->add(new Input(), 'id')->add(new Input(), 'type'); $items = new CollectionInputFilter(); $items->setInputFilter($items_inputfilter); $groups_inputfilter = new BaseInputFilter(); $groups_inputfilter->add(new Input(), 'group_class')->add($items, 'items'); $groups = new CollectionInputFilter(); $groups->setInputFilter($groups_inputfilter); $inputFilter = new BaseInputFilter(); $inputFilter->add($groups, 'groups'); $data = array('groups' => array(array('group_class' => 'bar', 'items' => array(array('id' => 100, 'type' => 'item-1'))), array('group_class' => 'biz', 'items' => array()), array('group_class' => 'bar', 'items' => array(array('id' => 200, 'type' => 'item-2'), array('id' => 300, 'type' => 'item-3'), array('id' => 400, 'type' => 'item-4'))))); $inputFilter->setData($data); $inputFilter->isValid(); $values = $inputFilter->getValues(); $this->assertEquals($data, $values); }
/** * Attempt to validate the incoming request * * If an input filter is associated with the matched controller service, * attempt to validate the incoming request, and inject the event with the * input filter, as the "ZF\ContentValidation\InputFilter" parameter. * * Uses the ContentNegotiation ParameterDataContainer to retrieve parameters * to validate, and returns an ApiProblemResponse when validation fails. * * Also returns an ApiProblemResponse in cases of: * * - Invalid input filter service name * - Missing ParameterDataContainer (i.e., ContentNegotiation is not registered) * * @param MvcEvent $e * @return null|ApiProblemResponse */ public function onRoute(MvcEvent $e) { $request = $e->getRequest(); if (! $request instanceof HttpRequest) { return; } $method = $request->getMethod(); if (in_array($method, $this->methodsWithoutBodies)) { return; } $routeMatches = $e->getRouteMatch(); if (! $routeMatches instanceof RouteMatch) { return; } $controllerService = $routeMatches->getParam('controller', false); if (! $controllerService) { return; } $inputFilterService = $this->getInputFilterService($controllerService, $method); if (! $inputFilterService) { return; } if (! $this->hasInputFilter($inputFilterService)) { return new ApiProblemResponse( new ApiProblem( 500, sprintf('Listed input filter "%s" does not exist; cannot validate request', $inputFilterService) ) ); } $dataContainer = $e->getParam('ZFContentNegotiationParameterData', false); if (! $dataContainer instanceof ParameterDataContainer) { return new ApiProblemResponse( new ApiProblem( 500, 'ZF\\ContentNegotiation module is not initialized; cannot validate request' ) ); } $data = $dataContainer->getBodyParams(); if (null === $data || '' === $data) { $data = array(); } $isCollection = $this->isCollection($controllerService, $data, $routeMatches, $request); $files = $request->getFiles(); if (! $isCollection && 0 < count($files)) { // File uploads are not validated for collections; impossible to // match file fields to discrete sets $data = array_merge_recursive($data, $files->toArray()); } $inputFilter = $this->getInputFilter($inputFilterService); if ($isCollection) { $collectionInputFilter = new CollectionInputFilter(); $collectionInputFilter->setInputFilter($inputFilter); $inputFilter = $collectionInputFilter; } $e->setParam('ZF\ContentValidation\InputFilter', $inputFilter); $events = $this->getEventManager(); $results = $events->trigger(self::EVENT_BEFORE_VALIDATE, $e, function ($result) { return ($result instanceof ApiProblem || $result instanceof ApiProblemResponse ); }); $last = $results->last(); if ($last instanceof ApiProblem) { $last = new ApiProblemResponse($last); } if ($last instanceof ApiProblemResponse) { return $last; } $inputFilter->setData($data); $status = ($request->isPatch()) ? $this->validatePatch($inputFilter, $data, $isCollection) : $inputFilter->isValid(); if ($status instanceof ApiProblemResponse) { return $status; } // Invalid? Return a 422 response. if (false === $status) { return new ApiProblemResponse( new ApiProblem(422, 'Failed Validation', null, null, array( 'validation_messages' => $inputFilter->getMessages(), )) ); } // Should we use the raw data vs. the filtered data? // - If no `use_raw_data` flag is present, always use the raw data, as // that was the default experience starting in 1.0. // - If the flag is present AND is boolean true, that is also // an indicator that the raw data should be present. if (! isset($this->config[$controllerService]['use_raw_data']) || (isset($this->config[$controllerService]['use_raw_data']) && $this->config[$controllerService]['use_raw_data'] === true) ) { $dataContainer->setBodyParams($data); return; } // If we don't have an instance of UnknownInputsCapableInterface, or no // unknown data is in the input filter, at this point we can just // set the input filter values directly into the data container. if (! $inputFilter instanceof UnknownInputsCapableInterface || ! $inputFilter->hasUnknown() ) { $dataContainer->setBodyParams($inputFilter->getValues()); return; } $bodyParams = $inputFilter->getValues(); $unknown = $inputFilter->getUnknown(); if ($this->allowsOnlyFieldsInFilter($controllerService)) { $fields = implode(', ', array_keys($unknown)); $detail = sprintf('Unrecognized fields: %s', $fields); $problem = new ApiProblem(Response::STATUS_CODE_422, $detail); return new ApiProblemResponse($problem); } $dataContainer->setBodyParams(array_merge($bodyParams, $unknown)); }
/** * Attempt to validate the incoming request * * If an input filter is associated with the matched controller service, * attempt to validate the incoming request, and inject the event with the * input filter, as the "ZF\ContentValidation\InputFilter" parameter. * * Uses the ContentNegotiation ParameterDataContainer to retrieve parameters * to validate, and returns an ApiProblemResponse when validation fails. * * Also returns an ApiProblemResponse in cases of: * * - Invalid input filter service name * - Missing ParameterDataContainer (i.e., ContentNegotiation is not registered) * * @param MvcEvent $e * @return null|ApiProblemResponse */ public function onRoute(MvcEvent $e) { $request = $e->getRequest(); if (!$request instanceof HttpRequest) { return; } $routeMatches = $e->getRouteMatch(); if (!($routeMatches instanceof RouteMatch || $routeMatches instanceof V2RouteMatch)) { return; } $controllerService = $routeMatches->getParam('controller', false); if (!$controllerService) { return; } $method = $request->getMethod(); $inputFilterService = $this->getInputFilterService($controllerService, $method); if (!$inputFilterService) { return; } if (!$this->hasInputFilter($inputFilterService)) { return new ApiProblemResponse(new ApiProblem(500, sprintf('Listed input filter "%s" does not exist; cannot validate request', $inputFilterService))); } $dataContainer = $e->getParam('ZFContentNegotiationParameterData', false); if (!$dataContainer instanceof ParameterDataContainer) { return new ApiProblemResponse(new ApiProblem(500, 'ZF\\ContentNegotiation module is not initialized; cannot validate request')); } $data = in_array($method, $this->methodsWithoutBodies) ? $dataContainer->getQueryParams() : $dataContainer->getBodyParams(); if (null === $data || '' === $data) { $data = []; } $isCollection = $this->isCollection($controllerService, $data, $routeMatches, $request); $files = $request->getFiles(); if (!$isCollection && 0 < count($files)) { // File uploads are not validated for collections; impossible to // match file fields to discrete sets $data = ArrayUtils::merge($data, $files->toArray(), true); } $inputFilter = $this->getInputFilter($inputFilterService); if ($isCollection && !in_array($method, $this->methodsWithoutBodies)) { $collectionInputFilter = new CollectionInputFilter(); $collectionInputFilter->setInputFilter($inputFilter); $inputFilter = $collectionInputFilter; } $e->setParam('ZF\\ContentValidation\\InputFilter', $inputFilter); $currentEventName = $e->getName(); $e->setName(self::EVENT_BEFORE_VALIDATE); $events = $this->getEventManager(); $results = $events->triggerEventUntil(function ($result) { return $result instanceof ApiProblem || $result instanceof ApiProblemResponse; }, $e); $e->setName($currentEventName); $last = $results->last(); if ($last instanceof ApiProblem) { $last = new ApiProblemResponse($last); } if ($last instanceof ApiProblemResponse) { return $last; } $inputFilter->setData($data); $status = $request->isPatch() ? $this->validatePatch($inputFilter, $data, $isCollection) : $inputFilter->isValid(); if ($status instanceof ApiProblemResponse) { return $status; } // Invalid? Return a 422 response. if (false === $status) { return new ApiProblemResponse(new ApiProblem(422, 'Failed Validation', null, null, ['validation_messages' => $inputFilter->getMessages()])); } // Should we use the raw data vs. the filtered data? // - If no `use_raw_data` flag is present, always use the raw data, as // that was the default experience starting in 1.0. // - If the flag is present AND is boolean true, that is also // an indicator that the raw data should be present. $useRawData = $this->useRawData($controllerService); if (!$useRawData) { $data = $inputFilter->getValues(); } // If we don't have an instance of UnknownInputsCapableInterface, or no // unknown data is in the input filter, at this point we can just // set the current data into the data container. if (!$inputFilter instanceof UnknownInputsCapableInterface || !$inputFilter->hasUnknown()) { $dataContainer->setBodyParams($data); return; } $unknown = $inputFilter->getUnknown(); if ($this->allowsOnlyFieldsInFilter($controllerService)) { if ($inputFilter instanceof CollectionInputFilter) { $unknownFields = []; foreach ($unknown as $key => $fields) { $unknownFields[] = '[' . $key . ': ' . implode(', ', array_keys($fields)) . ']'; } $fields = implode(', ', $unknownFields); } else { $fields = implode(', ', array_keys($unknown)); } $detail = sprintf('Unrecognized fields: %s', $fields); $problem = new ApiProblem(Response::STATUS_CODE_422, $detail); return new ApiProblemResponse($problem); } // The raw data already contains unknown inputs, so no need to merge // them with the data. if ($useRawData) { $dataContainer->setBodyParams($data); return; } // When not using raw data, we merge the unknown data with the // validated data to get the full set of input. $dataContainer->setBodyParams(array_merge($data, $unknown)); }