1 | <?php |
||||
2 | |||||
3 | namespace Jackal\Copycat\Writer; |
||||
4 | |||||
5 | use SplFileInfo; |
||||
6 | use Symfony\Component\OptionsResolver\OptionsResolver; |
||||
7 | |||||
8 | /** |
||||
9 | * Class SQLLoadDataLocalWriter |
||||
10 | * @package Jackal\Copycat\Writer |
||||
11 | */ |
||||
12 | class SQLLoadDataLocalWriter extends CSVFileWriter |
||||
13 | { |
||||
14 | /** |
||||
15 | * @var string |
||||
16 | */ |
||||
17 | protected $sqlOutputFilePathname; |
||||
18 | |||||
19 | /** |
||||
20 | * @var string |
||||
21 | */ |
||||
22 | protected $tableName; |
||||
23 | |||||
24 | /** |
||||
25 | * @var array |
||||
26 | */ |
||||
27 | protected $headers = []; |
||||
28 | |||||
29 | /** |
||||
30 | * SQLLoadDataLocalWriter constructor. |
||||
31 | * @param $tableName |
||||
32 | * @param $outputFilePathname |
||||
33 | * @param array $options |
||||
34 | */ |
||||
35 | public function __construct($tableName, $outputFilePathname, $options = []) |
||||
36 | { |
||||
37 | if (!is_dir(dirname($outputFilePathname))) { |
||||
38 | mkdir(dirname($outputFilePathname), 0775, true); |
||||
39 | } |
||||
40 | |||||
41 | touch($outputFilePathname); |
||||
42 | |||||
43 | $outputFile = new SplFileInfo($outputFilePathname); |
||||
44 | |||||
45 | $localPath = realpath($outputFile->getPathname()); |
||||
46 | $csvOutputFilePathname = str_replace('.' . $outputFile->getExtension(), '.csv', $localPath); |
||||
47 | |||||
48 | $opts = [ |
||||
49 | 'header' => true, |
||||
50 | 'delimiter' => "\t", |
||||
51 | ]; |
||||
52 | foreach (['columns','delimiter','enclosure','header','replace_file'] as $option) { |
||||
53 | if (array_key_exists($option, $options)) { |
||||
54 | $opts[$option] = $options[$option]; |
||||
55 | } |
||||
56 | } |
||||
57 | |||||
58 | parent::__construct($csvOutputFilePathname, $opts); |
||||
59 | |||||
60 | $resolver = new OptionsResolver(); |
||||
61 | $resolver->setDefaults([ |
||||
62 | 'replace_file' => false, |
||||
63 | 'delimiter' => $opts['delimiter'], |
||||
64 | 'enclosure' => '"', |
||||
65 | 'header' => $opts['header'], |
||||
66 | 'autoincrement_field' => false, |
||||
67 | 'drop_data' => false, |
||||
68 | 'create_table' => false, |
||||
69 | 'columns' => [], |
||||
70 | ]); |
||||
71 | |||||
72 | $this->options = $resolver->resolve(array_merge($options, $opts)); |
||||
73 | |||||
74 | $this->sqlOutputFilePathname = $localPath; |
||||
75 | $this->tableName = $tableName; |
||||
76 | } |
||||
77 | |||||
78 | /** |
||||
79 | * @param array $item |
||||
80 | */ |
||||
81 | public function writeItem(array $item) |
||||
82 | { |
||||
83 | if ($this->index == 0) { |
||||
84 | $this->headers = array_keys($item); |
||||
85 | } |
||||
86 | parent::writeItem($item); |
||||
87 | } |
||||
88 | |||||
89 | /** |
||||
90 | * |
||||
91 | */ |
||||
92 | public function finish() |
||||
93 | { |
||||
94 | parent::finish(); |
||||
95 | |||||
96 | $dropRecordsString = $this->options['drop_data'] ? sprintf("\n" . 'DELETE FROM %s;', $this->tableName) : null; |
||||
97 | $autoIncrementString = $this->options['autoincrement_field'] ? sprintf('SET %s = NULL', $this->options['autoincrement_field']) : null; |
||||
98 | $rowsToIgnore = $this->options['header'] ? 1 : 0; |
||||
99 | $headers = '(' . implode(', ', $this->headers) . ')'; |
||||
100 | |||||
101 | $delimiter = str_replace(["\t","\n","\r"], ['\\t','\\n','\\r'], $this->options['delimiter']); |
||||
102 | $enclosure = $this->options['enclosure']; |
||||
103 | |||||
104 | $createTableSql = null; |
||||
105 | if ($this->options['create_table']) { |
||||
106 | $h = fopen($this->outputFilePathname, 'r'); |
||||
107 | $columnNames = fgetcsv($h, 0, $this->options['delimiter'], $this->options['enclosure']); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
108 | |||||
109 | $autoIncrementField = $this->options['autoincrement_field'] ? $this->options['autoincrement_field'] . ' int auto_increment not null, ' : ''; |
||||
110 | $primaryKeyField = $this->options['autoincrement_field'] ? ', primary key (' . $this->options['autoincrement_field'] . ')' : ''; |
||||
111 | $createTableSql = sprintf('DROP TABLE IF EXISTS %s;CREATE TABLE %s (%s%s%s);', $this->tableName, $this->tableName, $autoIncrementField, implode(', ', array_map(function ($value) { |
||||
112 | return $value . ' text'; |
||||
113 | }, $columnNames)), $primaryKeyField); |
||||
0 ignored issues
–
show
It seems like
$columnNames can also be of type false and null ; however, parameter $arr1 of array_map() does only seem to accept array , 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
![]() |
|||||
114 | } |
||||
115 | |||||
116 | $contents = <<<SQL |
||||
117 | {$createTableSql}{$dropRecordsString} |
||||
118 | LOAD DATA LOCAL INFILE '{$this->outputFilePathname}' |
||||
119 | INTO TABLE {$this->tableName} |
||||
120 | CHARACTER SET utf8 |
||||
121 | FIELDS |
||||
122 | TERMINATED BY '{$delimiter}' |
||||
123 | ENCLOSED BY '{$enclosure}' |
||||
124 | ESCAPED BY '' |
||||
125 | LINES |
||||
126 | TERMINATED BY '\\n' |
||||
127 | IGNORE $rowsToIgnore LINES |
||||
128 | $headers |
||||
129 | $autoIncrementString |
||||
130 | ; |
||||
131 | SQL; |
||||
132 | file_put_contents($this->sqlOutputFilePathname, $contents); |
||||
133 | } |
||||
134 | } |
||||
135 |