Completed
Push — master ( 3afd02...a4590b )
by Vojta
04:54
created

ReservationsFacade::transformDateTime()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3.3332

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 2
cts 3
cp 0.6667
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
crap 3.3332
1
<?php namespace VojtaSvoboda\Reservations\Facades;
2
3
use Auth;
4
use Carbon\Carbon;
5
use Config;
6
use Event;
7
use Illuminate\Database\Eloquent\Collection;
8
use Illuminate\Support\Facades\DB;
9
use October\Rain\Exception\ApplicationException;
10
use October\Rain\Exception\ValidationException;
11
use VojtaSvoboda\Reservations\Classes\DatesResolver;
12
use VojtaSvoboda\Reservations\Mailers\ReservationAdminMailer;
13
use VojtaSvoboda\Reservations\Mailers\ReservationMailer;
14
use VojtaSvoboda\Reservations\Models\Reservation;
15
use VojtaSvoboda\Reservations\Models\Settings;
16
use VojtaSvoboda\Reservations\Models\Status;
17
18
/**
19
 * Public reservations facade.
20
 *
21
 * Usage: App::make('vojtasvoboda.reservations.facade');
22
 *
23
 * @package VojtaSvoboda\Reservations\Facades
24
 */
25
class ReservationsFacade
26
{
27
    /** @var Reservation $reservations */
28
    private $reservations;
29
30
    /** @var Status $statuses */
31
    private $statuses;
32
33
    /** @var DatesResolver $datesResolver */
34
    private $datesResolver;
35
36
    /** @var array $returningUsersCache */
37
    private $returningUsersCache;
38
39
    /** @var ReservationMailer $mailer */
40
    private $mailer;
41
42
    /** @var ReservationAdminMailer $adminMailer */
43
    private $adminMailer;
44
45
    /**
46 9
     * ReservationsFacade constructor.
47
     *
48 9
     * @param Reservation $reservations
49 9
     * @param Status $statuses
50 9
     * @param DatesResolver $resolver
51 9
     * @param ReservationMailer $mailer
52
     * @param ReservationAdminMailer $adminMailer
53
     */
54
    public function __construct(
55
        Reservation $reservations, Status $statuses, DatesResolver $resolver,
56
        ReservationMailer $mailer, ReservationAdminMailer $adminMailer
57
    ) {
58
        $this->reservations = $reservations;
59
        $this->statuses = $statuses;
60
        $this->datesResolver = $resolver;
61
        $this->mailer = $mailer;
62
        $this->adminMailer = $adminMailer;
63 8
    }
64
65
    /**
66 8
     * Create and store reservation.
67
     *
68
     * @param array $data
69 6
     *
70
     * @return Reservation $reservation
71
     *
72 6
     * @throws ApplicationException
73
     * @throws ValidationException
74
     */
75 6
    public function storeReservation($data)
76
    {
77
        // transform date and time to Carbon
78 6
        $data['date'] = $this->transformDateTime($data);
79
80 6
        // check date availability
81
        $this->checkDate($data);
82
83
        // create reservation
84
        $reservation = $this->reservations->create($data);
85
86
        // calculate reservations by same email
87
        $sameCount = $this->getReservationsWithSameEmailCount($reservation->email);
88
89
        // send reservation confirmation to customer
90
        $this->mailer->send($reservation, $sameCount);
91
92
        // send reservation confirmation to admin
93
        $this->adminMailer->send($reservation, $sameCount);
94
95
        return $reservation;
96
    }
97
98
    /**
99
     * Get all reservations.
100
     *
101
     * @return Collection
102
     */
103
    public function getReservations()
104
    {
105
        return $this->reservations->all();
106
    }
107
108
    /**
109
     * Get all active (not cancelled) reservations.
110
     *
111
     * @return Collection
112
     */
113
    public function getActiveReservations()
114
    {
115
        return $this->reservations->notCancelled()->get();
116
    }
117
118
    /**
119
     * Get all reserved time slots.
120
     *
121
     * @return array
122
     */
123
    public function getReservedDates()
124
    {
125
        $reservations = $this->getActiveReservations();
126
127
        return $this->datesResolver->getDatesFromReservations($reservations);
128
    }
129
130
    /**
131
     * Get all reservations by given date interval.
132
     *
133
     * @param Carbon $since Date from.
134
     * @param Carbon $till Date to.
135 1
     *
136
     * @return mixed
137 1
     */
138
    public function getReservationsByInterval(Carbon $since, Carbon $till)
139
    {
140
        return $this->reservations->whereBetween('date', [$since, $till])->get();
141
    }
142
143
    /**
144
     * Get reservations count by one email.
145
     *
146
     * @param $email
147 1
     *
148
     * @return int
149
     */
150 1
    public function getReservationsWithSameEmailCount($email)
151 1
    {
152
        return $this->reservations->where('email', $email)->notCancelled()->count();
153
    }
154
155
    /**
156 1
     * Is user returning or not? You have to set this parameter at Backend Reservations setting.
157
     *
158 1
     * @param $email
159 1
     *
160 1
     * @return bool
161 1
     */
162
    public function isUserReturning($email)
163 1
    {
164 1
        // if disabled, return always false
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
165
        $threshold = Settings::get('returning_mark', 0);
166
        if ($threshold < 1) {
167
            return false;
168 1
        }
169 1
170
        // load emails count
171 1
        if ($this->returningUsersCache === null) {
172
            $items = $this
173
                ->reservations
174
                ->select(DB::raw('email, count(*) as count'))
175
                ->groupBy('email')
176
                ->get();
177
            // refactor to mapWithKeys after upgrade to Laravel 5.3.
178
            foreach($items as $item) {
179
                $this->returningUsersCache[$item['email']] = $item['count'];
180
            }
181
        }
182
183
        $returning = $this->returningUsersCache;
184
        $actual = isset($returning[$email]) ? $returning[$email] : 0;
185
186
        return $threshold > 0 && $actual >= $threshold;
187
    }
188
189
    /**
190
     * Bulk reservation state change.
191
     *
192
     * @param array $ids
193
     * @param string $ident
194
     */
195
    public function bulkStateChange($ids, $ident)
196
    {
197
        // get state
198
        $status = $this->statuses->where('ident', $ident)->first();
199
        if (!$status) {
200
            return;
201
        }
202
203
        // go through reservations
204
        foreach ($ids as $id)
205
        {
206
            $reservation = $this->reservations->find($id);
207
            if (!$reservation) {
208
                continue;
209
            }
210
211
            $reservation->status = $status;
212
            $reservation->save();
213
        }
214
    }
215
216
    /**
217
     * Bulk reservations delete.
218
     *
219
     * @param array $ids
220
     */
221
    public function bulkDelete($ids)
222
    {
223
        // go through reservations
224
        foreach ($ids as $id)
225
        {
226
            $reservation = $this->reservations->find($id);
227
            if (!$reservation) {
228
                continue;
229 9
            }
230
231
            $reservation->delete();
232 9
        }
233 1
    }
234
235 8
    /**
236 1
     * Transform date and time to DateTime string.
237
     *
238
     * @param $data
239 7
     *
240
     * @return Carbon
241 7
     *
242
     * @throws ApplicationException
243
     */
244
    public function transformDateTime($data)
245
    {
246
        // validate date and time
247
        if (empty($data['date'])) {
248
            throw new ApplicationException('You have to select pickup date!');
249
250
        } elseif (empty($data['time'])) {
251 6
            throw new ApplicationException('You have to select pickup hour!');
252
        }
253
254 6
        $format = Config::get('vojtasvoboda.reservations::config.formats.datetime', 'd/m/Y H:i');
255
256
        return Carbon::createFromFormat($format, trim($data['date'] . ' ' . $data['time']));
257
    }
258
259 6
    /**
260 1
     * Check gived date and time.
261
     *
262 6
     * @param array $data
263
     *
264
     * @throws ApplicationException
265
     */
266
    public function checkDate($data)
267
    {
268
        // check reservation sent limit
269
        if ($this->isSomeReservationExistsInLastTime()) {
270
            throw new ApplicationException('You can sent only one reservation per 30 seconds, please wait a second.');
271 6
        }
272
273
        // check date availability
274 6
        if (!$this->isDateAvailable($data['date'])) {
275
            throw new ApplicationException($data['date']->format('d.m.Y H:i') . ' is already booked.');
276
        }
277 6
    }
278 6
279 6
    /**
280
     * Returns if date is available to book.
281
     *
282 6
     * @param Carbon $date
283 6
     *
284 6
     * @return bool
285
     */
286
    public function isDateAvailable(Carbon $date)
287 6
    {
288
        // get config
289 6
        $length = Config::get('vojtasvoboda.reservations::config.reservation.length', '2 hours');
290
291
        // check time slot before
292
        $startDatetime = clone $date;
293
        $startDatetime->modify('-' . $length);
294
        $startDatetime->modify('+1 second');
295
296
        // check time slot after
297 6
        $endDatetime = clone $date;
298
        $endDatetime->modify('+' . $length);
299 6
        $endDatetime->modify('-1 second');
300
301
        // get all reservations in this date
302
        $reservations = $this->reservations->notCancelled()->whereBetween('date', [$startDatetime, $endDatetime])->get();
303
304
        return $reservations->count() == 0;
305
    }
306
307
    /**
308
     * Try to find some reservation in less then half minute.
309
     *
310
     * @return boolean
311
     */
312
    public function isSomeReservationExistsInLastTime()
313
    {
314
        return $this->reservations->isExistInLastTime();
315
    }
316
}
317