Passed
Push — master ( 51be4e...ecae65 )
by Vítězslav
04:27
created

ToFile   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 345
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 132
dl 0
loc 345
ccs 0
cts 184
cp 0
rs 6.4799
c 0
b 0
f 0
wmc 54

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B setupLogFiles() 0 28 6
F addToLog() 0 52 19
A renameLogFile() 0 7 2
A singleton() 0 8 2
A __destruct() 0 7 3
B error() 0 31 9
B testDirectory() 0 38 10
A getLogStyle() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like ToFile often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ToFile, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Třída pro logování.
4
 *
5
 * @author    Vitex <[email protected]>
6
 * @copyright 2009-2016 [email protected] (G)
7
 */
8
9
namespace Ease\Logger;
10
11
class ToFile extends ToMemory
12
{
13
    /**
14
     * Předvolená metoda logování.
15
     *
16
     * @var string
17
     */
18
    public $logType = 'file';
19
20
    /**
21
     * Adresář do kterého se zapisují logy.
22
     *
23
     * @var string dirpath
24
     */
25
    public $logPrefix = null;
26
27
    /**
28
     * Soubor s do kterého se zapisuje log.
29
     *
30
     * @var string
31
     */
32
    public $logFileName = 'Ease.log';
33
34
    /**
35
     * úroveň logování.
36
     *
37
     * @var string - silent,debug
38
     */
39
    public $logLevel = 'debug';
40
41
    /**
42
     * Soubor do kterého se zapisuje report.
43
     *
44
     * @var string filepath
45
     */
46
    public $reportFile = 'EaseReport.log';
47
48
    /**
49
     * Soubor do kterého se lougují pouze zprávy typu Error.
50
     *
51
     * @var string filepath
52
     */
53
    public $errorLogFile = 'EaseErrors.log';
54
55
    /**
56
     * Odkaz na vlastnící objekt.
57
     *
58
     * @var \Ease\Sand
59
     */
60
    public $parentObject = null;
61
62
    /**
63
     * Filedescriptor Logu.
64
     *
65
     * @var resource
66
     */
67
    private $_logFileHandle = null;
68
69
    /**
70
     * Filedescriptor chybového Logu.
71
     *
72
     * @var resource
73
     */
74
    private $_errorLogFileHandle = null;
75
76
    /**
77
     * ID naposledy ulozene zpravy.
78
     *
79
     * @var int unsigned
80
     */
81
    private $messageID = 0;
82
83
    /**
84
     * Obecné konfigurace frameworku.
85
     *
86
     * @var \Ease\Shared
87
     */
88
    public $easeShared = null;
89
90
    /**
91
     * Saves obejct instace (singleton...).
92
     */
93
    private static $_instance = null;
94
95
    /**
96
     * Logovací třída.
97
     *
98
     * @param string $baseLogDir
99
     */
100
    public function __construct($baseLogDir = null)
101
    {
102
        $this->easeShared = \Ease\Shared::singleton();
103
        $this->setupLogFiles($baseLogDir);
104
    }
105
106
    /**
107
     * Pri vytvareni objektu pomoci funkce singleton (ma stejne parametry, jako
108
     * konstruktor) se bude v ramci behu programu pouzivat pouze jedna jeho
109
     * instance (ta prvni).
110
     *
111
     * @link http://docs.php.net/en/language.oop5.patterns.html Dokumentace a
112
     * priklad
113
     */
114
    public static function singleton()
115
    {
116
        if (!isset(self::$_instance)) {
117
            $Class           = __CLASS__;
118
            self::$_instance = new $Class();
119
        }
120
121
        return self::$_instance;
122
    }
123
124
    /**
125
     * Nastaví cesty logovacích souborů.
126
     * @param string $baseLogDir
127
     */
128
    public function setupLogFiles($baseLogDir = null)
129
    {
130
        if (is_null($baseLogDir)) {
131
            $baseLogDir = $this->logPrefix;
132
        }
133
134
        if (is_null($baseLogDir) && defined('LOG_DIRECTORY')) {
0 ignored issues
show
introduced by
The condition is_null($baseLogDir) is always false.
Loading history...
135
            $baseLogDir = constant('LOG_DIRECTORY');
136
        }
137
138
        if (!empty($baseLogDir)) {
139
            $this->logPrefix = \Ease\Brick::sysFilename($baseLogDir);
140
            if ($this->TestDirectory($this->logPrefix)) {
141
                $this->logFileName  = $this->logPrefix.$this->logFileName;
142
                $this->reportFile   = $this->logPrefix.$this->reportFile;
143
                $this->errorLogFile = $this->logPrefix.$this->errorLogFile;
144
            } else {
145
                $this->logPrefix    = null;
146
                $this->logFileName  = null;
147
                $this->reportFile   = null;
148
                $this->errorLogFile = null;
149
            }
150
        } else {
151
            $this->logType      = 'none';
152
            $this->logPrefix    = null;
153
            $this->logFileName  = null;
154
            $this->reportFile   = null;
155
            $this->errorLogFile = null;
156
        }
157
    }
158
159
    /**
160
     * Zapise zapravu do logu.
161
     *
162
     * @param string $caller  název volajícího objektu
163
     * @param string $message zpráva
164
     * @param string $type    typ zprávy (success|info|error|warning|*)
165
     *
166
     * @return null|boolean byl report zapsán ?
167
     */
168
    public function addToLog($caller, $message, $type = 'message')
169
    {
170
        ++$this->messageID;
171
        if (($this->logLevel == 'silent') && ($type != 'error')) {
172
            return;
173
        }
174
        if (($this->logLevel != 'debug') && ($type == 'debug')) {
175
            return;
176
        }
177
        $this->statusMessages[$type][$this->messageID] = $message;
178
179
        $message = htmlspecialchars_decode(strip_tags(stripslashes($message)));
180
181
        $logLine = date(DATE_ATOM).' ('.$caller.') '.str_replace(['notice', 'message',
182
                'debug', 'report', 'error', 'warning', 'success', 'info', 'mail',],
183
                ['**', '##', '@@', '::'], $type).' '.$message."\n";
184
        if (!isset($this->logStyles[$type])) {
185
            $type = 'notice';
186
        }
187
        if ($this->logType == 'console' || $this->logType == 'both') {
188
            if ($this->runType == 'cgi') {
0 ignored issues
show
Bug Best Practice introduced by
The property runType does not exist on Ease\Logger\ToFile. Did you maybe forget to declare it?
Loading history...
189
                echo $logLine;
190
            } else {
191
                echo '<div style="'.$this->logStyles[$type].'">'.$logLine."</div>\n";
192
                flush();
193
            }
194
        }
195
        if (!empty($this->logPrefix)) {
196
            if ($this->logType == 'file' || $this->logType == 'both') {
197
                if (!empty($this->logFileName)) {
198
                    if (!$this->_logFileHandle) {
199
                        $this->_logFileHandle = fopen($this->logFileName, 'a+');
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen($this->logFileName, 'a+') can also be of type false. However, the property $_logFileHandle 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...
200
                    }
201
                    if ($this->_logFileHandle !== null) {
202
                        fwrite($this->_logFileHandle, $logLine);
203
                    }
204
                }
205
            }
206
            if ($type == 'error') {
207
                if (!empty($this->errorLogFile)) {
208
                    if (!$this->_errorLogFileHandle) {
209
                        $this->_errorLogFileHandle = fopen($this->errorLogFile,
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen($this->errorLogFile, 'a+') can also be of type false. However, the property $_errorLogFileHandle 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...
210
                            'a+');
211
                    }
212
                    if ($this->_errorLogFileHandle) {
213
                        fputs($this->_errorLogFileHandle, $logLine);
214
                    }
215
                }
216
            }
217
        }
218
219
        return true;
220
    }
221
222
    /**
223
     * Přejmenuje soubor s logem.
224
     *
225
     * @param string $newLogFileName new log filename
226
     *
227
     * @return string
228
     */
229
    public function renameLogFile($newLogFileName)
230
    {
231
        $newLogFileName = dirname($this->logFileName).'/'.basename($newLogFileName);
232
        if (rename($this->logFileName, $newLogFileName)) {
233
            return realpath($newLogFileName);
234
        } else {
235
            return realpath($this->logFileName);
236
        }
237
    }
238
239
    /**
240
     * Zkontroluje stav adresáře a upozorní na případné nesnáze.
241
     *
242
     * @param string $directoryPath cesta k adresáři
243
     * @param bool   $isDir         detekovat existenci adresáře
244
     * @param bool   $isReadable    testovat čitelnost
245
     * @param bool   $isWritable    testovat zapisovatelnost
246
     * @param bool   $logToFile     povolí logování do souboru
247
     *
248
     * @return bool konečný výsledek testu
249
     */
250
    public static function testDirectory($directoryPath, $isDir = true,
251
                                         $isReadable = true, $isWritable = true,
252
                                         $logToFile = false)
253
    {
254
        $sanity = true;
255
        if ($isDir) {
256
            if (!is_dir($directoryPath)) {
257
                echo $directoryPath._(' not an folder. Current directory:').' '.getcwd();
258
                if ($logToFile) {
259
                    \Ease\Shared::logger()->addToLog('TestDirectory',
260
                        $directoryPath._(' not an folder. Current directory:').' '.getcwd());
261
                }
262
                $sanity = false;
263
            }
264
        }
265
        if ($isReadable) {
266
            if (!is_readable($directoryPath)) {
267
                echo $directoryPath._(' not an readable folder. Current directory:').' '.getcwd();
268
                if ($logToFile) {
269
                    \Ease\Shared::logger()->addToLog('TestDirectory',
270
                        $directoryPath._(' not an readable folder. Current directory:').' '.getcwd());
271
                }
272
                $sanity = false;
273
            }
274
        }
275
        if ($isWritable) {
276
            if (!is_writable($directoryPath)) {
277
                echo $directoryPath._(' not an writeable folder. Current directory:').' '.getcwd();
278
                if ($logToFile) {
279
                    \Ease\Shared::logger()->addToLog('TestDirectory',
280
                        $directoryPath._(' not an writeable folder. Current directory:').' '.getcwd());
281
                }
282
283
                $sanity = false;
284
            }
285
        }
286
287
        return $sanity;
288
    }
289
290
    /**
291
     * Oznamuje chybovou událost.
292
     *
293
     * @param string $caller     název volající funkce, nebo objektu
294
     * @param string $message    zpráva
295
     * @param mixed  $objectData data k zaznamenání
296
     */
297
    public function error($caller, $message, $objectData = null)
298
    {
299
        if ($this->errorLogFile) {
300
            $logFileHandle = @fopen($this->errorLogFile, 'a+');
301
            if ($logFileHandle) {
0 ignored issues
show
introduced by
$logFileHandle is of type false|resource, thus it always evaluated to false.
Loading history...
302
                if ($this->easeShared->runType == 'web') {
303
                    fputs($logFileHandle,
304
                        \Ease\Brick::printPreBasic($_SERVER)."\n #End of Server enviroment  <<<<<<<<<<<<<<<<<<<<<<<<<<< # \n\n");
305
                } else {
306
                    fputs($logFileHandle,
307
                        \Ease\Brick::printPreBasic($_ENV)."\n #End of CLI enviroment  <<<<<<<<<<<<<<<<<<<<<<<<<<< # \n\n");
308
                }
309
                if (isset($_POST) && count($_POST)) {
310
                    fputs($logFileHandle,
311
                        \Ease\Brick::printPreBasic($_POST)."\n #End of _POST  <<<<<<<<<<<<<<<<<<<<<<<<<<< # \n\n");
312
                }
313
                if (isset($_GET) && count($_GET)) {
314
                    fputs($logFileHandle,
315
                        \Ease\Brick::printPreBasic($_GET)."\n #End of _GET enviroment  <<<<<<<<<<<<<<<<<<<<<<<<<<< # \n\n");
316
                }
317
                if ($objectData) {
318
                    fputs($logFileHandle,
319
                        \Ease\Brick::printPreBasic($objectData)."\n #End of ObjectData >>>>>>>>>>>>>>>>>>>>>>>>>>>># \n\n");
320
                }
321
                fclose($logFileHandle);
322
            } else {
323
                $this->addToLog('Error: Couldn\'t open the '.realpath($this->errorLogFile).' error log file',
324
                    'error');
325
            }
326
        }
327
        $this->addToLog($caller, $message, 'error');
328
    }
329
330
    /**
331
     * Uzavře chybové soubory.
332
     */
333
    public function __destruct()
334
    {
335
        if ($this->_logFileHandle) {
336
            fclose($this->_logFileHandle);
337
        }
338
        if ($this->_errorLogFileHandle) {
339
            fclose($this->_errorLogFileHandle);
340
        }
341
    }
342
343
    /**
344
     * Vrací styl logování.
345
     *
346
     * @param string $logType typ logu warning|info|success|error|notice|*
347
     *
348
     * @return string
349
     */
350
    public function getLogStyle($logType = 'notice')
351
    {
352
        if (key_exists($logType, $this->logStyles)) {
353
            return $this->logStyles[$logType];
354
        } else {
355
            return '';
356
        }
357
    }
358
}
359