Completed
Push — master ( 4b253c...0bc4e9 )
by Vasyl
01:52
created

SlugGenerator::getSlugSourceString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 0
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Fomvasss\SlugMaker\ServiceTraits;
4
5
use Fomvasss\SlugMaker\InvalidOption;
6
7
trait SlugGenerator
8
{
9
    protected $currentSlugModel;
10
11
    /**
12
     * Get the slug with the model.
13
     */
14
    protected function getSlug()
15
    {
16
        $this->guardAgainstInvalidSlugOptions();
17
18
        $slug = $this->generateNonUniqueSlug();
19
20
        if ($this->slugOptions->generateUniqueSlugs) {
21
            $slug = $this->makeSlugUnique($slug);
22
        }
23
24
        return $slug;
25
    }
26
27
    /**
28
     * Generate a non unique slug for this record.
29
     */
30
    protected function generateNonUniqueSlug(): string
31
    {
32
        $this->slugOptions = $this->getSlugMakerOptions();
0 ignored issues
show
Bug introduced by
The method getSlugMakerOptions() does not exist on Fomvasss\SlugMaker\ServiceTraits\SlugGenerator. Did you maybe mean getSlug()? ( Ignorable by Annotation )

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

32
        /** @scrutinizer ignore-call */ 
33
        $this->slugOptions = $this->getSlugMakerOptions();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug Best Practice introduced by
The property slugOptions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
33
34
        return str_slug($this->getSlugSourceString(), $this->slugOptions->slugSeparator);
35
    }
36
37
    /**
38
     * Get the string that should be used as base for the slug.
39
     */
40
    protected function getSlugSourceString(): string
41
    {
42
        if (is_callable($this->slugOptions->generateSlugFrom)) {
43
            $slugSourceString = call_user_func($this->slugOptions->generateSlugFrom, $this);
44
45
            return $this->getClippedSlugWithPrefixSuffix($slugSourceString);
46
        }
47
48
        $slugSourceString = collect($this->slugOptions->generateSlugFrom)
49
            ->map(function (string $fieldName) : string {
50
                return $this->$fieldName ?? '';
51
            })
52
            ->implode('-');
53
54
        return $this->getClippedSlugWithPrefixSuffix($slugSourceString);
55
    }
56
57
    /**
58
     * Add prefix and suffix to slug. Clipped string.
59
     */
60
    public function getClippedSlugWithPrefixSuffix(string $slugSourceString): string
61
    {
62
        $prefix = $this->slugOptions->slugPrefix;
63
        $suffix = $this->slugOptions->slugSuffix;
64
        $lengthPrefix = strlen($prefix);
65
        $lengthSuffix = strlen($suffix);
66
67
        if ($lengthPrefix + $lengthSuffix) {
68
            $limitWithoutPrefixSuffix = $this->slugOptions->maximumLength - (++$lengthPrefix + ++$lengthSuffix);
69
70
            if ($limitWithoutPrefixSuffix < 1) {
71
                return str_limit($prefix.' '.$suffix, $this->slugOptions->maximumLength);
72
            }
73
74
            return $prefix.' '.str_limit($slugSourceString, $limitWithoutPrefixSuffix, '').' '.$suffix;
75
        }
76
77
        return str_limit($slugSourceString, $this->slugOptions->maximumLength);
78
    }
79
80
    /**
81
     * Make the given slug unique.
82
     */
83
    protected function makeSlugUnique(string $slug): string
84
    {
85
        $originalSlug = $slug;
86
        $i = 1;
87
        while ($this->otherRecordExistsWithSlug($slug) || $slug === '') {
88
            $slug = $originalSlug.'-'.$i++;
89
        }
90
91
        return $slug;
92
    }
93
94
    /**
95
     * Determine if a record exists with the given slug.
96
     */
97
    protected function otherRecordExistsWithSlug(string $slug): bool
98
    {
99
        return (bool) \Fomvasss\SlugMaker\Models\Slug::where('name', $slug)
100
            ->where('id', '<>', optional($this->currentSlugModel)->id)
101
            ->withoutGlobalScopes()
102
            ->first();
103
    }
104
105
    /**
106
     * This function will throw an exception when any of the options is missing or invalid.
107
     */
108
    protected function guardAgainstInvalidSlugOptions()
109
    {
110
        if (! count($this->slugOptions->generateSlugFrom)) {
111
            throw InvalidOption::missingFromField();
112
        }
113
114
        if ($this->slugOptions->maximumLength <= 0) {
115
            throw InvalidOption::invalidMaximumLength();
116
        }
117
    }
118
}
119