Completed
Push — master ( 2b72b9...3afd02 )
by Vojta
06:42
created

ReservationsFacade   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 277
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 63.75%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 28
c 1
b 0
f 0
lcom 1
cbo 4
dl 0
loc 277
ccs 51
cts 80
cp 0.6375
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A storeReservation() 0 19 1
A getReservations() 0 4 1
A getActiveReservations() 0 4 1
A getReservedDates() 0 6 1
A getReservationsByInterval() 0 4 1
A getReservationsWithSameEmailCount() 0 4 1
B isUserReturning() 0 26 6
A bulkStateChange() 0 20 4
A bulkDelete() 0 13 3
A transformDateTime() 0 14 3
A checkDate() 0 12 3
A isDateAvailable() 0 20 1
A isSomeReservationExistsInLastTime() 0 4 1
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
    /**
40
     * ReservationsFacade constructor.
41
     *
42
     * @param Reservation $reservations
43
     * @param Status $statuses
44
     * @param DatesResolver $resolver
45
     */
46 9
    public function __construct(Reservation $reservations, Status $statuses, DatesResolver $resolver)
47
    {
48 9
        $this->reservations = $reservations;
49 9
        $this->statuses = $statuses;
50 9
        $this->datesResolver = $resolver;
51 9
    }
52
53
    /**
54
     * Create and store reservation.
55
     *
56
     * @param array $data
57
     *
58
     * @return Reservation $reservation
59
     *
60
     * @throws ApplicationException
61
     * @throws ValidationException
62
     */
63 8
    public function storeReservation($data)
64
    {
65
        // transform date and time to Carbon
66 8
        $data['date'] = $this->transformDateTime($data);
67
68
        // check date availability
69 6
        $this->checkDate($data);
70
71
        // create reservation
72 6
        $reservation = $this->reservations->create($data);
73
74
        // send reservation confirmation to customer
75 6
        ReservationMailer::send($reservation);
76
77
        // send reservation confirmation to admin
78 6
        ReservationAdminMailer::send($reservation);
79
80 6
        return $reservation;
81
    }
82
83
    /**
84
     * Get all reservations.
85
     *
86
     * @return Collection
87
     */
88
    public function getReservations()
89
    {
90
        return $this->reservations->all();
91
    }
92
93
    /**
94
     * Get all active (not cancelled) reservations.
95
     *
96
     * @return Collection
97
     */
98
    public function getActiveReservations()
99
    {
100
        return $this->reservations->notCancelled()->get();
101
    }
102
103
    /**
104
     * Get all reserved time slots.
105
     *
106
     * @return array
107
     */
108
    public function getReservedDates()
109
    {
110
        $reservations = $this->getActiveReservations();
111
112
        return $this->datesResolver->getDatesFromReservations($reservations);
113
    }
114
115
    /**
116
     * Get all reservations by given date interval.
117
     *
118
     * @param Carbon $since Date from.
119
     * @param Carbon $till Date to.
120
     *
121
     * @return mixed
122
     */
123
    public function getReservationsByInterval(Carbon $since, Carbon $till)
124
    {
125
        return $this->reservations->whereBetween('date', [$since, $till])->get();
126
    }
127
128
    /**
129
     * Get reservations count by one email.
130
     *
131
     * @param $email
132
     *
133
     * @return int
134
     */
135 1
    public function getReservationsWithSameEmailCount($email)
136
    {
137 1
        return $this->reservations->where('email', $email)->notCancelled()->count();
138
    }
139
140
    /**
141
     * Is user returning or not? You have to set this parameter at Backend Reservations setting.
142
     *
143
     * @param $email
144
     *
145
     * @return bool
146
     */
147 1
    public function isUserReturning($email)
148
    {
149
        // 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...
150 1
        $threshold = Settings::get('returning_mark', 0);
151 1
        if ($threshold < 1) {
152
            return false;
153
        }
154
155
        // load emails count
156 1
        if ($this->returningUsersCache === null) {
157
            $items = $this
158 1
                ->reservations
159 1
                ->select(DB::raw('email, count(*) as count'))
160 1
                ->groupBy('email')
161 1
                ->get();
162
            // refactor to mapWithKeys after upgrade to Laravel 5.3.
163 1
            foreach($items as $item) {
164 1
                $this->returningUsersCache[$item['email']] = $item['count'];
165
            }
166
        }
167
168 1
        $returning = $this->returningUsersCache;
169 1
        $actual = isset($returning[$email]) ? $returning[$email] : 0;
170
171 1
        return $threshold > 0 && $actual >= $threshold;
172
    }
173
174
    /**
175
     * Bulk reservation state change.
176
     *
177
     * @param array $ids
178
     * @param string $ident
179
     */
180
    public function bulkStateChange($ids, $ident)
181
    {
182
        // get state
183
        $status = $this->statuses->where('ident', $ident)->first();
184
        if (!$status) {
185
            return;
186
        }
187
188
        // go through reservations
189
        foreach ($ids as $id)
190
        {
191
            $reservation = $this->reservations->find($id);
192
            if (!$reservation) {
193
                continue;
194
            }
195
196
            $reservation->status = $status;
197
            $reservation->save();
198
        }
199
    }
200
201
    /**
202
     * Bulk reservations delete.
203
     *
204
     * @param array $ids
205
     */
206
    public function bulkDelete($ids)
207
    {
208
        // go through reservations
209
        foreach ($ids as $id)
210
        {
211
            $reservation = $this->reservations->find($id);
212
            if (!$reservation) {
213
                continue;
214
            }
215
216
            $reservation->delete();
217
        }
218
    }
219
220
    /**
221
     * Transform date and time to DateTime string.
222
     *
223
     * @param $data
224
     *
225
     * @return Carbon
226
     *
227
     * @throws ApplicationException
228
     */
229 9
    public function transformDateTime($data)
230
    {
231
        // validate date and time
232 9
        if (empty($data['date'])) {
233 1
            throw new ApplicationException('You have to select pickup date!');
234
235 8
        } elseif (empty($data['time'])) {
236 1
            throw new ApplicationException('You have to select pickup hour!');
237
        }
238
239 7
        $format = Config::get('vojtasvoboda.reservations::config.formats.datetime', 'd/m/Y H:i');
240
241 7
        return Carbon::createFromFormat($format, trim($data['date'] . ' ' . $data['time']));
242
    }
243
244
    /**
245
     * Check gived date and time.
246
     *
247
     * @param array $data
248
     *
249
     * @throws ApplicationException
250
     */
251 6
    public function checkDate($data)
252
    {
253
        // check reservation sent limit
254 6
        if ($this->isSomeReservationExistsInLastTime()) {
255
            throw new ApplicationException('You can sent only one reservation per 30 seconds, please wait a second.');
256
        }
257
258
        // check date availability
259 6
        if (!$this->isDateAvailable($data['date'])) {
260 1
            throw new ApplicationException($data['date']->format('d.m.Y H:i') . ' is already booked.');
261
        }
262 6
    }
263
264
    /**
265
     * Returns if date is available to book.
266
     *
267
     * @param Carbon $date
268
     *
269
     * @return bool
270
     */
271 6
    public function isDateAvailable(Carbon $date)
272
    {
273
        // get config
274 6
        $length = Config::get('vojtasvoboda.reservations::config.reservation.length', '2 hours');
275
276
        // check time slot before
277 6
        $startDatetime = clone $date;
278 6
        $startDatetime->modify('-' . $length);
279 6
        $startDatetime->modify('+1 second');
280
281
        // check time slot after
282 6
        $endDatetime = clone $date;
283 6
        $endDatetime->modify('+' . $length);
284 6
        $endDatetime->modify('-1 second');
285
286
        // get all reservations in this date
287 6
        $reservations = $this->reservations->notCancelled()->whereBetween('date', [$startDatetime, $endDatetime])->get();
288
289 6
        return $reservations->count() == 0;
290
    }
291
292
    /**
293
     * Try to find some reservation in less then half minute.
294
     *
295
     * @return boolean
296
     */
297 6
    public function isSomeReservationExistsInLastTime()
298
    {
299 6
        return $this->reservations->isExistInLastTime();
300
    }
301
}
302