CheckOutController   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 73
c 3
b 0
f 0
dl 0
loc 127
rs 10
wmc 17

2 Methods

Rating   Name   Duplication   Size   Complexity  
A getOverview() 0 11 2
C startPayment() 0 110 15
1
<?php
2
3
namespace App\Http\Controllers\TicketShop;
4
5
use Illuminate\Support\Facades\DB;
6
use Illuminate\Database\Eloquent\ModelNotFoundException;
7
use App\Http\Requests\PayTickets;
8
use App\Http\Controllers\Controller;
9
use App\Purchase;
10
use App\Role;
11
use App\User;
12
use App\Ticket;
13
use Illuminate\Support\Str;
14
15
class CheckOutController extends Controller
16
{
17
18
    public function getOverview()
19
    {
20
        // Only allow requests for sessions with existing customer data
21
        if (!session()->has('customerData')) {
22
            return redirect()->route('ts.customerData');
23
        }
24
25
        return view('ticketshop.purchase-overview', [
26
            'event' => session('event'),
27
            'tickets' => session('tickets'),
28
            'customerData' => session('customerData'),
29
        ]);
30
    }
31
32
    public function startPayment(PayTickets $request)
33
    {
34
        // Only allow requests for sessions with existing customer data
35
        if (!session()->has('customerData')) {
36
            return redirect()->route('ts.customerData');
37
        }
38
        $cData = session('customerData');
39
40
        // Start a transaction for inserting all session data into database
41
        // and generating a purchase.
42
        // Checks at the end validate if tickets are still free/available
43
        DB::beginTransaction();
44
45
        // Retrieve selected event and refresh it by loading all related data
46
        // from database
47
        $event = session('event');
48
        $event->refresh();
49
50
        $tickets = session('tickets');
51
        $ticketSum = array_sum($tickets);
52
        if ($event->freeTickets() < $ticketSum) {
53
            // End transaction
54
            DB::rollback();
55
            // Empty session data so user must select new tickets
56
            $request->session()->forget('tickets');
57
            // Redirect user to select a valid amount of tickets
58
            return redirect()->route('ts.seatmap')
59
                ->with('status', 'There are not as many tickets as you chose left. Please only choose a lesser amount of tickets!');
60
        }
61
62
        if ($event->seatMap->layout !== null) {
63
            // Check if seats are still free and not booked by a concurrent transaction in the meantime
64
            $seats = session('seats');
65
            if (!$event->areSeatsFree($seats)) {
66
                // End transaction
67
                DB::rollback();
68
                // Empty session data in order to select new seats
69
                $request->session()->forget('seats');
70
                // redirect user to select a new set of seats
71
                return redirect()->route('ts.seatmap')
72
                    ->with('status', 'Not all of your selected seats are still free. Please choose a new set of seats!');
73
            }
74
        }
75
76
        try {
77
            $customer = User::where('email', $cData['email'])->firstOrFail();
78
        } catch (ModelNotFoundException $e) {
79
            $customer = User::create([
80
                'name' => $cData['name'],
81
                'email' => $cData['email'],
82
                'password' => '',
83
            ]);
84
85
            if (array_key_exists('newsletter', $cData) && $cData['newsletter'] == 'true') {
0 ignored issues
show
Bug introduced by
It seems like $cData can also be of type Illuminate\Session\SessionManager and Illuminate\Session\Store; however, parameter $array of array_key_exists() does only seem to accept ArrayObject|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

85
            if (array_key_exists('newsletter', /** @scrutinizer ignore-type */ $cData) && $cData['newsletter'] == 'true') {
Loading history...
86
                $customer->roles()->attach(Role::where('name', 'NewsletterReceiver')->first());
87
            }
88
        }
89
90
        $prices = $event->priceList->categories;
91
        $prices = $prices->keyBy('id');
92
93
        $purchase = new Purchase();
94
        $purchase->generateSecrets();
95
        $purchase->customer_id = $customer->id;
96
        // If someone already has bought tickets with the same email address
97
        // but with a different name, we store the custom name to the purchase.
98
        if ($cData['name'] != $customer->name) {
99
            $purchase->customer_name = $cData['name'];
100
        }
101
        $purchase->vendor_id = User::where('name', $request->validated()['paymethod'])->first()->id;
102
        $purchase->save();
103
104
105
        $seatsIndex = 0;
106
        foreach ($tickets as $ticketCategory => $ticketCount) {
107
            for ($i = 0; $i < $ticketCount; $i++) {
108
                Ticket::create([
109
                    'random_id' => Str::random(32),
110
                    'seat_number' => isset($seats) ? $seats[$seatsIndex] : 0,
111
                    'purchase_id' => $purchase->id,
112
                    'event_id' => $event->id,
113
                    'price_category_id' => $prices[$ticketCategory]->id
114
                ]);
115
                $seatsIndex++;
116
            }
117
        }
118
119
        switch($request->validated()['paymethod'])
120
        {
121
            case 'Klarna':
122
                $paymentProvider = resolve('App\PaymentProvider\Klarna');
123
                break;
124
            case 'PayPal':
125
                $paymentProvider = resolve('App\PaymentProvider\PayPal');
126
                break;
127
            case 'Mollie':
128
                $paymentProvider = resolve('App\PaymentProvider\Mollie');
129
                break;
130
            default:
131
                DB::rollBack();
132
                return redirect()->route('ts.overview')
133
                    ->with('status', 'The selected PaymentProvider is not supported!');
134
        }
135
136
        DB::commit();
137
        // forget all session data that has been written into database
138
        $request->session()->forget(['customerData', 'event', 'tickets', 'seats']);
139
140
        return redirect()->away(
141
            $paymentProvider->getPaymentUrl($purchase)
142
        );
143
    }
144
}
145