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

contributte / application / 6339616833

28 Sep 2023 01:30PM UTC coverage: 82.143% (+0.7%) from 81.429%
6339616833

push

github

f3l1x
Readme: versions

69 of 84 relevant lines covered (82.14%)

0.82 hits per line

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

78.72
/src/Response/CSVResponse.php
1
<?php declare(strict_types = 1);
2

3
namespace Contributte\Application\Response;
4

5
use Nette\Application\Response;
6
use Nette\Http\IRequest as HttpRequest;
7
use Nette\Http\IResponse as HttpResponse;
8
use Nette\InvalidStateException;
9
use Tracy\Debugger;
10

11
/**
12
 * CSV file download response
13
 */
14
class CSVResponse implements Response
15
{
16

17
        protected string $contentType = 'application/octet-stream';
18

19
        protected string $delimiter;
20

21
        /** @var array<int|string, array<scalar>> */
22
        protected array $data;
23

24
        protected string $outputEncoding;
25

26
        protected bool $includeBom;
27

28
        protected string $name;
29

30
        /** @var string[] */
31
        protected array $headers = [
32
                'Expires' => '0',
33
                'Cache-Control' => 'no-cache',
34
                'Pragma' => 'Public',
35
        ];
36

37
        /**
38
         * @param array<int|string, array<scalar>> $data Input data
39
         */
40
        public function __construct(
1✔
41
                array $data,
42
                string $name = 'export.csv',
43
                string $outputEncoding = 'utf-8',
44
                string $delimiter = ';',
45
                bool $includeBom = false
46
        )
47
        {
48
                if (strpos($name, '.csv') === false) {
1✔
49
                        $name = sprintf('%s.csv', $name);
×
50
                }
51

52
                $this->name = $name;
1✔
53
                $this->delimiter = $delimiter;
1✔
54
                $this->data = $data;
1✔
55
                $this->outputEncoding = $outputEncoding;
1✔
56
                $this->includeBom = $includeBom;
1✔
57
        }
1✔
58

59
        public function send(HttpRequest $httpRequest, HttpResponse $httpResponse): void
1✔
60
        {
61
                // Disable tracy bar
62
                if (class_exists(Debugger::class)) {
1✔
63
                        Debugger::$productionMode = true;
1✔
64
                }
65

66
                // Set Content-Type header
67
                $httpResponse->setContentType($this->contentType, $this->outputEncoding);
1✔
68

69
                // Set Content-Disposition header
70
                $httpResponse->setHeader('Content-Disposition', sprintf('attachment; filename="%s"', $this->name));
1✔
71

72
                // Set other headers
73
                foreach ($this->headers as $key => $value) {
1✔
74
                        $httpResponse->setHeader($key, $value);
1✔
75
                }
76

77
                if (function_exists('ob_start')) {
1✔
78
                        ob_start();
1✔
79
                }
80

81
                // Output data
82
                if ($this->includeBom) {
1✔
83
                        echo $this->getBom();
×
84
                }
85

86
                foreach ($this->data as $row) {
1✔
87
                        $csvRow = $this->printCsv($row);
1✔
88

89
                        if (strtolower($this->outputEncoding) === 'utf-8') {
1✔
90
                                echo $csvRow;
1✔
91
                        } elseif (strtolower($this->outputEncoding) === 'windows-1250') {
1✔
92
                                echo iconv('utf-8', $this->outputEncoding, $csvRow);
1✔
93
                        } else {
94
                                echo mb_convert_encoding($csvRow, $this->outputEncoding);
1✔
95
                        }
96
                }
97

98
                if (function_exists('ob_end_flush')) {
1✔
99
                        ob_end_flush();
1✔
100
                }
101
        }
1✔
102

103
        private function getBom(): string
104
        {
105
                switch (strtolower($this->outputEncoding)) {
×
106
                        case 'utf-8':
×
107
                                return b"\xEF\xBB\xBF";
×
108
                        case 'utf-16':
×
109
                                return b"\xFF\xFE";
×
110
                        default:
111
                                return '';
×
112
                }
113
        }
114

115
        /**
116
         * @param array<scalar> $row
117
         */
118
        private function printCsv(array $row): string
1✔
119
        {
120
                $out = fopen('php://memory', 'wb+');
1✔
121

122
                if ($out === false) {
1✔
123
                        throw new InvalidStateException('Unable to open memory stream');
×
124
                }
125

126
                fputcsv($out, $row, $this->delimiter);
1✔
127
                rewind($out);
1✔
128
                $c = stream_get_contents($out);
1✔
129
                fclose($out);
1✔
130

131
                if ($c === false) {
1✔
132
                        throw new InvalidStateException('Unable to read from memory stream');
×
133
                }
134

135
                return $c;
1✔
136
        }
137

138
}
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