LogfileHandler::__construct()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
cc 3
eloc 11
nc 4
nop 4
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Logger
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Logger\Handler;
16
17
use Phossa2\Logger\Message\Message;
18
use Phossa2\Logger\Exception\LogicException;
19
use Phossa2\Logger\Formatter\FormatterInterface;
20
21
/**
22
 * LogfileHandler
23
 *
24
 * Log to a file with file rotation support
25
 *
26
 * @package Phossa2\Logger
27
 * @author  Hong Zhang <[email protected]>
28
 * @see     StreamHandler
29
 * @version 2.0.0
30
 * @since   2.0.0 added
31
 * @since   2.0.1 updated constructor
32
 */
33
class LogfileHandler extends StreamHandler
34
{
35
    /**
36
     * rotation type
37
     * @var    int
38
     */
39
    const ROTATE_NONE =  0; // do not rotate
40
    const ROTATE_DATE = -1; // rotate by date
41
42
    /**
43
     * Constructor
44
     *
45
     * @param  string $path full path
46
     * @param  int $rotate rotate type or filesize in MB
47
     * @param  FormatterInterface $formatter
48
     * @param  bool $stopPropagation
49
     * @throws LogicException if path not writable
50
     * @access public
51
     * @since  2.0.1 removed level param
52
     */
53
    public function __construct(
54
        /*# string */ $path,
55
        /*# int */ $rotate = self::ROTATE_NONE,
56
        FormatterInterface $formatter = null,
57
        /*# bool */ $stopPropagation = false
58
    ) {
59
        // remove prefix 'file://' if any
60
        if ('file://' === substr($path, 0, 7)) {
61
            $path = substr($path, 7);
62
        }
63
64
        // check file path
65
        $this->checkPath($path);
66
67
        // rotate file ?
68
        if (file_exists($path)) {
69
            $this->doRotation($path, $rotate);
70
        }
71
72
        parent::__construct($path, $formatter, $stopPropagation);
73
    }
74
75
    /**
76
     * Check file path
77
     *
78
     * @param  string $path
79
     * @throws LogicException if directory failure etc.
80
     * @access protected
81
     */
82
    protected function checkPath(/*# string */$path)
83
    {
84
        // get the directory
85
        $dir = dirname(realpath($path));
86
87
        if (!is_dir($dir)) {
88
            mkdir($dir, 0777, true);
89
        }
90
91
        if (!is_dir($dir) || !is_writable($dir)) {
92
            throw new LogicException(
93
                Message::get(Message::MSG_PATH_NONWRITABLE, $dir),
94
                Message::MSG_PATH_NONWRITABLE
95
            );
96
        }
97
    }
98
99
    /**
100
     * Rotate file on start
101
     *
102
     * @param  string $path
103
     * @param  int $type
104
     * @return bool rotation status
105
     * @access protected
106
     */
107
    protected function doRotation(
108
        /*# string */ $path,
109
        /*# int */ $type
110
    )/*# : bool */ {
111
        switch ($type) {
112
            // no rotation
113
            case self::ROTATE_NONE:
114
                return true;
115
116
            // rotate by date
117
            case self::ROTATE_DATE:
118
                return $this->rotateByDate($path);
119
120
            // rotate by size
121
            default:
122
                return $this->rotateBySize($path, $type);
123
        }
124
    }
125
126
    /**
127
     * Rotate $path to $path_20160616
128
     *
129
     * @param  string $path
130
     * @param  string $format date format
131
     * @return bool rotation status
132
     * @access protected
133
     */
134
    protected function rotateByDate(
135
        /*# string */ $path,
136
        /*# string */ $format = 'Ymd'
137
    )/*# : bool */ {
138
        $time = filectime($path);
139
        return rename($path, $path . '_' . date($format, $time));
140
    }
141
142
    /**
143
     * Rotate $path if filesize > the specified in MB
144
     *
145
     * Rotate to $path.201606141310 (hour & minute)
146
     *
147
     * @param  string $path
148
     * @param  int $size size in MB
149
     * @return bool rotation status
150
     * @access protected
151
     */
152
    protected function rotateBySize(
153
        /*# string */ $path,
154
        /*# int */ $size
155
    )/*# : bool */ {
156
        if (round(filesize($path) / (1024 * 1024), 2) > $size) {
157
            return $this->rotateByDate($path, 'YmdHi');
158
        }
159
        return true;
160
    }
161
}
162