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