Passed
Push — next ( 480502...54a2e9 )
by Bas
12:53
created

Builder::firstOrCreate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 10
cc 2
nc 2
nop 2
crap 2
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 4
    public function firstOrCreate(array $attributes = [], array $values = [])
31
    {
32 4
        $instance = $this->where(associativeFlatten($attributes))->first();
33 4
        if (! is_null($instance)) {
34 2
            return $instance;
35
        }
36
37 2
        return tap($this->newModelInstance(array_merge($attributes, $values)), function ($instance) {
38 2
            $instance->save();
39 2
        });
40
    }
41
42
    /**
43
     * Get the first record matching the attributes or instantiate it.
44
     *
45
     * @param  array  $attributes
46
     * @param  array  $values
47
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Builder
48
     */
49 3
    public function firstOrNew(array $attributes = [], array $values = [])
50
    {
51 3
        $instance = $this->where(associativeFlatten($attributes))->first();
52 3
        if (! is_null($instance)) {
53 2
            return $instance;
54
        }
55
56 1
        return $this->newModelInstance(array_merge($attributes, $values));
57
    }
58
59
    /**
60
     * Insert a record in the database.
61
     *
62
     * @param array $values
63
     *
64
     * @return int
65
     */
66 39
    public function insert(array $values)
67
    {
68
        // 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 39
        if (empty($values)) {
72
            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
        }
74
75 39
        if (Arr::isAssoc($values)) {
76 11
            $values = [$values];
77
        }
78 39
        if (! Arr::isAssoc($values)) {
79
            // 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
            // so there are not any errors or problems when inserting these records.
82 39
            foreach ($values as $key => $value) {
83 39
                ksort($value);
84
85 39
                $values[$key] = $value;
86
            }
87
        }
88
89
        //Set timestamps
90 39
        foreach ($values as $key => $value) {
91 39
            $values[$key] = $this->updateTimestamps($value);
92
        }
93
94 39
        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
     */
104 39
    protected function updateTimestamps(array $values)
105
    {
106
        if (
107 39
            !$this->model->usesTimestamps() ||
108 39
            is_null($this->model->getUpdatedAtColumn()) ||
109 39
            is_null($this->model->getCreatedAtColumn())
110
        ) {
111
            return $values;
112
        }
113
114 39
        $timestamp = $this->model->freshTimestampString();
115 39
        $updatedAtColumn = $this->model->getUpdatedAtColumn();
116
117 39
        $timestamps = [];
118 39
        $timestamps[$updatedAtColumn] = $timestamp;
119
120 39
        $createdAtColumn = $this->model->getCreatedAtColumn();
121 39
        if (!isset($values[$createdAtColumn]) && !isset($this->model->$createdAtColumn)) {
122 39
            $timestamps[$createdAtColumn] = $timestamp;
123
        }
124
125 39
        $values = array_merge(
126 39
            $timestamps,
127
            $values
128
        );
129 39
        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 22
    protected function addUpdatedAtColumn(array $values): array
140
    {
141
        if (
142 22
            ! $this->model->usesTimestamps() ||
143 22
            is_null($this->model->getUpdatedAtColumn())
144
        ) {
145
            return $values;
146
        }
147
148 22
        $column = $this->model->getUpdatedAtColumn();
149
150 22
        $values = array_merge(
151 22
            [$column => $this->model->freshTimestampString()],
152
            $values
153
        );
154
155 22
        return $values;
156
    }
157
}
158