Completed
Push — master ( 1f8449...3785e1 )
by Bernhard
12:25
created

File::retrieve()   F

Complexity

Conditions 20
Paths 640

Size

Total Lines 75
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 0 Features 4
Metric Value
c 7
b 0
f 4
dl 0
loc 75
rs 2.6666
cc 20
eloc 38
nc 640
nop 5

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * \Wicked\Timely\Storage\File
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Bernhard Wick <[email protected]>
15
 * @copyright 2016 Bernhard Wick
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/wick-ed/timely
18
 */
19
20
namespace Wicked\Timely\Storage;
21
22
use Wicked\Timely\Entities\Booking;
23
use Wicked\Timely\Entities\Clipping;
24
use Wicked\Timely\Formatter\FormatterFactory;
25
use Wicked\Timely\Entities\BookingFactory;
26
27
/**
28
 * File storage
29
 *
30
 * @author    Bernhard Wick <[email protected]>
31
 * @copyright 2016 Bernhard Wick
32
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
33
 * @link      https://github.com/wick-ed/timely
34
 */
35
class File implements StorageInterface
36
{
37
38
    /**
39
     * Default character for a line break in the format
40
     *
41
     * @var string LINE_BREAK
42
     */
43
    const LINE_BREAK = ';';
44
45
    /**
46
     * Default character sequence for segment separation
47
     *
48
     * @var string SEPARATOR
49
     */
50
    const SEPARATOR = ' | ';
51
52
    /**
53
     * Name of the log file
54
     *
55
     * @var string DATA_NAME
56
     */
57
    const DATA_NAME = 'timely-log.txt';
58
59
    /**
60
     * Path to the log file
61
     *
62
     * @var string $logFilePath
63
     */
64
    protected $logFilePath;
65
66
    /**
67
     * Default constructor
68
     */
69
    public function __construct()
70
    {
71
        // calculate the default file path
72
        $this->logFilePath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . self::DATA_NAME;
73
        // check if the file exists, if not create it
74
        if (!is_file($this->logFilePath)) {
75
            touch($this->logFilePath);
76
        }
77
    }
78
79
    /**
80
     * Getter for the log file path
81
     *
82
     * @return string
83
     */
84
    public function getLogFilePath()
85
    {
86
        return $this->logFilePath;
87
    }
88
89
    /**
90
     * Stores a single booking
91
     *
92
     * @param \Wicked\Timely\Entities\Booking $booking The booking to store
93
     *
94
     * @return void
95
     */
96
    public function store(Booking $booking)
97
    {
98
        // get the formatter and convert to string
99
        $formatter = FormatterFactory::getFormatter();
100
        $bookString = $formatter->toString($booking);
101
102
        // write the new booking to the beginning of the file
103
        $path = $this->getLogFilePath();
104
        file_put_contents($path, $bookString . file_get_contents($path));
105
    }
106
107
    /**
108
     * Retrieves one or several bookings from the storage. Bookings can be filtered by pattern,
109
     * date, etc.
110
     *
111
     * @param null|string  $pattern  A pattern to filter ticket IDs for. Defaults to NULL
112
     * @param null|integer $toDate   Date up to which bookings will be returned. Defaults to NULL
113
     * @param null|integer $fromDate Date from which on bookings will be returned. Defaults to NULL
114
     * @param null|integer $limit    Number of non-meta bookings the retrieval is limited to. Defaults to NULL
115
     * @param boolean      $dontClip Whether or not the retrieved bookings should be clipped where appropriate. Defaults to FALSE
116
     *
117
     * @return \Wicked\Timely\Entities\Booking[]
118
     */
119
    public function retrieve($pattern = null, $toDate = null, $fromDate = null, $limit = null, $dontClip = false)
120
    {
121
        // test if we got a pattern, if not match against all
122
        if (is_null($pattern)) {
123
            $pattern = '*';
124
        }
125
        // test if we got some dates to filter by
126
        if (is_null($toDate)) {
127
            $toDate = 9999999999;
128
        }
129
        if (is_null($fromDate)) {
130
            $fromDate = 0;
131
        }
132
133
        // get the raw entries
134
        $rawData = file_get_contents($this->getLogFilePath());
135
        $rawEntries = explode(self::LINE_BREAK, rtrim($rawData, self::LINE_BREAK));
136
137
        $entries = array();
138
139
        // if clipping is not omitted we will add the rear clipping to our collection
140
        if (!$dontClip) {
141
            $entries[] = BookingFactory::getBooking('', Clipping::CLIPPING_TAG_REAR);
142
        }
143
144
        // iterate them and generate the entities
145
        $bookingKey = null;
146
        $bookingCount = 0;
147
        foreach ($rawEntries as $key => $rawEntry) {
148
            // get the potential entry and filter them by ticket ID
149
            $entry = explode(self::SEPARATOR, trim($rawEntry, ' |'));
150
            $timestamp = strtotime($entry[0]);
151
            if (isset($entry[1]) &&
152
                (fnmatch($pattern, $entry[1]) || isset(BookingFactory::getAllMetaTicketIds()[$entry[1]])) &&
153
                $timestamp > $fromDate && $timestamp < $toDate
154
            ) {
155
                // collect the actual booking
156
                $comment = isset($entry[2]) ? $entry[2] : '';
157
                $booking = BookingFactory::getBooking($comment, $entry[1], $entry[0]);
158
                $entries[] = $booking;
159
160
                // increase the booking counter
161
                if (!$booking->isMetaBooking()) {
162
                    $bookingCount ++;
163
                }
164
165
                // collect keys we found something for, for later re-use
166
                $bookingKey = $key;
167
168
                // break if we got as much bookings as our limit is
169
                if (!is_null($limit) && $limit <= $bookingCount) {
170
                    break;
171
                }
172
            }
173
        }
174
175
        // clip the front, but only if we filter by from date
176
        if (!$dontClip && $fromDate !== 0) {
177
            $entries[] = BookingFactory::getBooking('', Clipping::CLIPPING_TAG_FRONT, $fromDate);
178
179
            // move some bookings into the past to get the startbooking of a potential task we might need
180
            for ($i = $bookingKey - 1; $i >= 0; $i--) {
181
                $entry = explode(self::SEPARATOR, trim($rawEntries[$i], ' |'));
182
                $comment = isset($entry[2]) ? $entry[2] : '';
183
                $booking = BookingFactory::getBooking($comment, $entry[1], $entry[0]);
184
                $entries[] = $booking;
185
                // break after the first non-meta booking
186
                if ($booking->isMetaBooking()) {
187
                    break;
188
                }
189
            }
190
        }
191
192
        return $entries;
193
    }
194
}
195