• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

conedevelopment / root / 18110914680

29 Sep 2025 09:13PM UTC coverage: 77.523%. Remained the same
18110914680

push

github

iamgergo
wip

0 of 4 new or added lines in 1 file covered. (0.0%)

3342 of 4311 relevant lines covered (77.52%)

35.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.15
/src/Fields/Media.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Cone\Root\Fields;
6

7
use Cone\Root\Filters\MediaSearch;
8
use Cone\Root\Filters\RenderableFilter;
9
use Cone\Root\Http\Controllers\MediaController;
10
use Cone\Root\Models\Medium;
11
use Cone\Root\Traits\HasMedia;
12
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
13
use Illuminate\Database\Eloquent\Model;
14
use Illuminate\Http\Request;
15
use Illuminate\Http\UploadedFile;
16
use Illuminate\Routing\Router;
17
use Illuminate\Support\Facades\Config;
18
use Illuminate\Support\Facades\Storage;
19
use Illuminate\Support\Facades\View;
20
use Illuminate\Support\Str;
21
use Illuminate\Validation\Rule;
22

23
class Media extends File
24
{
25
    /**
26
     * Indicates if the component is multiple.
27
     */
28
    protected bool $multiple = true;
29

30
    /**
31
     * The Blade template.
32
     */
33
    protected string $template = 'root::fields.media';
34

35
    /**
36
     * Get the route parameter name.
37
     */
38
    public function getRouteParameterName(): string
3✔
39
    {
40
        return 'field';
3✔
41
    }
42

43
    /**
44
     * Get the modal key.
45
     */
46
    public function getModalKey(): string
2✔
47
    {
48
        return sprintf('media-field-%s', $this->getModelAttribute());
2✔
49
    }
50

51
    /**
52
     * Set the multiple attribute.
53
     */
54
    public function multiple(bool $value = true): static
197✔
55
    {
56
        $this->multiple = $value;
197✔
57

58
        return $this;
197✔
59
    }
60

61
    /**
62
     * Get the model.
63
     */
64
    public function getModel(): Model
×
65
    {
66
        return $this->model ?: new class extends Model
×
67
        {
×
68
            use HasMedia;
69
        };
×
70
    }
71

72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function fields(Request $request): array
197✔
76
    {
77
        return [];
197✔
78
    }
79

80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function filters(Request $request): array
3✔
84
    {
85
        return [
3✔
86
            new MediaSearch,
3✔
87
        ];
3✔
88
    }
89

90
    /**
91
     * Paginate the relatable models.
92
     */
93
    public function paginateRelatable(Request $request, Model $model): LengthAwarePaginator
1✔
94
    {
95
        return $this->resolveFilters($request)
1✔
96
            ->apply($request, $this->resolveRelatableQuery($request, $model))
1✔
97
            ->paginate($request->input('per_page'))
1✔
98
            ->withQueryString()
1✔
99
            ->through(function (Medium $related) use ($request, $model): array {
1✔
100
                $option = $this->toOption($request, $model, $related);
×
101

102
                return array_merge($option, [
×
103
                    'html' => View::make('root::fields.file-option', $option)->render(),
×
104
                ]);
×
105
            });
1✔
106
    }
107

108
    /**
109
     * {@inheritdoc}
110
     */
111
    public function persist(Request $request, Model $model, mixed $value): void
3✔
112
    {
113
        $model->saved(function (Model $model) use ($request, $value): void {
3✔
114
            $this->resolveHydrate($request, $model, $value);
3✔
115

116
            $keys = $this->getRelation($model)->sync($value);
3✔
117

118
            if ($this->prunable && ! empty($keys['detached'])) {
3✔
119
                $this->prune($request, $model, $keys['detached']);
×
120
            }
121
        });
3✔
122
    }
123

124
    /**
125
     * Handle the file upload.
126
     */
127
    public function upload(Request $request, Model $model): array
1✔
128
    {
129
        $accept = $this->getAttribute('accept');
1✔
130

131
        $data = $request->validate(['file' => [
1✔
132
            'required',
1✔
133
            'file',
1✔
134
            Rule::when(! is_null($accept), ['mimetypes:'.$accept]),
1✔
135
        ]]);
1✔
136

137
        return $this->store($request, $model, $data['file']);
1✔
138
    }
139

140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function store(Request $request, Model $model, UploadedFile $file): array
1✔
144
    {
145
        $disk = Storage::build([
1✔
146
            'driver' => 'local',
1✔
147
            'root' => Config::get('root.media.tmp_dir'),
1✔
148
        ]);
1✔
149

150
        $disk->append($file->getClientOriginalName(), $file->get());
1✔
151

152
        if ($request->header('X-Chunk-Index') !== $request->header('X-Chunk-Total')) {
1✔
NEW
153
            return array_merge(
×
NEW
154
                $this->toOption($request, $model, new Medium(['mime_type' => '', 'file_name' => $file->getBasename()])),
×
NEW
155
                ['processing' => true, 'fileName' => null, 'uuid' => Str::uuid()]
×
NEW
156
            );
×
157
        }
158

159
        return $this->stored($request, $model, $disk->path($file->getClientOriginalName()));
1✔
160
    }
161

162
    /**
163
     * The routes that should be registered.
164
     */
165
    public function routes(Router $router): void
197✔
166
    {
167
        $router->match(['GET', 'POST', 'DELETE'], '/', MediaController::class);
197✔
168
    }
169

170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function toInput(Request $request, Model $model): array
2✔
174
    {
175
        $data = parent::toInput($request, $model);
2✔
176

177
        $filters = $this->resolveFilters($request)->authorized($request);
2✔
178

179
        return array_merge($data, [
2✔
180
            'modalKey' => $this->getModalKey(),
2✔
181
            'config' => [
2✔
182
                'accept' => $this->getAttribute('accept', '*'),
2✔
183
                'multiple' => $this->multiple,
2✔
184
                'chunk_size' => Config::get('root.media.chunk_size'),
2✔
185
                'query' => $filters->mapToData($request),
2✔
186
            ],
2✔
187
            'selection' => array_map(static fn (array $option): array => array_merge($option, [
2✔
188
                'html' => View::make('root::fields.file-option', $option)->render(),
2✔
189
            ]), $data['options'] ?? []),
2✔
190
            'url' => $this->modelUrl($model),
2✔
191
            'filters' => $filters->renderable()
2✔
192
                ->map(fn (RenderableFilter $filter): array => $filter->toField()
2✔
193
                    ->removeAttribute('name')
2✔
194
                    ->setAttributes([
2✔
195
                        'x-model.debounce.300ms' => $filter->getKey(),
2✔
196
                        'x-bind:readonly' => 'processing',
2✔
197
                    ])
2✔
198
                    ->toInput($request, $this->getRelation($model)->make()))
2✔
199
                ->all(),
2✔
200
        ]);
2✔
201
    }
202
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc