Passed
Push — master ( b3953e...c3d70c )
by Jan
01:24
created

PurePhpXmlWriter::_writeEol()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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 PurePhpXmlWriter;
16
17
18
class PurePhpXmlWriter
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
     * File encoding
37
     *
38
     * @var string
39
     */
40
    private $_encoding;
41
42
    /**
43
     * Prefix of file name (used only with temporary files)
44
     *
45
     * @var string
46
     */
47
    private $_fileNamePrefix;
48
49
    /**
50
     * Write mode for file
51
     *
52
     * @var string
53
     * @see https://secure.php.net/manual/en/function.fopen.php
54
     */
55
    private $_writeMode;
56
57
    /**
58
     * Indicator if EOL should be used
59
     *
60
     * @var bool
61
     */
62
    private $_isCompressed;
63
64
    /**
65
     * XML file header
66
     *
67
     * @var string
68
     */
69
    private $_fileHeader;
70
71
    /**
72
     * Indicates how deep child element is
73
     *
74
     * @var int
75
     */
76
    private $_elementDeep = 0;
77
78
    /**
79
     * Setter for file name
80
     *
81
     * @param $filename
82
     */
83
    public function setFileName($filename){
84
        $this->_fileName = $filename;
85
    }
86
87
    /**
88
     * Setter for encoding
89
     *
90
     * @param $encoding
91
     */
92
    public function setEncoding($encoding){
93
       $this->_encoding = $encoding;
94
    }
95
96
    /**
97
     * Setter for file name prefix (for generated names only)
98
     *
99
     * @param $fileNamePrefix
100
     */
101
    public function setFileNamePrefix($fileNamePrefix){
102
        $this->_fileNamePrefix = $fileNamePrefix;
103
    }
104
105
    /**
106
     * Setter for write mode
107
     *
108
     * @param $writeMode
109
     * @see https://secure.php.net/manual/en/function.fopen.php
110
     */
111
    public function setWriteMode($writeMode){
112
        $this->_writeMode = $writeMode;
113
    }
114
115
    /**
116
     * Setter for compressed format (EOL used or not)
117
     *
118
     * @param $compressed bool
119
     */
120
    public function setIsCompressed($isCompressed){
121
        $this->_isCompressed = $isCompressed;
122
    }
123
124
125
    /**
126
     * Set file header
127
     *
128
     * @param string $fileHeader
129
     */
130
    public function setHeader($fileHeader = null){
131
132
        /**
133
         * Set standard XML header if not defined
134
         */
135
        if($fileHeader === null){
136
            $this->_fileHeader = '<?xml version="1.0" encoding="' . $this->_encoding .'"?>';
137
        }
138
        else{
139
            $this->_fileHeader = $fileHeader;
140
        }
141
    }
142
143
    /**
144
     * Getter for file name
145
     *
146
     * @return string
147
     */
148
    public function getFileName(){
149
        return $this->_fileName;
150
    }
151
152
    /**
153
     * Constructor
154
     *
155
     * @param string $fileName
156
     * @param bool $autoOpenFile Indicates if file should be opened immediately
157
     * @param string $encoding
158
     * @param string $fileNamePrefix
159
     * @param string $writeMode
160
     * @param bool $compressed Indicates if EOL should be used or not
161
     */
162
    public function __construct($fileName = null, $autoOpenFile = false, $encoding = 'utf-8', $fileNamePrefix = 'ppxw',
163
        $writeMode = 'w', $isCompressed = false)
164
    {
165
        /**
166
         * Setters
167
         */
168
        $this->setEncoding($encoding);
169
        $this->setFileNamePrefix($fileNamePrefix);
170
        $this->setWriteMode($writeMode);
171
        $this->setIsCompressed($isCompressed);
172
        $this->setHeader();
173
174
        /**
175
         * Generate filename if needed
176
         */
177
        if($fileName === null){
178
            $this->setFileName(tempnam(sys_get_temp_dir(), $this->_fileNamePrefix));
179
        }
180
        else{
181
            $this->setFileName($fileName);
182
        }
183
184
        /**
185
         * Autoopen file if needed
186
         */
187
        if($autoOpenFile === true) {
188
            $this->openFile();
189
        }
190
    }
191
192
    /**
193
     * Destructor
194
     *
195
     * Explicitly close the file to make a sure buffer has been written
196
     */
197
    public function __destruct()
198
    {
199
        $this->closeFile();
200
    }
201
202
    /**
203
     * Open XML file
204
     */
205
    public function openFile($autoAddHeader = true){
206
        try {
207
            $this->_filePointer = fopen($this->_fileName, $this->_writeMode);
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen($this->_fileName, $this->_writeMode) can also be of type false. However, the property $_filePointer is declared as type resource. Maybe add an additional type check?

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 the id property of an instance of the Account 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.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
208
        }
209
        catch (\Exception $e){
210
            die('File cannot be opened: ' . $e->getMessage());
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
211
        }
212
213
        if($autoAddHeader === true){
214
            $this->writeHeader();
215
        }
216
    }
217
218
    /**
219
     * Close XML file if is opened
220
     */
221
    public function closeFile(){
222
        if(is_resource($this->_filePointer) === true){
223
            fclose($this->_filePointer);
224
        }
225
    }
226
227
    /**
228
     * Write the EOL if file is not compressed
229
     */
230
    private function _writeEol(){
231
        if($this->_isCompressed === false){
232
            fwrite($this->_filePointer, PHP_EOL);
233
        }
234
    }
235
236
    /**
237
     * Write the Tabs if file is not compressed
238
     */
239
    private function _writeTabs(){
240
        if($this->_isCompressed === false){
241
            for($a = 0; $a < $this->_elementDeep; $a++) {
242
                fwrite($this->_filePointer, "\t");
243
            }
244
        }
245
    }
246
247
    /**
248
     * Write string to file
249
     *
250
     * @param string $string
251
     * @param bool $useTabs Indicates if use tabs
252
     * @param bool $useEol Indicates if use EOL
253
     */
254
    private function _writeString($string = '', $useTabs = true, $useEol = true){
255
        if($useTabs === true){
256
            $this->_writeTabs();
257
        }
258
259
        fwrite($this->_filePointer, $string);
260
261
        if($useEol === true){
262
            $this->_writeEol();
263
        }
264
    }
265
266
    /**
267
     * Write file header
268
     */
269
    public function writeHeader(){
270
        $this->_writeString($this->_fileHeader, false, true);
271
    }
272
273
    /**
274
     * Open XML element
275
     *
276
     * @param $tag
277
     * @param bool $expectedChildren Indicates if children are expected
278
     */
279
    public function openXMLElement($tag, $expectedChildren = true)
280
    {
281
        $this->_writeString('<' . $tag . '>', true, $expectedChildren);
282
        $this->_elementDeep++;
283
    }
284
285
    /**
286
     * Close XML element
287
     *
288
     * @param $tag
289
     * @param bool $expectedChildren Indicates if children are expected
290
     */
291
    public function closeXMLElement($tag, $expectedChildren = true)
292
    {
293
        $this->_elementDeep--;
294
        $this->_writeString('</' . $tag . '>', $expectedChildren,true);
295
    }
296
297
    /**
298
     * Write blank XML element
299
     *
300
     * @param $tag
301
     */
302
    public function blankXMLElement($tag)
303
    {
304
        $this->_writeString('<' . $tag . '/>', true,true);
305
306
    }
307
308
    /**
309
     * Save element with value
310
     *
311
     * @param $tag
312
     * @param $value
313
     * @param int $decimals Only using with number
314
     * @param bool $useCdata
315
     * @param bool $forceCdata
316
     */
317
    public function saveElementWithValue($tag, $value, $decimals = 0, $useCdata = true, $forceCdata = false){
318
319
        /**
320
         * Empty element
321
         */
322
        if (empty($value)) {
323
            $this->blankXMLElement($tag);
324
        }
325
326
        /**
327
         * Non-empty element
328
         */
329
        if( $useCdata === true && (is_numeric($value) === false || $forceCdata === true) ){
330
            if(is_numeric($value) == true){
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
331
                $completeValue = '<![CDATA[' . number_format($value, $decimals) . ']]>';
332
            }
333
            else {
334
                $completeValue = '<![CDATA[' . $value . ']]>';
335
            }
336
        }
337
        else{
338
            if(is_numeric($value) === true) {
339
                $completeValue = number_format($value, $decimals);
340
            }
341
            else{
342
                $completeValue = $value;
343
            }
344
        }
345
346
        $this->openXMLElement($tag, false);
347
        $this->_writeString($completeValue, false, false);
348
        $this->closeXMLElement($tag, false);
349
    }
350
351
}