1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace Jtotty\CsvLoader; |
||||
6 | |||||
7 | use Jtotty\Steps\CheckGroupOptionsStep; |
||||
8 | use Jtotty\Steps\CheckPupilDobStep; |
||||
9 | use Jtotty\Steps\CheckPupilGenderStep; |
||||
10 | use Jtotty\Steps\CheckPupilNamesStep; |
||||
11 | use Port\Csv\CsvReader; |
||||
12 | use Port\Csv\CsvWriter; |
||||
13 | use Port\Steps\Step\FilterStep; |
||||
14 | use Port\Steps\Step\MappingStep; |
||||
15 | use Port\Steps\Step\ValueConverterStep; |
||||
16 | use Port\Steps\StepAggregator as Workflow; |
||||
17 | use Port\ValueConverter\DateTimeValueConverter; |
||||
18 | use Port\Writer\ArrayWriter; |
||||
19 | |||||
20 | class CsvLoader |
||||
21 | { |
||||
22 | /** |
||||
23 | * Holds an instance of SplFileObject. |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
24 | * |
||||
25 | * @var SplFileObject |
||||
26 | */ |
||||
27 | private $file; |
||||
28 | |||||
29 | /** |
||||
30 | * Holds an isntance of file contents as an associative array. |
||||
31 | * |
||||
32 | * @var array |
||||
33 | */ |
||||
34 | private $contents = []; |
||||
35 | |||||
36 | /** |
||||
37 | * Holds an instance of the column name mappings. |
||||
38 | * |
||||
39 | * @var array |
||||
40 | */ |
||||
41 | private $columnMap; |
||||
42 | |||||
43 | /** |
||||
44 | * Holds an instance of the \Port\Csv\CsvReader. |
||||
45 | * |
||||
46 | * @var \Port\Csv\CsvReader |
||||
47 | */ |
||||
48 | private $reader; |
||||
49 | |||||
50 | /** |
||||
51 | * Holds an instanec of the \Port\Steps\StepAggregator. |
||||
52 | * |
||||
53 | * @var \Port\Steps\StepAggregator |
||||
54 | */ |
||||
55 | private $workflow; |
||||
56 | |||||
57 | /** |
||||
58 | * Constructor method. |
||||
59 | */ |
||||
60 | public function __constructor() |
||||
61 | { |
||||
62 | } |
||||
63 | |||||
64 | /** |
||||
65 | * Load the file to the SplFileObject. |
||||
66 | * |
||||
67 | * @return void |
||||
68 | */ |
||||
69 | public function loadFile(string $file_path) |
||||
70 | { |
||||
71 | // Set the file |
||||
72 | $this->file = new \SplFileObject($file_path); |
||||
0 ignored issues
–
show
It seems like
new SplFileObject($file_path) of type SplFileObject is incompatible with the declared type Jtotty\CsvLoader\SplFileObject of property $file .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
73 | |||||
74 | // Add file to reader |
||||
75 | $this->reader = new CsvReader($this->file); |
||||
76 | $this->reader->setHeaderRowNumber(0, CsvReader::DUPLICATE_HEADERS_INCREMENT); |
||||
77 | |||||
78 | // Initialise the workflow!! |
||||
79 | $this->createWorkFlow(); |
||||
80 | } |
||||
81 | |||||
82 | /** |
||||
83 | * Starts the workflow to process the array data. |
||||
84 | * |
||||
85 | * @return void |
||||
86 | */ |
||||
87 | public function createWorkFlow() |
||||
88 | { |
||||
89 | // Initialise Workflow |
||||
90 | $this->workflow = new Workflow($this->reader); |
||||
91 | |||||
92 | // The modified array data will be saved to `$this->contents` |
||||
93 | $writer = new ArrayWriter($this->contents); |
||||
94 | $this->workflow->addWriter($writer); |
||||
95 | } |
||||
96 | |||||
97 | /** |
||||
98 | * Returns the number of data rows. |
||||
99 | * |
||||
100 | * @return Integer |
||||
101 | */ |
||||
102 | public function getDataCount() |
||||
103 | { |
||||
104 | return $this->reader->count(); |
||||
105 | } |
||||
106 | |||||
107 | /** |
||||
108 | * Returns the column headings from the uploaded csv. |
||||
109 | * |
||||
110 | * @return Array |
||||
111 | */ |
||||
112 | public function getColumnHeadings() |
||||
113 | { |
||||
114 | return $this->reader->getColumnHeaders(); |
||||
115 | } |
||||
116 | |||||
117 | /** |
||||
118 | * Run the workflow. |
||||
119 | * |
||||
120 | * @return void |
||||
121 | */ |
||||
122 | public function processData() |
||||
123 | { |
||||
124 | $this->workflow->process(); |
||||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * Stop the workflow so we can unlink the file. |
||||
129 | * |
||||
130 | * @return void |
||||
131 | */ |
||||
132 | public function stopWorkflow() |
||||
133 | { |
||||
134 | $this->workflow = null; |
||||
135 | } |
||||
136 | |||||
137 | /** |
||||
138 | * Sets the data column mapping array. |
||||
139 | * |
||||
140 | * @return void |
||||
141 | */ |
||||
142 | public function setColumnMap(array $columnMap) |
||||
143 | { |
||||
144 | $this->columnMap = $columnMap; |
||||
145 | } |
||||
146 | |||||
147 | /** |
||||
148 | * Remove rows that have no data in all columns. |
||||
149 | * |
||||
150 | * @return void |
||||
151 | */ |
||||
152 | public function removeEmptyRowsStep() |
||||
153 | { |
||||
154 | $columnCount = count($this->getColumnHeadings()); |
||||
155 | |||||
156 | $filterStep = new FilterStep(); |
||||
157 | $filterStep->add(function ($input) use ($columnCount) { |
||||
158 | $blanks = 0; |
||||
159 | foreach ($input as $value) { |
||||
160 | if (empty($value)) { |
||||
161 | ++$blanks; |
||||
162 | } |
||||
163 | } |
||||
164 | |||||
165 | return $blanks !== $columnCount; |
||||
166 | }); |
||||
167 | |||||
168 | $this->workflow->addStep($filterStep); |
||||
169 | } |
||||
170 | |||||
171 | /** |
||||
172 | * Renames the column names according to the map. |
||||
173 | * |
||||
174 | * @return void |
||||
175 | */ |
||||
176 | public function mapColumnNamesStep() |
||||
177 | { |
||||
178 | // Create a mapping step |
||||
179 | $mappingStep = new MappingStep(); |
||||
180 | |||||
181 | // Iterate through the column names that need changing |
||||
182 | foreach ($this->columnMap as $key => $value) { |
||||
183 | $mappingStep->map('[' . $key . ']', '[' . $value . ']'); |
||||
184 | } |
||||
185 | |||||
186 | // Add to the workflow |
||||
187 | $this->workflow->addStep($mappingStep); |
||||
188 | } |
||||
189 | |||||
190 | /** |
||||
191 | * Converts date of birth to correct format. |
||||
192 | * |
||||
193 | * @return void |
||||
194 | */ |
||||
195 | public function convertDobStep() |
||||
196 | { |
||||
197 | // Format the dob string so we can convert it correctly |
||||
198 | $this->workflow->addStep(new CheckPupilDobStep()); |
||||
199 | |||||
200 | // Convert from input format to output |
||||
201 | $converterStep = new ValueConverterStep(); |
||||
202 | $converterStep->add('[DOB]', new DateTimeValueConverter(null, 'Y-m-d')); |
||||
203 | |||||
204 | $this->workflow->addStep($converterStep); |
||||
205 | } |
||||
206 | |||||
207 | /** |
||||
208 | * Very specific method to check if a user has entered |
||||
209 | * the entire pupil's name into one column (Either forename or surname). |
||||
210 | */ |
||||
211 | public function checkPupilNamesStep() |
||||
212 | { |
||||
213 | $this->workflow->addStep(new CheckPupilNamesStep()); |
||||
214 | } |
||||
215 | |||||
216 | /** |
||||
217 | * Step to check for validity of pupil gender and convert to |
||||
218 | * appropriate 'male' or 'female' string value. |
||||
219 | */ |
||||
220 | public function checkPupilGenderStep() |
||||
221 | { |
||||
222 | $this->workflow->addStep(new CheckPupilGenderStep()); |
||||
223 | } |
||||
224 | |||||
225 | /** |
||||
226 | * Very specific method to convert the additional attributes |
||||
227 | * to. |
||||
228 | */ |
||||
229 | public function checkGroupOptionValuesStep(array $options) |
||||
230 | { |
||||
231 | $this->workflow->addStep(new CheckGroupOptionsStep($options)); |
||||
232 | } |
||||
233 | |||||
234 | /** |
||||
235 | * Returns the content of the csv file as array. |
||||
236 | */ |
||||
237 | public function getProcessedContents() |
||||
238 | { |
||||
239 | return $this->contents; |
||||
240 | } |
||||
241 | |||||
242 | /** |
||||
243 | * Writes contents of an array to a csv file. |
||||
244 | */ |
||||
245 | public function writeToCsv(array $data, string $filePath) |
||||
246 | { |
||||
247 | $writer = new CsvWriter(','); // Set delimiter to comma (default = semicolon) |
||||
248 | $writer->setStream(fopen($filePath, 'w')); |
||||
0 ignored issues
–
show
It seems like
fopen($filePath, 'w') can also be of type false ; however, parameter $stream of Port\Writer\AbstractStreamWriter::setStream() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
249 | |||||
250 | // Write column headers |
||||
251 | $columnHeaders = array_keys($data[0]); |
||||
252 | $writer->writeItem($columnHeaders); |
||||
253 | |||||
254 | // Get row data and write |
||||
255 | foreach ($data as $pupil) { |
||||
256 | $writer->writeItem(array_values($pupil)); // Reset associative keys to indexes |
||||
257 | } |
||||
258 | |||||
259 | $writer->finish(); |
||||
260 | } |
||||
261 | } |
||||
262 |