Completed
Push — master ( 134289...710834 )
by Bernhard
01:32
created

File::retrieveLast()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
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
     * Get the content of the files storage
109
     *
110
     * @return string
111
     */
112
    protected function getStorageContent()
113
    {
114
        return file_get_contents($this->getLogFilePath());
115
    }
116
117
    /**
118
     * Retrieves retrieves the last booking from the storage
119
     *
120
     * @param boolean $includeMetaTickets Whether or not the retrieved booking can be a meta ticket
121
     *
122
     * @return \Wicked\Timely\Entities\Booking
123
     */
124
    public function retrieveLast($includeMetaTickets = false) {
125
        $tmp = $this->retrieve(null, null, null, 1, true, $includeMetaTickets);
126
        return array_pop($tmp);
127
    }
128
129
    /**
130
     * Retrieves one or several bookings from the storage. Bookings can be filtered by pattern,
131
     * date, etc.
132
     *
133
     * @param null|string  $pattern   A pattern to filter ticket IDs for. Defaults to NULL
134
     * @param null|integer $toDate    Date up to which bookings will be returned. Defaults to NULL
135
     * @param null|integer $fromDate  Date from which on bookings will be returned. Defaults to NULL
136
     * @param null|integer $limit     Number of non-meta bookings the retrieval is limited to. Defaults to NULL
137
     * @param boolean      $dontClip  Whether or not the retrieved bookings should be clipped where appropriate. Defaults to FALSE
138
     * @param boolean      $countMeta Whether or not meta tickets will be included in the counter which is used for our limit
139
     *
140
     * @return \Wicked\Timely\Entities\Booking[]
141
     */
142
    public function retrieve($pattern = null, $toDate = null, $fromDate = null, $limit = null, $dontClip = false, $countMeta = false)
143
    {
144
        // test if we got a pattern, if not match against all
145
        if (is_null($pattern)) {
146
            $pattern = '*';
147
        }
148
        // test if we got some dates to filter by
149
        if (is_null($toDate)) {
150
            $toDate = 9999999999;
151
        }
152
        if (is_null($fromDate)) {
153
            $fromDate = 0;
154
        }
155
156
        // get the raw entries
157
        $rawData = $this->getStorageContent();
158
        $rawEntries = explode(self::LINE_BREAK, rtrim($rawData, self::LINE_BREAK));
159
160
        $entries = array();
161
162
        // iterate them and generate the entities
163
        $bookingKey = null;
164
        $bookingCount = 0;
165
        foreach ($rawEntries as $key => $rawEntry) {
166
            // get the potential entry and filter them by ticket ID
167
            $entry = explode(self::SEPARATOR, trim($rawEntry, ' |'));
168
            $timestamp = strtotime($entry[0]);
169
            if (isset($entry[1]) &&
170
                (fnmatch($pattern, $entry[1]) || isset(BookingFactory::getAllMetaTicketIds()[$entry[1]])) &&
171
                $timestamp > $fromDate && $timestamp < $toDate
172
            ) {
173
                // collect the actual booking
174
                $comment = isset($entry[2]) ? $entry[2] : '';
175
                $booking = BookingFactory::getBooking($comment, $entry[1], $entry[0]);
176
                $entries[] = $booking;
177
178
                // increase the booking counter
179
                if (!$booking->isMetaBooking() || $countMeta) {
180
                    $bookingCount ++;
181
                }
182
183
                // if clipping is not omitted we will add the rear clipping to our collection.
184
                // We do it here to make sure we get the correct day
185
                if (count($entries) === 1 && !$dontClip) {
186
                    // test if the last booking is from the today, if not we have to clip at the end of the last booked day
187
                    $bookingTime = new \DateTime($booking->getTime());
188
                    $now = new \DateTime();
189
                    $interval = $bookingTime->diff($now);
190
                    if ($interval->days === 0) {
191
                        $entries[] = BookingFactory::getBooking('', Clipping::CLIPPING_TAG_REAR);
192
                    } else {
193
                        $entries[] = BookingFactory::getBooking('', Clipping::CLIPPING_TAG_REAR, date('Y-m-d', strtotime($booking->getTime()) + 24 * 60 * 60));
194
                    }
195
                    // reverse entries array to let it start with our clipping again
196
                    $entries = array_reverse($entries);
197
                }
198
199
                // collect keys we found something for, for later re-use
200
                $bookingKey = $key;
201
202
                // break if we got as much bookings as our limit is
203
                if (!is_null($limit) && $limit <= $bookingCount) {
204
                    break;
205
                }
206
            }
207
        }
208
209
        // clip the front, but only if we filter by from date
210
        if (!$dontClip && $fromDate !== 0) {
211
            $entries[] = BookingFactory::getBooking('', Clipping::CLIPPING_TAG_FRONT, $fromDate);
212
213
            // move some bookings into the past to get the startbooking of a potential task we might need
214
            for ($i = $bookingKey + 1; $i < count($rawEntries); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
215
                $entry = explode(self::SEPARATOR, trim($rawEntries[$i], ' |'));
216
                $comment = isset($entry[2]) ? $entry[2] : '';
217
                $booking = BookingFactory::getBooking($comment, $entry[1], $entry[0]);
218
                $entries[] = $booking;
219
                // break after the first non-meta booking
220
                if (!$booking->isMetaBooking()) {
221
                    break;
222
                }
223
            }
224
        }
225
226
        return $entries;
227
    }
228
}
229