1 | <?php |
||
2 | |||
3 | namespace Astrotomic\Stancy\Models; |
||
4 | |||
5 | use Astrotomic\Stancy\Contracts\Page as PageContract; |
||
6 | use Astrotomic\Stancy\Contracts\Routable; |
||
7 | use Exception; |
||
8 | use Illuminate\Contracts\View\Factory as ViewFactoryContract; |
||
9 | use Illuminate\Contracts\View\View; |
||
10 | use Illuminate\Support\Arr; |
||
11 | use Illuminate\Support\Traits\Macroable; |
||
12 | use RuntimeException; |
||
13 | use Spatie\Feed\FeedItem; |
||
14 | use Spatie\Sheets\Facades\Sheets; |
||
15 | use Spatie\Sheets\Sheet; |
||
16 | use Spatie\Sitemap\Tags\Tag; |
||
17 | use Symfony\Component\HttpFoundation\Response; |
||
18 | |||
19 | class Page implements PageContract |
||
20 | { |
||
21 | use Macroable; |
||
22 | |||
23 | /** @var string|null */ |
||
24 | protected $view; |
||
25 | |||
26 | /** @var string|null */ |
||
27 | protected $page; |
||
28 | |||
29 | /** @var PageData|array */ |
||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
30 | protected $data = []; |
||
31 | |||
32 | /** @var ViewFactoryContract */ |
||
33 | protected $viewFactory; |
||
34 | |||
35 | 26 | public function __construct(ViewFactoryContract $viewFactory, array $data = [], ?string $page = null) |
|
0 ignored issues
–
show
|
|||
36 | { |
||
37 | 26 | $this->viewFactory = $viewFactory; |
|
38 | |||
39 | 26 | $this->view($data['_view'] ?? null); |
|
40 | |||
41 | 26 | $page = $page ?? $data['_pageData'] ?? null; |
|
42 | |||
43 | 26 | $data = array_merge($data, $this->getSheetData($data['_sheets'] ?? [])); |
|
44 | |||
45 | 25 | $this->data($data); |
|
46 | 25 | $this->page($page); |
|
47 | 22 | } |
|
48 | |||
49 | 2 | public function __get($name) |
|
0 ignored issues
–
show
|
|||
50 | { |
||
51 | 2 | return data_get($this->data, $name); |
|
52 | } |
||
53 | |||
54 | 25 | public function page(?string $page): PageContract |
|
55 | { |
||
56 | 25 | if (is_string($page)) { |
|
57 | 16 | if (! is_subclass_of($page, PageData::class, true)) { |
|
58 | 2 | throw new Exception(sprintf('The page data class [%s] has to extend %s.', $page, PageData::class)); |
|
59 | } |
||
60 | } |
||
61 | |||
62 | 23 | $this->page = $page; |
|
63 | |||
64 | 23 | $this->parse(); |
|
65 | |||
66 | 22 | return $this; |
|
67 | } |
||
68 | |||
69 | 25 | public function data(array $data): PageContract |
|
0 ignored issues
–
show
|
|||
70 | { |
||
71 | 25 | $this->data = $this->prepareData($data); |
|
72 | |||
73 | 25 | $this->parse(); |
|
74 | |||
75 | 25 | return $this; |
|
76 | } |
||
77 | |||
78 | 26 | public function view(?string $view): PageContract |
|
79 | { |
||
80 | 26 | $this->view = $view; |
|
81 | |||
82 | 26 | return $this; |
|
83 | } |
||
84 | |||
85 | 6 | public function render(): View |
|
86 | { |
||
87 | 6 | if (empty($this->view)) { |
|
88 | 1 | throw new Exception('You have to define a view before the page can render.'); |
|
89 | } |
||
90 | |||
91 | 5 | return $this->viewFactory->make($this->view, $this->toArray()); |
|
92 | } |
||
93 | |||
94 | 3 | public function toHtml(): string |
|
95 | { |
||
96 | 3 | return $this->render()->render(); |
|
0 ignored issues
–
show
|
|||
97 | } |
||
98 | |||
99 | 15 | public function toArray(): array |
|
0 ignored issues
–
show
|
|||
100 | { |
||
101 | 15 | return is_array($this->data) ? $this->data : $this->data->all(); |
|
102 | } |
||
103 | |||
104 | 2 | public function jsonSerialize(): array |
|
0 ignored issues
–
show
|
|||
105 | { |
||
106 | 2 | return is_array($this->data) ? $this->data : $this->data->toArray(); |
|
107 | } |
||
108 | |||
109 | /** {@inheritdoc} */ |
||
110 | 1 | public function toJson($options = 0): string |
|
111 | { |
||
112 | 1 | return json_encode($this->jsonSerialize(), $options); |
|
113 | } |
||
114 | |||
115 | /** {@inheritdoc} */ |
||
116 | 6 | public function toResponse($request): Response |
|
117 | { |
||
118 | 6 | if ($request->wantsJson()) { |
|
119 | 1 | return response()->json($this->jsonSerialize()); |
|
120 | } |
||
121 | |||
122 | 5 | return response($this->render()); |
|
123 | } |
||
124 | |||
125 | 2 | public function toFeedItem(): FeedItem |
|
126 | { |
||
127 | 2 | if (! ($this->data instanceof PageData)) { |
|
128 | 1 | throw new Exception(sprintf('The page data has to extend %s to allow transformation to %s.', PageData::class, FeedItem::class)); |
|
129 | } |
||
130 | |||
131 | 1 | return $this->data->toFeedItem(); |
|
132 | } |
||
133 | |||
134 | 3 | public function toSitemapItem(): Tag |
|
135 | { |
||
136 | 3 | if (! ($this->data instanceof PageData)) { |
|
137 | 1 | throw new Exception(sprintf('The page data has to extend %s to allow transformation to %s.', PageData::class, Tag::class)); |
|
138 | } |
||
139 | |||
140 | 2 | return $this->data->toSitemapItem(); |
|
141 | } |
||
142 | |||
143 | 3 | public function getUrl(): string |
|
144 | { |
||
145 | 3 | if (! ($this->data instanceof Routable)) { |
|
146 | 1 | throw new Exception(sprintf('The page data has to be instance of %s to allow access to the URL.', Routable::class)); |
|
147 | } |
||
148 | |||
149 | 2 | return $this->data->getUrl(); |
|
150 | } |
||
151 | |||
152 | 25 | protected function parse(): void |
|
153 | { |
||
154 | 25 | if ($this->page === null) { |
|
155 | 25 | return; |
|
156 | } |
||
157 | |||
158 | 14 | $this->data = forward_static_call( |
|
159 | 14 | [$this->page, 'make'], |
|
160 | 14 | $this->toArray() |
|
161 | ); |
||
162 | 12 | } |
|
163 | |||
164 | 26 | protected function getSheetData(array $sheets): array |
|
0 ignored issues
–
show
|
|||
165 | { |
||
166 | 26 | if (empty($sheets)) { |
|
167 | 24 | return []; |
|
168 | } |
||
169 | |||
170 | 2 | if (! Arr::isAssoc($sheets)) { |
|
171 | 1 | throw new RuntimeException('The [_sheets] data has to be an associative array.'); |
|
172 | } |
||
173 | |||
174 | 1 | $data = []; |
|
175 | |||
176 | 1 | foreach ($sheets as $key => $sheet) { |
|
177 | 1 | [$collection, $path] = explode(':', $sheet); |
|
178 | |||
179 | 1 | if ($path === '*') { |
|
180 | $data[$key] = Sheets::collection($collection)->all()->map(function (Sheet $sheet) { |
||
181 | 1 | return $this->prepareData($sheet->toArray()); |
|
182 | 1 | })->all(); |
|
183 | |||
184 | 1 | continue; |
|
185 | } |
||
186 | |||
187 | 1 | $data[$key] = $this->prepareData(Sheets::collection($collection)->get($path)->toArray()); |
|
188 | } |
||
189 | |||
190 | 1 | return $data; |
|
191 | } |
||
192 | |||
193 | 25 | protected function prepareData(array $data): array |
|
0 ignored issues
–
show
|
|||
194 | { |
||
195 | 25 | unset($data['_view'], $data['_pageData'], $data['_sheets']); |
|
196 | |||
197 | 25 | return $data; |
|
198 | } |
||
199 | } |
||
200 |