public function setInputFilter($inputFilter)
 {
     if (is_string($inputFilter)) {
         $inputFilters = $this->getFactory()->getInputFilterManager();
         $inputFilter = $inputFilters->get($inputFilter);
     }
     return parent::setInputFilter($inputFilter);
 }
 public function testEmptyCollectionIsNotValidIfRequired()
 {
     $data = array();
     $this->filter->setInputFilter($this->getBaseInputFilter());
     $this->filter->setData($data);
     $this->filter->setIsRequired(true);
     $this->assertFalse($this->filter->isValid());
 }
Esempio n. 3
0
 /**
  * @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);
 }
 /**
  * @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);
 }
Esempio n. 6
0
 /**
  * Attach defaults provided by the elements to the input filter
  *
  * @param  InputFilterInterface $inputFilter
  * @param  FieldsetInterface $fieldset Fieldset to traverse when looking for default inputs
  * @return void
  */
 public function attachInputFilterDefaults(InputFilterInterface $inputFilter, FieldsetInterface $fieldset)
 {
     $formFactory = $this->getFormFactory();
     $inputFactory = $formFactory->getInputFilterFactory();
     if ($fieldset instanceof Collection && $fieldset->getTargetElement() instanceof FieldsetInterface) {
         $elements = $fieldset->getTargetElement()->getElements();
     } else {
         $elements = $fieldset->getElements();
     }
     if (!$fieldset instanceof Collection || !$fieldset->getTargetElement() instanceof FieldsetInterface || $inputFilter instanceof CollectionInputFilter) {
         foreach ($elements as $name => $element) {
             if ($this->preferFormInputFilter && $inputFilter->has($name)) {
                 continue;
             }
             if (!$element instanceof InputProviderInterface) {
                 if ($inputFilter->has($name)) {
                     continue;
                 }
                 // Create a new empty default input for this element
                 $spec = array('name' => $name, 'required' => false);
                 $input = $inputFactory->createInput($spec);
             } else {
                 // Create an input based on the specification returned from the element
                 $spec = $element->getInputSpecification();
                 $input = $inputFactory->createInput($spec);
                 if ($inputFilter->has($name) && $inputFilter instanceof ReplaceableInputInterface) {
                     $input->merge($inputFilter->get($name));
                     $inputFilter->replace($input, $name);
                     continue;
                 }
             }
             // Add element input filter to CollectionInputFilter
             if ($inputFilter instanceof CollectionInputFilter && !$inputFilter->getInputFilter()->has($name)) {
                 $inputFilter->getInputFilter()->add($input, $name);
             } else {
                 $inputFilter->add($input, $name);
             }
         }
         if ($fieldset === $this && $fieldset instanceof InputFilterProviderInterface) {
             foreach ($fieldset->getInputFilterSpecification() as $name => $spec) {
                 $input = $inputFactory->createInput($spec);
                 $inputFilter->add($input, $name);
             }
         }
     }
     foreach ($fieldset->getFieldsets() as $name => $childFieldset) {
         if (!$childFieldset instanceof InputFilterProviderInterface) {
             if (!$inputFilter->has($name)) {
                 // Add a new empty input filter if it does not exist (or the fieldset's object input filter),
                 // so that elements of nested fieldsets can be recursively added
                 if ($childFieldset->getObject() instanceof InputFilterAwareInterface) {
                     $inputFilter->add($childFieldset->getObject()->getInputFilter(), $name);
                 } else {
                     // Add input filter for collections via getInputFilterSpecification()
                     if ($childFieldset instanceof Collection && $childFieldset->getTargetElement() instanceof InputFilterProviderInterface && $childFieldset->getTargetElement()->getInputFilterSpecification()) {
                         $collectionContainerFilter = new CollectionInputFilter();
                         $spec = $childFieldset->getTargetElement()->getInputFilterSpecification();
                         $filter = $inputFactory->createInputFilter($spec);
                         $collectionContainerFilter->setInputFilter($filter);
                         $inputFilter->add($collectionContainerFilter, $name);
                         // We need to copy the inputs to the collection input filter
                         if ($inputFilter instanceof CollectionInputFilter) {
                             $inputFilter = $this->addInputsToCollectionInputFilter($inputFilter);
                         }
                         // Add child elements from target element
                         $childFieldset = $childFieldset->getTargetElement();
                     } else {
                         $inputFilter->add(new InputFilter(), $name);
                     }
                 }
             }
             $fieldsetFilter = $inputFilter->get($name);
             if (!$fieldsetFilter instanceof InputFilterInterface) {
                 // Input attached for fieldset, not input filter; nothing more to do.
                 continue;
             }
             // Traverse the elements of the fieldset, and attach any
             // defaults to the fieldset's input filter
             $this->attachInputFilterDefaults($fieldsetFilter, $childFieldset);
             continue;
         }
         if ($inputFilter->has($name)) {
             // if we already have an input/filter by this name, use it
             continue;
         }
         // Create an input filter based on the specification returned from the fieldset
         $spec = $childFieldset->getInputFilterSpecification();
         $filter = $inputFactory->createInputFilter($spec);
         $inputFilter->add($filter, $name);
         // Recursively attach sub filters
         $this->attachInputFilterDefaults($filter, $childFieldset);
         // We need to copy the inputs to the collection input filter to ensure that all sub filters are added
         if ($inputFilter instanceof CollectionInputFilter) {
             $inputFilter = $this->addInputsToCollectionInputFilter($inputFilter);
         }
     }
 }
 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));
 }