PluginProbe
Elementor Website Builder – more than just a page builder / 3.35.0-dev4
Elementor Website Builder – more than just a page builder v3.35.0-dev4
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 / app / modules / kit-library / data / repository.php

repository.php in Elementor Website Builder – more than just a page builder 3.35.0-dev4, at app/modules/kit-library/data/repository.php

349 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\App\Modules\KitLibrary\Data;
3
4 use Elementor\Core\Common\Modules\Connect\Module as ConnectModule;
5 use Elementor\Core\Utils\Collection;
6 use Elementor\Data\V2\Base\Exceptions\Error_404;
7 use Elementor\Data\V2\Base\Exceptions\WP_Error_Exception;
8 use Elementor\Modules\Library\User_Favorites;
9 use Elementor\App\Modules\KitLibrary\Connect\Kit_Library;
10 use Elementor\Plugin;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly.
14 }
15
16 class Repository {
17 /**
18 * There is no label for subscription plan with access_level=0 + it should not
19 * be translated.
20 */
21 const SUBSCRIPTION_PLAN_FREE_TAG = 'Free';
22
23 const TAXONOMIES_KEYS = [ 'tags', 'categories', 'main_category', 'third_category', 'features', 'types' ];
24
25 const KITS_CACHE_KEY = 'elementor_remote_kits';
26 const KITS_TAXONOMIES_CACHE_KEY = 'elementor_remote_kits_taxonomies';
27
28 const KITS_CACHE_TTL_HOURS = 12;
29 const KITS_TAXONOMIES_CACHE_TTL_HOURS = 12;
30
31 /**
32 * @var Kit_Library
33 */
34 protected $api;
35
36 /**
37 * @var User_Favorites
38 */
39 protected $user_favorites;
40
41 /**
42 * @var Collection
43 */
44 protected $subscription_plans;
45
46 /**
47 * Get all kits.
48 *
49 * @param false $force_api_request
50 *
51 * @return Collection
52 */
53 public function get_all( $force_api_request = false ) {
54 return $this->get_kits_data( $force_api_request )
55 ->map( function ( $kit ) {
56 return $this->transform_kit_api_response( $kit );
57 } );
58 }
59
60 /**
61 * Get specific kit.
62 *
63 * @param $id
64 * @param array $options
65 *
66 * @return array|null
67 *
68 * @throws WP_Error_Exception If kit is not found.
69 */
70 public function find( $id, $options = [] ) {
71 $options = wp_parse_args( $options, [
72 'manifest_included' => true,
73 ] );
74
75 $item = $this->get_kits_data()
76 ->find( function ( $kit ) use ( $id ) {
77 return $kit->_id === $id;
78 } );
79
80 if ( ! $item ) {
81 return null;
82 }
83
84 $manifest = null;
85
86 if ( $options['manifest_included'] ) {
87 $manifest = $this->api->get_manifest( $id );
88
89 if ( is_wp_error( $manifest ) ) {
90 throw new WP_Error_Exception( esc_html( $manifest ) );
91 }
92 }
93
94 return $this->transform_kit_api_response( $item, $manifest );
95 }
96
97 /**
98 * @param false $force_api_request
99 *
100 * @return Collection
101 */
102 public function get_taxonomies( $force_api_request = false ) {
103 return $this->get_taxonomies_data( $force_api_request )
104 ->only( static::TAXONOMIES_KEYS )
105 ->reduce( function ( Collection $carry, $taxonomies, $type ) {
106 return $carry->merge( array_map( function ( $taxonomy ) use ( $type ) {
107 return [
108 'text' => $taxonomy->name,
109 'type' => $type,
110 ];
111 }, $taxonomies ) );
112 }, new Collection( [] ) )
113 ->merge(
114 $this->subscription_plans->map( function ( $label ) {
115 return [
116 'text' => $label ? $label : self::SUBSCRIPTION_PLAN_FREE_TAG,
117 'type' => 'subscription_plans',
118 ];
119 } )
120 )
121 ->unique( [ 'text', 'type' ] );
122 }
123
124 /**
125 * @param $id
126 *
127 * @return array
128 *
129 * @throws WP_Error_Exception If download link retrieval fails or API errors occur.
130 */
131 public function get_download_link( $id ) {
132 $response = $this->api->download_link( $id );
133
134 if ( is_wp_error( $response ) ) {
135 throw new WP_Error_Exception( esc_html( $response ) );
136 }
137
138 return [ 'download_link' => $response->download_link ];
139 }
140
141 /**
142 * @param $id
143 *
144 * @return array
145 *
146 * @throws Error_404 If kit is not found.
147 */
148 public function add_to_favorites( $id ) {
149 $kit = $this->find( $id, [ 'manifest_included' => false ] );
150
151 if ( ! $kit ) {
152 throw new Error_404( esc_html__( 'Kit not found', 'elementor' ), 'kit_not_found' );
153 }
154
155 $this->user_favorites->add( 'elementor', 'kits', $kit['id'] );
156
157 $kit['is_favorite'] = true;
158
159 return $kit;
160 }
161
162 /**
163 * @param $id
164 *
165 * @return array
166 *
167 * @throws Error_404 If kit is not found.
168 */
169 public function remove_from_favorites( $id ) {
170 $kit = $this->find( $id, [ 'manifest_included' => false ] );
171
172 if ( ! $kit ) {
173 throw new Error_404( esc_html__( 'Kit not found', 'elementor' ), 'kit_not_found' );
174 }
175
176 $this->user_favorites->remove( 'elementor', 'kits', $kit['id'] );
177
178 $kit['is_favorite'] = false;
179
180 return $kit;
181 }
182
183 /**
184 * @param bool $force_api_request
185 *
186 * @return Collection
187 *
188 * @throws WP_Error_Exception If kits data retrieval fails.
189 */
190 private function get_kits_data( $force_api_request = false ) {
191 $data = get_transient( static::KITS_CACHE_KEY );
192
193 $experiments_manager = Plugin::$instance->experiments;
194 $kits_editor_layout_type = $experiments_manager->is_feature_active( 'container' ) ? 'container_flexbox' : '';
195
196 if ( ! $data || $force_api_request ) {
197 $args = [
198 'body' => [
199 'editor_layout_type' => $kits_editor_layout_type,
200 ],
201 ];
202
203 /**
204 * Filters arguments for the request to the Kits API.
205 *
206 * @since 3.11.0
207 *
208 * @param array[] $args Array of http arguments.
209 */
210 $args = apply_filters( 'elementor/kit-library/get-kits-data/args', $args );
211
212 $data = $this->api->get_all( $args );
213
214 if ( is_wp_error( $data ) ) {
215 throw new WP_Error_Exception( esc_html( $data ) );
216 }
217
218 set_transient( static::KITS_CACHE_KEY, $data, static::KITS_CACHE_TTL_HOURS * HOUR_IN_SECONDS );
219 }
220
221 return new Collection( $data );
222 }
223
224 /**
225 * @param bool $force_api_request
226 *
227 * @return Collection
228 *
229 * @throws WP_Error_Exception If taxonomies data retrieval fails.
230 */
231 private function get_taxonomies_data( $force_api_request = false ) {
232 $data = get_transient( static::KITS_TAXONOMIES_CACHE_KEY );
233
234 if ( ! $data || $force_api_request ) {
235 $data = $this->api->get_taxonomies();
236
237 if ( is_wp_error( $data ) ) {
238 throw new WP_Error_Exception( esc_html( $data ) );
239 }
240
241 set_transient( static::KITS_TAXONOMIES_CACHE_KEY, $data, static::KITS_TAXONOMIES_CACHE_TTL_HOURS * HOUR_IN_SECONDS );
242 }
243
244 return new Collection( (array) $data );
245 }
246
247 /**
248 * @param $kit
249 * @param null $manifest
250 *
251 * @return array
252 */
253 private function transform_kit_api_response( $kit, $manifest = null ) {
254 // BC: Support legacy APIs that don't have access tiers.
255 if ( isset( $kit->access_tier ) ) {
256 $access_tier = $kit->access_tier;
257 } else {
258 $access_tier = 0 === $kit->access_level
259 ? ConnectModule::ACCESS_TIER_FREE
260 : ConnectModule::ACCESS_TIER_ESSENTIAL;
261 }
262
263 $subscription_plan_tag = $this->subscription_plans->get( $access_tier );
264
265 $taxonomies = ( new Collection( ( (array) $kit )['taxonomies'] ) )
266 ->filter( function ( $taxonomy ) {
267 return in_array( $taxonomy->type, self::TAXONOMIES_KEYS );
268 } )
269 ->flatten()
270 ->pluck( 'name' )
271 ->push( $subscription_plan_tag ? $subscription_plan_tag : self::SUBSCRIPTION_PLAN_FREE_TAG );
272
273 return array_merge(
274 [
275 'id' => $kit->_id,
276 'title' => $kit->title,
277 'thumbnail_url' => $kit->thumbnail,
278 'access_level' => $kit->access_level,
279 'access_tier' => $access_tier,
280 'keywords' => $kit->keywords,
281 'taxonomies' => $taxonomies->values(),
282 'is_favorite' => $this->user_favorites->exists( 'elementor', 'kits', $kit->_id ),
283 // TODO: Remove all the isset when the API stable.
284 'trend_index' => isset( $kit->trend_index ) ? $kit->trend_index : 0,
285 'featured_index' => isset( $kit->featured_index ) ? $kit->featured_index : 0,
286 'popularity_index' => isset( $kit->popularity_index ) ? $kit->popularity_index : 0,
287 'created_at' => isset( $kit->created_at ) ? $kit->created_at : null,
288 'updated_at' => isset( $kit->updated_at ) ? $kit->updated_at : null,
289 ],
290 $manifest ? $this->transform_manifest_api_response( $manifest ) : []
291 );
292 }
293
294 /**
295 * @param $manifest
296 *
297 * @return array
298 */
299 private function transform_manifest_api_response( $manifest ) {
300 $manifest_content = ( new Collection( (array) $manifest->content ) )
301 ->reduce( function ( $carry, $content, $type ) {
302 $mapped_documents = array_map( function ( $document ) use ( $type ) {
303 // TODO: Fix it!
304 // Hack to override a bug when a document with type of 'wp-page' is declared as 'wp-post'.
305 if ( 'page' === $type ) {
306 $document->doc_type = 'wp-page';
307 }
308
309 return $document;
310 }, (array) $content );
311
312 return $carry + $mapped_documents;
313 }, [] );
314
315 $content = ( new Collection( (array) $manifest->templates ) )
316 ->union( $manifest_content )
317 ->map( function ( $manifest_item, $key ) {
318 return [
319 'id' => isset( $manifest_item->id ) ? $manifest_item->id : $key,
320 'title' => $manifest_item->title,
321 'doc_type' => $manifest_item->doc_type,
322 'thumbnail_url' => $manifest_item->thumbnail,
323 'preview_url' => isset( $manifest_item->url ) ? $manifest_item->url : null,
324 ];
325 } );
326
327 return [
328 'description' => $manifest->description,
329 'preview_url' => isset( $manifest->site ) ? $manifest->site : '',
330 'documents' => $content->values(),
331 ];
332 }
333
334 /**
335 * @param Kit_Library $kit_library
336 * @param User_Favorites $user_favorites
337 * @param Collection $subscription_plans
338 */
339 public function __construct( Kit_Library $kit_library, User_Favorites $user_favorites, Collection $subscription_plans ) {
340 $this->api = $kit_library;
341 $this->user_favorites = $user_favorites;
342 $this->subscription_plans = $subscription_plans;
343 }
344
345 public static function clear_cache() {
346 delete_transient( static::KITS_CACHE_KEY );
347 }
348 }
349