Passed
Push — master ( 00b5d2...444819 )
by Vasyl
01:28
created

EUSGenerator::where()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: fomvasss
5
 * Date: 23.10.18
6
 * Time: 21:25
7
 */
8
9
namespace Fomvasss\LaravelEUS;
10
11
use Illuminate\Database\Eloquent\Model;
12
use Fomvasss\LaravelEUS\Contracts\EUSGenerator as EUSGeneratorContract;
13
14
class EUSGenerator implements \Fomvasss\LaravelEUS\Contracts\EUSGenerator
15
{
16
    const CONFIG_FILE_NAME = 'eus';
17
18
    protected $app;
19
    
20
    protected $config = [];
21
22
    protected $entity;
23
24
    protected $where = [];
25
26
    protected $rawStr = '';
27
28
    /**
29
     * EUSGenerator constructor.
30
     *
31
     * @param $app
32
     */
33
    public function __construct($app = null)
34
    {
35
        if (! $app) {
36
            $app = app();   //Fallback when $app is not given
0 ignored issues
show
Bug introduced by
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

36
            $app = /** @scrutinizer ignore-call */ app();   //Fallback when $app is not given
Loading history...
37
        }
38
        $this->app = $app;
39
40
        $this->config = $this->app['config']->get(self::CONFIG_FILE_NAME);
41
    }
42
43
    /**
44
     * Generate and save unique string value in specified field.
45
     *
46
     * @return mixed
47
     * @throws \Exception
48
     */
49
    public function save()
50
    {
51
        $str = $this->get();
52
53
        $this->entity->{$this->config['field_name_for_unique_str']} = $str;
54
55
        return $this->entity->save();
56
    }
57
58
    /**
59
     * Generate unique string value.
60
     *
61
     * @return string
62
     * @throws \Exception
63
     */
64
    public function get()
65
    {
66
        $nonUniqueStr = $this->makeNonUniqueStr($this->rawStr);
67
68
        return $this->makeUniqueStr($nonUniqueStr);
69
    }
70
71
    /**
72
     * @param array $params
73
     * @return $this
74
     */
75
    public function where(array $params): self
76
    {
77
        $this->where[] = $params;
78
79
        return $this;
80
    }
81
82
    /**
83
     * @param string|null $rawStr
84
     * @return \Fomvasss\LaravelEUS\EUSGenerator
85
     */
86
    public function setRawStr(string $rawStr = null): self
87
    {
88
        $this->rawStr = $rawStr;
89
        
90
        return $this;
91
    }
92
93
    /**
94
     * @param Model $entity
95
     * @return EUSGenerator
96
     */
97
    public function setEntity(Model $entity): self
98
    {
99
        $this->entity = $entity;
100
        
101
        return $this;
102
    }
103
104
    /**
105
     * @param string $fieldNameForUniqueStr
106
     * @return EUSGenerator
107
     */
108
    public function setFieldName(string $fieldNameForUniqueStr): self
109
    {
110
        $this->config['field_name_for_unique_str'] = $fieldNameForUniqueStr;
111
112
        return $this;
113
    }
114
115
    /**
116
     * @param string $modelPrimaryKey
117
     * @return \Fomvasss\LaravelEUS\EUSGenerator
118
     */
119
    public function setModelPrimaryKey(string $modelPrimaryKey): self
120
    {
121
        $this->config['model_primary_key'] = $modelPrimaryKey;
122
123
        return $this;
124
    }
125
126
    /**
127
     * @param string $separator
128
     * @return \Fomvasss\LaravelEUS\EUSGenerator
129
     */
130
    public function setSlugSeparator(string $separator): self
131
    {
132
        $this->config['str_slug_separator'] = $separator;
133
134
        return $this;
135
    }
136
137
    /**
138
     * @param string $separator
139
     * @return EUSGenerator
140
     */
141
    public function setAllowedSeparator(string $separator): self
142
    {
143
        $this->config['str_allowed_separator'] = $separator;
144
145
        return $this;
146
    }
147
148
    /**
149
     * @param string $rawStr
150
     * @return string
151
     */
152
    protected function makeNonUniqueStr(string $rawStr): string
153
    {
154
        if ($str_allowed_separator = $this->config['str_allowed_separator']) {
155
            $res = array_map(function ($str) {
156
157
                return str_slug($this->getClippedSlugWithPrefixSuffix($str), $this->config['str_slug_separator']);
158
159
            }, explode($str_allowed_separator, $rawStr));
160
161
            return implode($str_allowed_separator, $res);
162
        }
163
164
        return str_slug($this->getClippedSlugWithPrefixSuffix($rawStr), $this->config['str_slug_separator']);
165
    }
166
167
    /**
168
     * @param string $str
169
     * @return string
170
     */
171
    protected function getClippedSlugWithPrefixSuffix(string $str): string
172
    {
173
        $prefix = $this->config['prefix'];
174
        $suffix = $this->config['suffix'];
175
        $maximumLength= $this->config['max_length'];
176
        
177
        if ($strLen = strlen($prefix) + strlen($suffix)) {
178
            $limitWithoutPrefixSuffix = $maximumLength - ($strLen + 2);
179
180
            if ($limitWithoutPrefixSuffix < 1) {
181
                return str_limit($prefix . ' ' . $suffix, $maximumLength);
182
            }
183
            
184
            return $prefix.' '.str_limit($str, $limitWithoutPrefixSuffix, '').' '.$suffix;
185
        }
186
        
187
        return str_limit($str, $maximumLength, '');
188
    }
189
190
    /**
191
     * @param string $str
192
     * @return string
193
     * @throws \Exception
194
     */
195
    protected function makeUniqueStr(string $str): string
196
    {
197
        $notUniqueStr = $str;
198
        $i = 1;
199
        
200
        while ($this->isOtherRecordExists($str) || $str === '') {
201
            $str = $notUniqueStr . $this->config['str_slug_separator'] . $i++;
202
        }
203
        
204
        return $str;
205
    }
206
207
    /**
208
     * @param string $str
209
     * @return bool
210
     * @throws \Exception
211
     */
212
    protected function isOtherRecordExists(string $str): bool
213
    {
214
        $modelClass = $this->app->make(get_class($this->entity));
215
        $primaryKey = $this->config['model_primary_key'];
216
        $fieldNameForUnique = $this->config['field_name_for_unique_str'];
217
218
        return (bool) $modelClass::withoutGlobalScopes()
219
            ->where($primaryKey, '<>', optional($this->entity)->{$primaryKey}) // except check self entity
220
            ->where($fieldNameForUnique, $str)
221
            ->when($this->where, function ($q) {
222
                $q->where($this->where);
223
            })->first();
224
    }
225
}