PluginProbe
Elementor Website Builder – more than just a page builder / 4.1.0-beta1
Elementor Website Builder – more than just a page builder v4.1.0-beta1
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / modules / global-classes / global-class-post.php

global-class-post.php in Elementor Website Builder – more than just a page builder 4.1.0-beta1, at modules/global-classes/global-class-post.php

207 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\GlobalClasses;
4
5 use Elementor\Modules\AtomicWidgets\PropTypeMigrations\Migrations_Orchestrator;
6 use Elementor\Modules\GlobalClasses\Concerns\Has_Preview_Context;
7 use WP_Post;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly.
11 }
12
13 class Global_Class_Post {
14 use Has_Preview_Context;
15
16 const META_KEY_VERSION = '_elementor_version';
17 const META_KEY_ID = '_elementor_global_class_id';
18 const META_KEY_DATA = '_elementor_global_class_data';
19 const META_KEY_DATA_PREVIEW = '_elementor_global_class_data_preview';
20
21 protected array $context_keys = [
22 'data' => [
23 'frontend' => self::META_KEY_DATA,
24 'preview' => self::META_KEY_DATA_PREVIEW,
25 ],
26 ];
27
28 private WP_Post $post;
29
30 private function __construct( WP_Post $post ) {
31 $this->post = $post;
32 }
33
34 public static function from_post( WP_Post $post, bool $is_preview = false ): self {
35 return ( new self( $post ) )->set_preview( $is_preview );
36 }
37
38 public static function from_post_id( int $post_id, bool $is_preview = false ): ?self {
39 $post = get_post( $post_id );
40
41 if ( ! $post || Global_Class_Post_Type::CPT !== $post->post_type ) {
42 return null;
43 }
44
45 return ( new self( $post ) )->set_preview( $is_preview );
46 }
47
48 public static function find_by_class_id( string $class_id, bool $is_preview = false ): ?self {
49 $posts = get_posts( [
50 'post_type' => Global_Class_Post_Type::CPT,
51 'post_status' => 'publish',
52 'posts_per_page' => 1,
53 'meta_key' => self::META_KEY_ID,
54 'meta_value' => $class_id,
55 ] );
56
57 if ( empty( $posts ) ) {
58 return null;
59 }
60
61 return ( new self( $posts[0] ) )->set_preview( $is_preview );
62 }
63
64 public function get_post_id(): int {
65 return $this->post->ID;
66 }
67
68 public function get_class_id(): string {
69 $class_id = get_post_meta( $this->post->ID, self::META_KEY_ID, true );
70
71 if ( ! $class_id ) {
72 return '';
73 }
74
75 return $class_id;
76 }
77
78 public function get_label(): string {
79 return $this->post->post_title;
80 }
81
82 public function get_order(): int {
83 return (int) $this->post->menu_order;
84 }
85
86 public function get_data( bool $skip_migration = false ): array {
87 $data = $this->get_context_data();
88 $meta_key = $this->get_context_key( 'data' );
89
90 // Empty preview (draft) - use frontend (published) data
91 if ( empty( $data ) && $this->is_preview() ) {
92 $data = $this->get_frontend_data();
93 $meta_key = self::META_KEY_DATA;
94 }
95
96 if ( ! empty( $data ) && ( ! $skip_migration ) ) {
97 $this->migrate_data( $data, $meta_key );
98 }
99
100 return $data;
101 }
102
103 private function migrate_data( array &$data, string $meta_key ): void {
104 if ( ! Migrations_Orchestrator::is_active() ) {
105 return;
106 }
107
108 $post_id = $this->post->ID;
109
110 Migrations_Orchestrator::make()->migrate(
111 $data,
112 $post_id,
113 $meta_key,
114 function ( $migrated ) use ( $post_id, $meta_key ) {
115 update_post_meta( $post_id, $meta_key, $migrated );
116 clean_post_cache( $post_id );
117 }
118 );
119 }
120
121 public function to_array( bool $skip_migration = false ): array {
122 $data = $this->get_data( $skip_migration );
123
124 $result = [
125 'id' => $this->get_class_id(),
126 'label' => $this->get_label(),
127 'type' => $data['type'] ?? 'class',
128 'variants' => $data['variants'] ?? [],
129 ];
130
131 if ( array_key_exists( 'sync_to_v3', $data ) ) {
132 $result['sync_to_v3'] = (bool) $data['sync_to_v3'];
133 }
134
135 return $result;
136 }
137
138 public function update_label( string $label ): bool {
139 $result = wp_update_post( [
140 'ID' => $this->post->ID,
141 'post_title' => $label,
142 ] );
143
144 return ! is_wp_error( $result );
145 }
146
147 private function get_context_data(): array {
148 $data = get_post_meta( $this->post->ID, $this->get_context_key( 'data' ), true );
149
150 return is_array( $data ) ? $data : [];
151 }
152
153 private function get_frontend_data(): array {
154 $data = get_post_meta( $this->post->ID, self::META_KEY_DATA, true );
155
156 return is_array( $data ) ? $data : [];
157 }
158
159 public function update_data(
160 array $data,
161 string $version = ELEMENTOR_VERSION
162 ): bool {
163 $meta_key = $this->get_context_key( 'data' );
164
165 $result = update_post_meta( $this->post->ID, $meta_key, $data );
166
167 if ( ! $this->is_preview() ) {
168 delete_post_meta( $this->post->ID, self::META_KEY_DATA_PREVIEW );
169 }
170
171 update_post_meta( $this->post->ID, self::META_KEY_VERSION, $version );
172
173 return false !== $result;
174 }
175
176 public static function create(
177 string $class_id,
178 string $label,
179 array $data,
180 int $order = 0,
181 string $version = ELEMENTOR_VERSION
182 ): ?self {
183 $post_id = wp_insert_post( [
184 'post_type' => Global_Class_Post_Type::CPT,
185 'post_title' => $label,
186 'post_status' => 'publish',
187 'menu_order' => $order,
188 ] );
189
190 if ( is_wp_error( $post_id ) || ! $post_id ) {
191 return null;
192 }
193
194 update_post_meta( $post_id, self::META_KEY_ID, $class_id );
195 update_post_meta( $post_id, self::META_KEY_DATA, $data );
196 update_post_meta( $post_id, self::META_KEY_VERSION, $version );
197
198 return self::from_post_id( $post_id );
199 }
200
201 public function delete(): bool {
202 $result = wp_delete_post( $this->post->ID, true );
203
204 return false !== $result;
205 }
206 }
207