PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.2.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.2.0
6.2.0 6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / app / Services / PageService.php
kirki / app / Services Last commit date
AppsService.php 2 weeks ago CollaborationCommentService.php 1 month ago CollaborationService.php 5 days ago CollectionItemService.php 1 month ago CollectionService.php 5 days ago ContentManagerTemplateBinder.php 5 days ago ContentManagerTemplateService.php 5 days ago EditorService.php 1 month ago FontService.php 2 weeks ago FormSubmissionService.php 5 days ago GlobalDataService.php 2 weeks ago MediaService.php 1 month ago PageService.php 5 days ago PageSettingsService.php 1 month ago PostService.php 5 days ago UtilityPageService.php 5 days ago
PageService.php
352 lines
1 <?php
2
3 namespace Kirki\App\Services;
4
5 defined('ABSPATH') || exit;
6
7 use Exception;
8 use Kirki\App\Constants\PageContentTypes;
9 use Kirki\App\Constants\PageMetaKeys;
10 use Kirki\App\Constants\PostTypes;
11 use Kirki\App\DTO\Page\EditorPagePayloadDTO;
12 use Kirki\App\DTO\Page\EditPageDTO;
13 use Kirki\App\DTO\Page\EditPopupDTO;
14 use Kirki\App\DTO\Page\PageFilterDTO;
15 use Kirki\App\DTO\Page\PagePayloadDTO;
16 use Kirki\App\DTO\Page\TogglePageSymbolDTO;
17 use Kirki\App\Models\Page as PageModel;
18 use Kirki\App\Models\PostMeta;
19 use Kirki\App\Supports\Canvas;
20 use Kirki\App\Supports\Facades\GlobalData;
21 use Kirki\App\Supports\Facades\Page;
22 use Kirki\App\Supports\Template;
23 use Kirki\Framework\Database\Query\Paginator;
24 use Kirki\Framework\Database\Query\QueryBuilder;
25 use Kirki\Framework\Http\Response;
26
27 use function Kirki\App\soft_flush_rewrite_rules;
28 use function Kirki\Framework\collection;
29
30 class PageService
31 {
32 /**
33 * Create a new page.
34 *
35 * @param PagePayloadDTO $payload
36 *
37 * @return PageModel
38 */
39 public function save(PagePayloadDTO $payload)
40 {
41 $page_data = [
42 'post_title' => $payload->post_title,
43 'post_name' => $payload->post_title,
44 // Check if type = kirki_page then change it to wp page type. cause we only set template if page type is kirki_page.
45 'post_type' => $payload->post_type === PostTypes::PAGE ? PostTypes::WP_PAGE : $payload->post_type,
46 ];
47
48 $page = PageModel::create_post($page_data);
49
50 if (!empty($payload->blocks)) {
51 // This is for popup creation. cause popup has predefined blocks.
52 Page::save_blocks($page->ID, $payload->blocks);
53 }
54
55 if (!empty($payload->conditions)) {
56 // This is for template creation. cause popup has predefined conditions.
57 PostMeta::update_meta_value($page->ID, PageMetaKeys::TEMPLATE_CONDITIONS, $payload->conditions);
58 }
59
60 // @todo: Need to remove this code. after checking collection_type used or not
61 if (!empty($payload->collection_type)) {
62 PostMeta::update_meta_value($page->ID, PageMetaKeys::TEMPLATE_COLLECTION_TYPE, $payload->collection_type);
63 }
64
65 if (!empty($payload->utility_page_type)) {
66 PostMeta::update_meta_value($page->ID, PageMetaKeys::UTILITY_PAGE_TYPE, $payload->utility_page_type);
67 }
68
69 Page::save_editor_mode($page->ID);
70
71 switch ($payload->post_type) {
72 case PostTypes::WP_PAGE:
73 case PostTypes::PAGE:
74 PostMeta::update_meta_value($page->ID, PageMetaKeys::PAGE_TEMPLATE, Canvas::get_full_canvas_template_path());
75 break;
76 case PostTypes::UTILITY:
77 if (!empty($payload->utility_page_type)) {
78 Template::assign_utility_page_template($page->ID, $payload->utility_page_type);
79 soft_flush_rewrite_rules();
80 }
81 break;
82 default:
83 break;
84 }
85
86 if (
87 !empty($payload->custom_template)
88 && isset($payload->custom_template['url'])
89 && !empty(($payload->custom_template['url']))
90 ) {
91 Template::assign_custom_page_template($page->ID, $payload->custom_template['url']);
92 }
93
94 if (!empty($payload->content_manager_collection_id) && !empty($payload->content_manager_page_kind)) {
95 try {
96 (new ContentManagerTemplateService())->initialize(
97 $page->ID,
98 (int) $payload->content_manager_collection_id,
99 $payload->content_manager_page_kind
100 );
101 } catch (\Throwable $error) {
102 PageModel::delete_post($page->ID, true);
103 throw $error;
104 }
105 }
106
107 return $page;
108 }
109
110 /**
111 * Update page data
112 *
113 * @param PageModel $page
114 * @param EditPageDTO $payload
115 *
116 * @return PageModel
117 */
118 public function update(PageModel $page, EditPageDTO $payload)
119 {
120 $post_payload = collection($payload->to_array())->filter(fn ($value) => !is_null($value))->to_array();
121
122 if (!empty($post_payload)) {
123 $page = PageModel::update_post($page->ID, $post_payload);
124
125 if ($page->post_type === PostTypes::UTILITY) {
126 soft_flush_rewrite_rules();
127 }
128 }
129
130 return $page;
131 }
132
133 public function update_popup_data(PageModel $popup, EditPopupDTO $payload)
134 {
135 if (!is_null($payload->blocks)) {
136 Page::save_blocks($popup->ID, $payload->blocks);
137 }
138
139 if (!is_null($payload->styleBlocks)) {
140 Page::save_style_blocks($popup->ID, $payload->styleBlocks);
141 }
142
143 if (!is_null($payload->usedFonts)) {
144 Page::save_used_font_list($popup->ID, $payload->usedFonts);
145 }
146
147 return $popup;
148 }
149
150 /**
151 * Save editor page data
152 *
153 * @return int|false - when not staging return false otherwise return staging version
154 */
155 public function save_page_data(EditorPagePayloadDTO $payload, string $page_content_type)
156 {
157 if (is_null($payload->page) || empty($payload->data)) {
158 return false;
159 }
160
161 Page::save_editor_mode($payload->page->ID);
162
163 $staging_version = false;
164 $page_data = $payload->data;
165
166 if($payload->is_staging) {
167 $staging_version = Page::get_most_recent_stage_version($payload->page->ID);
168 Page::set_last_edited_datetime_of_stage_version($payload->page->ID);
169 }
170
171 switch ($page_content_type) {
172 case PageContentTypes::BLOCKS:
173 Page::save_blocks($payload->page->ID, ['blocks' => $page_data['blocks'] ?? []], $staging_version);
174 break;
175 case PageContentTypes::STYLES:
176 $styles = $page_data['styles'] ?? [];
177 Page::save_style_blocks($payload->page->ID, $styles, $staging_version);
178 break;
179 case PageContentTypes::USED_STYLES:
180 Page::save_used_global_style_block_ids($payload->page->ID, $page_data['usedStyles'] ?? [], $staging_version);
181 break;
182 case PageContentTypes::USED_STYLE_IDS_RANDOM:
183 Page::save_used_style_block_ids($payload->page->ID, $page_data['usedStyleIdsRandom'] ?? [], $staging_version);
184 break;
185 case PageContentTypes::USED_FONTS:
186 Page::save_used_font_list($payload->page->ID, $page_data['usedFonts'] ?? [], $staging_version);
187 break;
188 case PageContentTypes::CUSTOM_FONTS:
189 // Save others data if isset. this is only used for template import
190 if (!isset($page_data['customFonts'])) {
191 break;
192 }
193
194 $custom_fonts = GlobalData::get_global_custom_fonts();
195
196 foreach ($page_data['customFonts'] as $key => $custom_font) {
197 $custom_fonts[$key] = $custom_font;
198 }
199
200 GlobalData::update_global_custom_fonts($custom_fonts);
201 break;
202 case PageContentTypes::VIEWPORT_LIST:
203 // Save others data if isset. this is only used for template import
204 if (!isset($page_data['viewportList'])) {
205 break;
206 }
207
208 $controller_data = GlobalData::get_global_ui_controller();
209
210 if (!$controller_data) {
211 $controller_data = [
212 'viewport' => [
213 'active' => 'md',
214 'defaults'=> ["md", "tablet", "mobileLandscape", "mobile"],
215 'list' => $page_data['viewportList'],
216 'mdWidth' => 1200,
217 "scale" => 1,
218 "width" => 2484,
219 "zoom" => 1
220 ]
221 ];
222 }
223
224 $controller_data['viewport']['list'] = $page_data['viewportList'];
225
226 GlobalData::update_global_ui_controller($controller_data);
227 break;
228 }
229
230 return $staging_version;
231 }
232
233 /**
234 * Toggle disabled page symbols
235 *
236 * @param TogglePageSymbolDTO $payload
237 *
238 * @return bool
239 */
240 public function toggle_disabled_page_symbols(TogglePageSymbolDTO $payload)
241 {
242 $prev_status = PostMeta::get_meta_value($payload->post_id, PageMetaKeys::DISABLED_PAGE_SYMBOLS, []);
243
244 if (!is_array($prev_status)) {
245 $prev_status = [];
246 }
247
248 $current_status = array_merge($prev_status, [$payload->symbol_type => $payload->disable]);
249
250 PostMeta::update_meta_value($payload->post_id, PageMetaKeys::DISABLED_PAGE_SYMBOLS, $current_status);
251
252 return true;
253 }
254
255 /**
256 * Duplicate page
257 *
258 * @param PageModel $current_page
259 *
260 * @return PageModel New page
261 */
262 public function duplicate_page(PageModel $current_page)
263 {
264 $new_page = PageModel::create_post([
265 'post_title' => $current_page->post_title . ' (copy)',
266 'post_content' => $current_page->post_content,
267 'post_name' => $current_page->post_name,
268 'post_type' => $current_page->post_type,
269 'post_status' => $current_page->post_status,
270 ]);
271
272 $current_page_block = PostMeta::get_meta_value($current_page->ID, PageMetaKeys::BLOCKS);
273
274 if (!empty($current_page_block)) {
275 Page::save_blocks($new_page->ID, $current_page_block);
276 Page::save_editor_mode($new_page->ID);
277 }
278
279 /**
280 * Also duplicate _wp_page_template meta if exists
281 */
282 $current_page_template = PostMeta::get_meta_value($current_page->ID, PageMetaKeys::PAGE_TEMPLATE);
283
284 if (!empty($current_page_template)) {
285 $current_page_template = Canvas::normalize_full_canvas_template_path($current_page_template);
286 PostMeta::update_meta_value($new_page->ID, PageMetaKeys::PAGE_TEMPLATE, $current_page_template);
287 }
288
289 /**
290 * Also duplicate this page style blocks if exists
291 */
292 $current_post_styles = PostMeta::get_meta_value($current_page->ID, PageMetaKeys::STYLE_BLOCKS, []);
293
294 if (!empty($current_post_styles)) {
295 Page::save_style_blocks($new_page->ID, $current_post_styles);
296 }
297
298 $current_used_fonts = PostMeta::get_meta_value($current_page->ID, PageMetaKeys::USED_FONT_LIST, []);
299
300 if (!empty($current_used_fonts)) {
301 Page::save_used_font_list($new_page->ID, $current_used_fonts);
302 }
303
304 if ($current_page->post_type === PostTypes::UTILITY) {
305 soft_flush_rewrite_rules();
306 }
307
308 return $new_page;
309 }
310
311 public function delete_page(PageModel $page) {
312 $is_deleted = PageModel::delete_post($page->ID);
313
314 if (!$is_deleted) {
315 throw new Exception(esc_html__('Page not deleted.', 'kirki'), Response::FORBIDDEN);
316 }
317
318 if ($page->post_type === PostTypes::UTILITY) {
319 soft_flush_rewrite_rules();
320 }
321
322 return $is_deleted;
323 }
324
325 /**
326 * Get all pages
327 *
328 * @param PageFilterDTO $filter_dto
329 *
330 * @return Paginator
331 */
332 public function paginated(PageFilterDTO $filter_dto)
333 {
334 $front_page_id = $filter_dto->current_page === 1 ? Page::get_front_page_id() : 0;
335
336 $paginated = PageModel::query()
337 ->with([
338 'meta' => function (QueryBuilder $query) {
339 $query->where_in('meta_key', PageMetaKeys::get_single_post_keys());
340 }])
341 ->filter_post_type($filter_dto->post_types)
342 ->filter_status($filter_dto->post_statuses)
343 ->where_not_in('ID', $filter_dto->exclude_page_ids)
344 ->search($filter_dto->query)
345 ->order_by_raw('CASE WHEN `ID` = %d THEN 0 ELSE 1 END', [$front_page_id])
346 ->order_by('ID', 'DESC')
347 ->paginate($filter_dto->limit, $filter_dto->current_page);
348
349 return $paginated;
350 }
351 }
352