subject = $subject; } /** * @return mixed */ public function getValue() { $value = $this->subject->value; if (! $this->subject->isValid || ! is_array($value)) { return $value; } // Run filters ~after~ validation, so that is_uploaded_file() // validation is not affected by filters. $filter = $this->subject->getFilterChain(); if (isset($value['tmp_name'])) { // Single file input $value = $filter->filter($value); return $value; } // Multi file input (multiple attribute set) $newValue = []; foreach ($value as $fileData) { if (is_array($fileData) && isset($fileData['tmp_name'])) { $newValue[] = $filter->filter($fileData); } } return $newValue; } /** * @param mixed $context Extra "context" to provide the validator * @return bool */ public function isValid($context = null) { $rawValue = $this->subject->getRawValue(); $validator = $this->injectUploadValidator($this->subject->getValidatorChain()); if (! is_array($rawValue)) { // This can happen in an AJAX POST, where the input comes across as a string $rawValue = [ 'tmp_name' => $rawValue, 'name' => $rawValue, 'size' => 0, 'type' => '', 'error' => UPLOAD_ERR_NO_FILE, ]; } elseif (! isset($rawValue['tmp_name']) && ! isset($rawValue[0]['tmp_name'])) { // This can happen when sent not file and just array $rawValue = [ 'tmp_name' => '', 'name' => '', 'size' => 0, 'type' => '', 'error' => UPLOAD_ERR_NO_FILE, ]; } if (is_array($rawValue) && isset($rawValue['tmp_name'])) { // Single file input $this->subject->isValid = $validator->isValid($rawValue, $context); return $this->subject->isValid; } if (is_array($rawValue) && isset($rawValue[0]['tmp_name'])) { // Multi file input (multiple attribute set) $this->subject->isValid = true; foreach ($rawValue as $value) { if (! $validator->isValid($value, $context)) { $this->subject->isValid = false; return false; // Do not continue processing files if validation fails } } return true; // We return early from the loop if validation fails } return $this->subject->isValid; } /** * @return ValidatorChain */ protected function injectUploadValidator(ValidatorChain $chain) { if (! $this->subject->autoPrependUploadValidator) { return $chain; } // Check if Upload validator is already first in chain $validators = $chain->getValidators(); if ( isset($validators[0]['instance']) && $validators[0]['instance'] instanceof UploadValidator ) { $this->subject->autoPrependUploadValidator = false; return $chain; } $chain->prependByName('fileuploadfile', [], true); $this->subject->autoPrependUploadValidator = false; return $chain; } }