Test Failed
Push — ft/fields-refactor ( 9f047d...e6f9ef )
by Ben
315:03 queued 288:46
created

UrlRecord::exists()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 12
c 1
b 1
f 0
dl 0
loc 22
rs 9.8666
cc 4
nc 8
nop 4
1
<?php
2
3
namespace Thinktomorrow\Chief\Urls;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Support\Collection;
7
use Thinktomorrow\Chief\Concerns\Morphable\Morphables;
8
use Thinktomorrow\Chief\FlatReferences\FlatReferencePresenter;
9
10
class UrlRecord extends Model
11
{
12
    public $table = 'chief_urls';
13
14
    public $guarded = [];
15
16
    /**
17
     * Find matching url record for passed slug and locale. The locale parameter will try
18
     * to match specific given locales first and records without locale as fallback.
19
     *
20
     * @param string $slug
21
     * @param string $locale
22
     * @return UrlRecord
23
     * @throws UrlRecordNotFound
24
     */
25
    public static function findBySlug(string $slug, string $locale): UrlRecord
26
    {
27
        // Clear the input from any trailing slashes.
28
        if ($slug != '/') {
29
            $slug = trim($slug, '/');
30
        }
31
32
        $record = static::where('slug', $slug)
33
                        ->where('locale', $locale)
34
                        ->orderBy('redirect_id', 'ASC')
35
                        ->first();
36
37
        if (!$record) {
38
            throw new UrlRecordNotFound('No url record found by slug ['.$slug.'] for locale ['.$locale.'].');
39
        }
40
41
        return $record;
42
    }
43
44
    /**
45
     * Find matching url record for passed slug and locale. The locale parameter will try
46
     * to match specific given locales first and records without locale as fallback.
47
     *
48
     * @param Model $model
49
     * @param string $locale
50
     * @return UrlRecord
51
     * @throws UrlRecordNotFound
52
     */
53
    public static function findByModel(Model $model, string $locale): UrlRecord
54
    {
55
        $record = static::where('model_type', $model->getMorphClass())
56
            ->where('model_id', $model->id)
57
            ->where('locale', $locale)
58
            ->orderBy('redirect_id', 'ASC')
59
            ->first();
60
61
        if (!$record) {
62
            throw new UrlRecordNotFound('No url record found for model ['.$model->getMorphClass().'@'.$model->id.'] for locale ['.$locale.'].');
63
        }
64
65
        return $record;
66
    }
67
68
    public static function getByModel(Model $model)
69
    {
70
        return static::where('model_type', $model->getMorphClass())
71
                     ->where('model_id', $model->id)
72
                     ->get();
73
    }
74
75
    public function replaceAndRedirect(array $values): UrlRecord
76
    {
77
        $newRecord = static::create(array_merge([
78
            'locale'              => $this->locale,
79
            'model_type'          => $this->model_type,
80
            'model_id'            => $this->model_id,
81
        ], $values));
82
83
        $this->redirectTo($newRecord);
84
85
        return $newRecord;
86
    }
87
88
    public function redirectTo(self $record = null): ?UrlRecord
89
    {
90
        if (!$record) {
91
            return $this->isRedirect() ? static::find($this->redirect_id) : null;
92
        }
93
94
        $this->redirect_id = $record->id;
95
        $this->save();
96
97
        return null;
98
    }
99
100
    public function isRedirect(): bool
101
    {
102
        return !!($this->redirect_id);
103
    }
104
105
    public static function existsIgnoringRedirects($slug, string $locale = null, Model $ignoredModel = null): bool
106
    {
107
        return static::exists($slug, $locale, $ignoredModel, false);
108
    }
109
110
    public static function exists($slug, string $locale = null, Model $ignoredModel = null, bool $includeRedirects = true): bool
111
    {
112
        $builder = static::where('slug', $slug);
113
114
        if ($locale) {
115
            $builder->where('locale', $locale);
116
        }
117
118
        if (! $includeRedirects) {
119
            $builder->whereNull('redirect_id');
120
        }
121
122
        if ($ignoredModel) {
123
            $builder->whereNotIn('id', function ($query) use ($ignoredModel) {
124
                $query->select('id')
125
                      ->from('chief_urls')
126
                      ->where('model_type', '=', $ignoredModel->getMorphClass())
127
                      ->where('model_id', '=', $ignoredModel->id);
128
            });
129
        }
130
131
        return ($builder->count() > 0);
132
    }
133
134
    public static function allOnlineModels(): array
135
    {
136
        return chiefMemoize('all-online-models', function () {
137
138
            $liveUrlRecords = static::whereNull('redirect_id')->select('model_type', 'model_id')->groupBy('model_type', 'model_id')->get()->mapToGroups(function($record) {
139
                return [$record->model_type => $record->model_id];
140
            });
141
142
            // Get model for each of these records...
143
            $models = $liveUrlRecords->map(function($record, $key){
144
                return Morphables::instance($key)->find($record->toArray());
145
            })->each->reject(function ($model) {
146
                // Invalid references to archived or removed models where url record still exists.
147
                return is_null($model);
148
            })->flatten();
149
150
            return FlatReferencePresenter::toGroupedSelectValues($models)->toArray();
151
        });
152
    }
153
}
154