1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Main file |
4
|
|
|
* |
5
|
|
|
* All functions for XML writing |
6
|
|
|
* |
7
|
|
|
* @category Controller |
8
|
|
|
* @package PurePhpXmlWriter |
9
|
|
|
* @author Jan Drda <[email protected]> |
10
|
|
|
* @copyright Jan Drda |
11
|
|
|
* @license https://opensource.org/licenses/MIT MIT |
12
|
|
|
* |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace PurePhpGoogleAdsCsvGenerator; |
16
|
|
|
|
17
|
|
|
|
18
|
|
|
class PurePhpGoogleAdsCsvGenerator |
19
|
|
|
{ |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* XML file pointer |
23
|
|
|
* |
24
|
|
|
* @var resource |
25
|
|
|
*/ |
26
|
|
|
private $_filePointer; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* XML file name |
30
|
|
|
* |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
private $_fileName; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* XML file header |
37
|
|
|
* |
38
|
|
|
* @var array |
39
|
|
|
*/ |
40
|
|
|
private $_fileHeader = array( |
41
|
|
|
'Campaign', |
42
|
|
|
'Campaign type', |
43
|
|
|
'Campaign Daily Budget', |
44
|
|
|
'Networks', |
45
|
|
|
'Ad Schedule', |
46
|
|
|
'Location', |
47
|
|
|
'Excluded Webs', |
48
|
|
|
'Ad Group', |
49
|
|
|
'Max CPC', |
50
|
|
|
'Max CPT', |
51
|
|
|
'Keyword', |
52
|
|
|
'Criterion Type', |
53
|
|
|
'Sitelink Text', |
54
|
|
|
'Headline', |
55
|
|
|
'Description Line 1', |
56
|
|
|
'Description Line 2', |
57
|
|
|
'Headline 1', |
58
|
|
|
'Headline 2', |
59
|
|
|
'Headline 3', |
60
|
|
|
'Description', |
61
|
|
|
'Display URL', |
62
|
|
|
'Final URL', |
63
|
|
|
'Path 1', |
64
|
|
|
'Path 2', |
65
|
|
|
'Tracking Template', |
66
|
|
|
'Campaign Status', |
67
|
|
|
'Ad Group Status', |
68
|
|
|
'Creative Status', |
69
|
|
|
'Topics', |
70
|
|
|
'Website', |
71
|
|
|
'Gender', |
72
|
|
|
'Age', |
73
|
|
|
'Website Status', |
74
|
|
|
'Audience', |
75
|
|
|
'Id', |
76
|
|
|
'Status', |
77
|
|
|
'Product Group', |
78
|
|
|
'Product Set Label', |
79
|
|
|
'PLA shop', |
80
|
|
|
'Country of Sale', |
81
|
|
|
'Languages', |
82
|
|
|
'Bid Strategy Type', |
83
|
|
|
'Promotion', |
84
|
|
|
'Approval Status', |
85
|
|
|
'Short headline', |
86
|
|
|
'Long headline', |
87
|
|
|
'Business name', |
88
|
|
|
'Final mobile URL', |
89
|
|
|
'Image', |
90
|
|
|
'Square Image', |
91
|
|
|
'Logo', |
92
|
|
|
'Landscape logo', |
93
|
|
|
'Impression tracking template', |
94
|
|
|
'Impression tracking template 2', |
95
|
|
|
'Ad name', |
96
|
|
|
'Type', |
97
|
|
|
'Desktop Bid Modifier', |
98
|
|
|
'Mobile Bid Modifier', |
99
|
|
|
'Tablet Bid Modifier', |
100
|
|
|
'TV Screen Bid Modifier' |
101
|
|
|
); |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Age groups |
105
|
|
|
* |
106
|
|
|
* @var array |
107
|
|
|
*/ |
108
|
|
|
private $_ageGroups = array( |
109
|
|
|
'Unknown', |
110
|
|
|
'18-24', |
111
|
|
|
'25-34', |
112
|
|
|
'35-44', |
113
|
|
|
'45-54', |
114
|
|
|
'55-64', |
115
|
|
|
'65 or more' |
116
|
|
|
); |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Genders |
120
|
|
|
* |
121
|
|
|
* @var array |
122
|
|
|
*/ |
123
|
|
|
private $_genders = array( |
124
|
|
|
'Unknown', |
125
|
|
|
'Male', |
126
|
|
|
'Female' |
127
|
|
|
); |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Prototype of blank row |
131
|
|
|
* |
132
|
|
|
* @var array |
133
|
|
|
*/ |
134
|
|
|
private $_blankRow; |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Setter for file name |
138
|
|
|
* |
139
|
|
|
* @param $filename |
140
|
|
|
*/ |
141
|
|
|
public function setFileName($filename){ |
142
|
|
|
$this->_fileName = $filename; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Getter for file name |
147
|
|
|
* |
148
|
|
|
* @return string |
149
|
|
|
*/ |
150
|
|
|
public function getFileName(){ |
151
|
|
|
return $this->_fileName; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Constructor |
156
|
|
|
* |
157
|
|
|
* @param string $fileName |
158
|
|
|
*/ |
159
|
|
|
public function __construct($fileName = null) |
160
|
|
|
{ |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Generate filename if needed |
164
|
|
|
*/ |
165
|
|
|
if($fileName === null){ |
166
|
|
|
$this->setFileName('ads.csv'); |
167
|
|
|
} |
168
|
|
|
else{ |
169
|
|
|
$this->setFileName($fileName); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* Autoopen file if needed |
174
|
|
|
*/ |
175
|
|
|
$this->openFile(); |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Generate blank row prototype |
179
|
|
|
*/ |
180
|
|
|
$this->_blankRow = $this->_generateBlankRow(); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Destructor |
185
|
|
|
* |
186
|
|
|
* Explicitly close the file to make a sure buffer has been written |
187
|
|
|
*/ |
188
|
|
|
public function __destruct() |
189
|
|
|
{ |
190
|
|
|
$this->closeFile(); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Open CSV file |
195
|
|
|
*/ |
196
|
|
|
public function openFile(){ |
197
|
|
|
try { |
198
|
|
|
$this->_filePointer = fopen($this->_fileName, "w"); |
|
|
|
|
199
|
|
|
} |
200
|
|
|
catch (\Exception $e){ |
201
|
|
|
die('File cannot be opened: ' . $e->getMessage()); |
|
|
|
|
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Add header |
206
|
|
|
*/ |
207
|
|
|
$this->_writeRawRow($this->_fileHeader); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Close CSV file if is opened |
212
|
|
|
*/ |
213
|
|
|
public function closeFile(){ |
214
|
|
|
if(is_resource($this->_filePointer) === true){ |
215
|
|
|
fclose($this->_filePointer); |
216
|
|
|
} |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Write Raw SV row |
221
|
|
|
*/ |
222
|
|
|
private function _writeRawRow($array, $delimiter = "\t", $enclosure = null){ |
223
|
|
|
if($enclosure == null){ |
224
|
|
|
$enclosure = chr(0); |
225
|
|
|
} |
226
|
|
|
fputcsv($this->_filePointer, $array, $delimiter, $enclosure); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Generate prototype of blank row |
231
|
|
|
* |
232
|
|
|
* @return array |
233
|
|
|
*/ |
234
|
|
|
private function _generateBlankRow(){ |
235
|
|
|
|
236
|
|
|
$blankRow = array(); |
237
|
|
|
foreach ($this->_fileHeader as $value){ |
238
|
|
|
|
239
|
|
|
$blankRow[strtolower(str_replace(' ', '-', $value))] = ''; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
return $blankRow; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Prepare row for write |
247
|
|
|
* |
248
|
|
|
* @param $array |
249
|
|
|
* @return array |
250
|
|
|
*/ |
251
|
|
|
private function _prepareRow($array){ |
252
|
|
|
return array_merge($this->_blankRow, $array); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* Prepare and write row |
257
|
|
|
* |
258
|
|
|
* @param $array |
259
|
|
|
*/ |
260
|
|
|
private function _writeRow($array, $delimiter = "\t", $enclosure = null){ |
261
|
|
|
$this->_writeRawRow($this->_prepareRow($array), $delimiter, $enclosure); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Write campaign data |
266
|
|
|
* @param array $config |
267
|
|
|
*/ |
268
|
|
|
public function writeCampaign( $data = array ( |
269
|
|
|
'campaign' => 'Campaign', |
270
|
|
|
'campaign-type' => 'Search', |
271
|
|
|
'campaign-daily-budget' => '100.00', |
272
|
|
|
'networks' => 'Search;Google Search;Search Partners', |
273
|
|
|
'campaign-status' => 'active' |
274
|
|
|
)){ |
275
|
|
|
|
276
|
|
|
$this->_writeRow($data); |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* Write Ad group |
281
|
|
|
* |
282
|
|
|
* @param array $data |
283
|
|
|
*/ |
284
|
|
|
public function writeAdGroup( $data = array ( |
285
|
|
|
'campaign' => 'Campaign', |
286
|
|
|
'ad-group' => 'Ad Group', |
287
|
|
|
'max-cpc' => '1', |
288
|
|
|
'max-cpt' => '1', |
289
|
|
|
'ad-group-status' => 'Active' |
290
|
|
|
)) |
291
|
|
|
{ |
292
|
|
|
|
293
|
|
|
$this->_writeRow($data); |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Write keyword |
298
|
|
|
* |
299
|
|
|
* @param array $data |
300
|
|
|
*/ |
301
|
|
|
public function writeKeyword( $data = array ( |
302
|
|
|
'campaign' => 'Campaign', |
303
|
|
|
'ad-group' => 'Ad Group', |
304
|
|
|
'keyword' => 'Keyword', |
305
|
|
|
'criterion-type' => 'Phrase', |
306
|
|
|
'status' => 'Active', |
307
|
|
|
)) |
308
|
|
|
{ |
309
|
|
|
|
310
|
|
|
$this->_writeRow($data); |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* Write ad |
315
|
|
|
* |
316
|
|
|
* @param array $data |
317
|
|
|
*/ |
318
|
|
|
public function writeAd( $data = array ( |
319
|
|
|
'campaign' => 'Campaign', |
320
|
|
|
'ad-group' => 'Ad Group', |
321
|
|
|
'description-line-1' => 'Description line 1', |
322
|
|
|
'description-line-2' => 'Description line 2', |
323
|
|
|
'headline-1' => 'Headline 1', |
324
|
|
|
'headline-2' => 'Headline 2', |
325
|
|
|
'headline-3' => 'Headline 3', |
326
|
|
|
'final-url' => 'https://www.final.com/', |
327
|
|
|
'status' => 'Active', |
328
|
|
|
)) |
329
|
|
|
{ |
330
|
|
|
|
331
|
|
|
$this->_writeRow($data); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Write age |
336
|
|
|
* |
337
|
|
|
* @param array $data |
338
|
|
|
*/ |
339
|
|
|
public function writeAge( $data = array ( |
340
|
|
|
'campaign' => 'Campaign', |
341
|
|
|
'ad-group' => 'Ad Group', |
342
|
|
|
'age' => 'Unknown', |
343
|
|
|
'status' => 'Active', |
344
|
|
|
)) |
345
|
|
|
{ |
346
|
|
|
|
347
|
|
|
$this->_writeRow($data); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Write age |
352
|
|
|
* |
353
|
|
|
* @param array $data |
354
|
|
|
*/ |
355
|
|
|
public function writeGender( $data = array ( |
356
|
|
|
'campaign' => 'Campaign', |
357
|
|
|
'ad-group' => 'Ad Group', |
358
|
|
|
'gender' => 'Unknown', |
359
|
|
|
'status' => 'Active', |
360
|
|
|
)) |
361
|
|
|
{ |
362
|
|
|
|
363
|
|
|
$this->_writeRow($data); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* Write all age groups |
368
|
|
|
* |
369
|
|
|
* @param array $data |
370
|
|
|
*/ |
371
|
|
|
public function writeAllAges( $data = array ( |
372
|
|
|
'campaign' => 'Campaign', |
373
|
|
|
'ad-group' => 'Ad Group', |
374
|
|
|
'status' => 'Active', |
375
|
|
|
)) |
376
|
|
|
{ |
377
|
|
|
foreach ($this->_ageGroups as $ageGroup) { |
378
|
|
|
$data['age'] = $ageGroup; |
379
|
|
|
$this->_writeRow($data); |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
/** |
384
|
|
|
* Write all genders |
385
|
|
|
* |
386
|
|
|
* @param array $data |
387
|
|
|
*/ |
388
|
|
|
public function writeAllGenders( $data = array ( |
389
|
|
|
'campaign' => 'Campaign', |
390
|
|
|
'ad-group' => 'Ad Group', |
391
|
|
|
'status' => 'Active', |
392
|
|
|
)) |
393
|
|
|
{ |
394
|
|
|
foreach ($this->_genders as $gender) { |
395
|
|
|
$data['gender'] = $gender; |
396
|
|
|
$this->_writeRow($data); |
397
|
|
|
} |
398
|
|
|
} |
399
|
|
|
} |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.