• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / forms / 21851792823

10 Feb 2026 04:31AM UTC coverage: 93.412% (-0.07%) from 93.481%
21851792823

push

github

dg
component/model 4 WIP

2070 of 2216 relevant lines covered (93.41%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.86
/src/Forms/Controls/UploadControl.php
1
<?php
2

3
/**
4
 * This file is part of the Nette Framework (https://nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
declare(strict_types=1);
9

10
namespace Nette\Forms\Controls;
11

12
use Nette;
13
use Nette\Forms;
14
use Nette\Forms\Form;
15
use Nette\Http\FileUpload;
16
use Nette\Utils\Arrays;
17
use Stringable;
18
use function implode, ini_get, is_array;
19

20

21
/**
22
 * Text box and browse button that allow users to select a file to upload to the server.
23
 */
24
class UploadControl extends BaseControl
25
{
26
        /** validation rule */
27
        public const Valid = ':uploadControlValid';
28

29
        /** @deprecated use UploadControl::Valid */
30
        public const VALID = self::Valid;
31

32
        private bool $nullable = false;
33

34

35
        public function __construct(string|Stringable|null $label = null, bool $multiple = false)
1✔
36
        {
37
                parent::__construct($label);
1✔
38
                $this->control->type = 'file';
1✔
39
                $this->control->multiple = $multiple;
1✔
40
                $this->setOption('type', 'file');
1✔
41
                $this->addCondition(true) // not to block the export of rules to JS
1✔
42
                        ->addRule($this->isOk(...), Forms\Validator::$messages[self::Valid]);
1✔
43
                $this->addRule(Form::MaxFileSize, null, Forms\Helpers::iniGetSize('upload_max_filesize'));
1✔
44
                if ($multiple) {
1✔
45
                        $this->addRule(Form::MaxLength, 'The maximum allowed number of uploaded files is %d', (int) ini_get('max_file_uploads'));
1✔
46
                }
47

48
                $this->monitor(Form::class, function (Form $form): void {
1✔
49
                        if (!$form->isMethod('post')) {
1✔
50
                                throw new Nette\InvalidStateException('File upload requires method POST.');
51
                        }
52

53
                        $form->getElementPrototype()->enctype = 'multipart/form-data';
1✔
54
                });
1✔
55
        }
1✔
56

57

58
        public function loadHttpData(): void
59
        {
60
                $this->value = $this->getHttpData(Form::DataFile);
1✔
61
        }
1✔
62

63

64
        public function getHtmlName(): string
65
        {
66
                return parent::getHtmlName() . ($this->control->multiple ? '[]' : '');
1✔
67
        }
68

69

70
        /**
71
         * @return static
72
         * @internal
73
         */
74
        public function setValue($value)
75
        {
76
                return $this;
1✔
77
        }
78

79

80
        /** @return FileUpload|FileUpload[]|null */
81
        public function getValue(): FileUpload|array|null
82
        {
83
                return $this->value ?? ($this->nullable ? null : new FileUpload(null));
1✔
84
        }
85

86

87
        /**
88
         * Has been any file uploaded?
89
         */
90
        public function isFilled(): bool
91
        {
92
                return (bool) $this->value;
1✔
93
        }
94

95

96
        /**
97
         * Sets whether getValue() returns null instead of FileUpload with error UPLOAD_ERR_NO_FILE.
98
         */
99
        public function setNullable(bool $value = true): static
1✔
100
        {
101
                $this->nullable = $value;
1✔
102
                return $this;
1✔
103
        }
104

105

106
        public function isNullable(): bool
107
        {
108
                return $this->nullable;
×
109
        }
110

111

112
        /**
113
         * Have been all files successfully uploaded?
114
         * @internal
115
         */
116
        public function isOk(): bool
117
        {
118
                return match (true) {
119
                        !$this->value => false,
1✔
120
                        is_array($this->value) => Arrays::every($this->value, fn(FileUpload $upload): bool => $upload->isOk()),
1✔
121
                        default => $this->value->isOk(),
1✔
122
                };
123
        }
124

125

126
        /**
127
         * @param  (callable(self): bool)|string  $validator
128
         * @return static
129
         */
130
        public function addRule(
1✔
131
                callable|string $validator,
132
                string|Stringable|null $errorMessage = null,
133
                mixed $arg = null,
134
        ) {
135
                if ($validator === Form::Image) {
1✔
136
                        $this->control->accept = implode(', ', Forms\Helpers::getSupportedImages());
1✔
137

138
                } elseif ($validator === Form::MimeType) {
1✔
139
                        $this->control->accept = implode(', ', (array) $arg);
1✔
140

141
                } elseif ($validator === Form::MaxFileSize) {
1✔
142
                        if ($arg > ($ini = Forms\Helpers::iniGetSize('upload_max_filesize'))) {
1✔
143
                                trigger_error("Value of MaxFileSize ($arg) is greater than value of directive upload_max_filesize ($ini).", E_USER_WARNING);
×
144
                        }
145
                        $this->getRules()->removeRule($validator);
1✔
146

147
                } elseif ($validator === Form::MaxLength) {
1✔
148
                        if ($arg > ($ini = ini_get('max_file_uploads'))) {
1✔
149
                                trigger_error("Value of MaxLength ($arg) is greater than value of directive max_file_uploads ($ini).", E_USER_WARNING);
×
150
                        }
151
                        $this->getRules()->removeRule($validator);
1✔
152
                }
153

154
                return parent::addRule($validator, $errorMessage, $arg);
1✔
155
        }
156
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc