Passed
Push — next ( 230762...ff9bff )
by Bas
08:27
created

Builder::firstOrCreate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.1481

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 9
ccs 2
cts 3
cp 0.6667
rs 10
cc 2
nc 2
nop 2
crap 2.1481
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Eloquent;
4
5
use Illuminate\Database\Eloquent\Builder as IlluminateBuilder;
6
use Illuminate\Support\Arr;
7
use LaravelFreelancerNL\Aranguent\Eloquent\Concerns\QueriesAranguentRelationships;
8
9
class Builder extends IlluminateBuilder
10
{
11
    use QueriesAranguentRelationships;
0 ignored issues
show
introduced by
The trait LaravelFreelancerNL\Aran...sAranguentRelationships requires some properties which are not provided by LaravelFreelancerNL\Aranguent\Eloquent\Builder: $grammar, $aqb, $from
Loading history...
12
13
    /**
14
     * The methods that should be returned from query builder.
15
     *
16
     * @var array
17
     */
18
    protected $passthru = [
19
        'insert', 'insertOrIgnore', 'insertGetId', 'insertUsing', 'getBindings', 'toSql', 'dump', 'dd',
20
        'exists', 'doesntExist', 'count', 'min', 'max', 'avg', 'average', 'sum', 'getConnection',
21
    ];
22
23
    /**
24
     * Get the first record matching the attributes or create it.
25
     *
26
     * @param  array  $attributes
27
     * @param  array  $values
28
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Builder
29
     */
30 103
    public function firstOrCreate(array $attributes = [], array $values = [])
31
    {
32
        $instance = $this->where(associativeFlatten($attributes))->first();
33
        if (! is_null($instance)) {
34
            return $instance;
35 103
        }
36
37
        return tap($this->newModelInstance(array_merge($attributes, $values)), function ($instance) {
38
            $instance->save();
39 103
        });
40 79
    }
41
42 103
    /**
43
     * Get the first record matching the attributes or instantiate it.
44
     *
45
     * @param  array  $attributes
46 103
     * @param  array  $values
47 103
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Builder
48
     */
49 103
    public function firstOrNew(array $attributes = [], array $values = [])
50
    {
51
        $instance = $this->where(associativeFlatten($attributes))->first();
52
        if (! is_null($instance)) {
53
            return $instance;
54 103
        }
55 103
56
        return $this->newModelInstance(array_merge($attributes, $values));
57
    }
58 103
59
    /**
60
     * Insert a record in the database.
61
     *
62
     * @param array $values
63
     *
64
     * @return int
65
     */
66
    public function insert(array $values)
67
    {
68 103
        // Since every insert gets treated like a batch insert, we will make sure the
69
        // bindings are structured in a way that is convenient when building these
70
        // inserts statements by verifying these elements are actually an array.
71 103
        if (empty($values)) {
72 103
            return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type integer.
Loading history...
73 103
        }
74
75
        if (Arr::isAssoc($values)) {
76
            $values = [$values];
77
        }
78 103
        if (! Arr::isAssoc($values)) {
79 103
            // Here, we will sort the insert keys for every record so that each insert is
80
            // in the same order for the record. We need to make sure this is the case
81 103
            // so there are not any errors or problems when inserting these records.
82 103
            foreach ($values as $key => $value) {
83
                ksort($value);
84 103
85 103
                $values[$key] = $value;
86 103
            }
87
        }
88
89 103
        //Set timestamps
90 103
        foreach ($values as $key => $value) {
91
            $values[$key] = $this->updateTimestamps($value);
92
        }
93 103
94
        return $this->toBase()->insert($values);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->toBase()->insert($values) returns the type boolean which is incompatible with the documented return type integer.
Loading history...
95
    }
96
97
    /**
98
     * Add the "updated at" column to an array of values.
99
     *
100
     * @param array $values
101
     *
102
     * @return array
103 18
     */
104
    protected function updateTimestamps(array $values)
105
    {
106 18
        if (
107 18
            !$this->model->usesTimestamps() ||
108
            is_null($this->model->getUpdatedAtColumn()) ||
109
            is_null($this->model->getCreatedAtColumn())
110
        ) {
111
            return $values;
112 18
        }
113
114 18
        $timestamp = $this->model->freshTimestampString();
115 18
        $updatedAtColumn = $this->model->getUpdatedAtColumn();
116
117
        $timestamps = [];
118
        $timestamps[$updatedAtColumn] = $timestamp;
119 18
120
        $createdAtColumn = $this->model->getCreatedAtColumn();
121
        if (!isset($values[$createdAtColumn]) && !isset($this->model->$createdAtColumn)) {
122
            $timestamps[$createdAtColumn] = $timestamp;
123
        }
124
125
        $values = array_merge(
126
            $timestamps,
127
            $values
128
        );
129
        return $values;
130
    }
131
132
133
    /**
134
     * Add the "updated at" column to an array of values.
135
     *
136
     * @param  array  $values
137
     * @return array
138
     */
139
    protected function addUpdatedAtColumn(array $values): array
140
    {
141
        if (
142
            ! $this->model->usesTimestamps() ||
143
            is_null($this->model->getUpdatedAtColumn())
144
        ) {
145
            return $values;
146
        }
147
148
        $column = $this->model->getUpdatedAtColumn();
149
150
        $values = array_merge(
151
            [$column => $this->model->freshTimestampString()],
152
            $values
153
        );
154
155
        return $values;
156
    }
157
}
158