| @@ -12,62 +12,73 @@ | ||
| 12 | 12 | use ABlocks\import\CustomizerImporter; |
| 13 | 13 | use ABlocks\import\ThemeOptions\CodeStar; |
| 14 | 14 | use ABlocks\import\ThemeOptions\Redux; |
| 15 | 15 | use ABlocks\import\WidgetImporter; |
| 16 | +use ABlocksThemeBuilder\Database; | |
| 16 | 17 | |
| 17 | 18 | class DemoImport extends AbstractAjaxHandler { |
| 18 | 19 | |
| 19 | 20 | public function __construct() { |
| 20 | 21 | $this->actions = array( |
| 21 | - 'get_demo_list' => array( | |
| 22 | - 'callback' => array( $this, 'get_demo_list' ), | |
| 23 | - 'fields' => array( | |
| 24 | - 'type' => 'string', | |
| 22 | + 'get_demo_list' => array( | |
| 23 | + 'callback' => array( $this, 'get_demo_list' ), | |
| 24 | + 'capability' => 'ablocks_import_templates', | |
| 25 | + 'fields' => array( | |
| 26 | + 'type' => 'string', | |
| 25 | 27 | 'cost_type' => 'string', |
| 26 | - 'page' => 'integer', | |
| 27 | - 'per_page' => 'integer', | |
| 28 | - 'category' => 'string', | |
| 29 | - 'dev' => 'string', | |
| 30 | - 'q' => 'string', | |
| 28 | + 'page' => 'integer', | |
| 29 | + 'per_page' => 'integer', | |
| 30 | + 'category' => 'string', | |
| 31 | + 'dev' => 'string', | |
| 32 | + 'q' => 'string', | |
| 31 | 33 | ) |
| 32 | 34 | ), |
| 33 | - 'get_single_demo' => array( | |
| 34 | - 'callback' => array( $this, 'get_single_demo' ), | |
| 35 | - 'fields' => array( | |
| 36 | - 'id' => 'integer', | |
| 35 | + 'get_single_demo' => array( | |
| 36 | + 'callback' => array( $this, 'get_single_demo' ), | |
| 37 | + 'capability' => 'ablocks_import_templates', | |
| 38 | + 'fields' => array( | |
| 39 | + 'id' => 'integer', | |
| 37 | 40 | 'with_images' => 'string', |
| 38 | 41 | ) |
| 39 | 42 | ), |
| 40 | - 'get_demo_categories' => array( | |
| 41 | - 'callback' => array( $this, 'get_demo_categories' ), | |
| 42 | - 'fields' => array( | |
| 43 | + 'get_demo_categories' => array( | |
| 44 | + 'callback' => array( $this, 'get_demo_categories' ), | |
| 45 | + 'capability' => 'ablocks_import_templates', | |
| 46 | + 'fields' => array( | |
| 43 | 47 | 'type' => 'string', |
| 44 | 48 | ) |
| 45 | 49 | ), |
| 46 | - 'get_theme_demos' => array( | |
| 47 | - 'callback' => array( $this, 'get_theme_demos' ), | |
| 50 | + 'get_theme_demos' => array( | |
| 51 | + 'callback' => array( $this, 'get_theme_demos' ), | |
| 52 | + 'capability' => 'ablocks_import_templates', | |
| 48 | 53 | ), |
| 49 | - 'check_dependencies' => array( | |
| 50 | - 'callback' => array( $this, 'check_dependencies' ), | |
| 51 | - 'fields' => array( | |
| 54 | + 'check_dependencies' => array( | |
| 55 | + 'callback' => array( $this, 'check_dependencies' ), | |
| 56 | + 'capability' => 'ablocks_import_templates', | |
| 57 | + 'fields' => array( | |
| 52 | 58 | 'dependencies' => 'array|string', |
| 53 | 59 | ) |
| 54 | 60 | ), |
| 55 | - 'install_and_active' => array( | |
| 56 | - 'callback' => array( $this, 'install_and_active' ), | |
| 57 | - 'fields' => array( | |
| 61 | + 'install_and_active' => array( | |
| 62 | + 'callback' => array( $this, 'install_and_active' ), | |
| 63 | + // A demo's dependencies are plugins. Importing templates is a | |
| 64 | + // design permission; installing plugins is not, and must never | |
| 65 | + // become reachable through one. | |
| 66 | + 'capability' => 'install_plugins', | |
| 67 | + 'fields' => array( | |
| 58 | 68 | 'dependency' => 'array|string', |
| 59 | 69 | ) |
| 60 | 70 | ), |
| 61 | - 'import_template' => array( | |
| 62 | - 'callback' => array( $this, 'import_template' ), | |
| 63 | - 'fields' => array( | |
| 64 | - 'file_url' => 'string', | |
| 71 | + 'import_template' => array( | |
| 72 | + 'callback' => array( $this, 'import_template' ), | |
| 73 | + 'capability' => 'ablocks_import_templates', | |
| 74 | + 'fields' => array( | |
| 75 | + 'file_url' => 'string', | |
| 65 | 76 | 'customizer_file_url' => 'string', |
| 66 | - 'widget_file_url' => 'string', | |
| 67 | - 'codestar_file_url' => 'string', | |
| 68 | - 'redux_options' => 'json', | |
| 69 | - 'with_images' => 'boolean', | |
| 77 | + 'widget_file_url' => 'string', | |
| 78 | + 'codestar_file_url' => 'string', | |
| 79 | + 'redux_options' => 'json', | |
| 80 | + 'with_images' => 'boolean', | |
| 70 | 81 | ) |
| 71 | 82 | ), |
| 72 | 83 | ); |
| 73 | 84 | } |
| @@ -80,11 +91,11 @@ | ||
| 80 | 91 | * @return void |
| 81 | 92 | */ |
| 82 | 93 | public function get_demo_list( array $data ) { |
| 83 | 94 | $args = [ |
| 84 | - 'type' => $data['type'] ?? 'pattern', | |
| 95 | + 'type' => $data['type'] ?? 'pattern', | |
| 85 | 96 | 'cost_type' => $data['cost_type'] ?? 'all', |
| 86 | - 'page' => $data['page'] ?? 1, | |
| 97 | + 'page' => $data['page'] ?? 1, | |
| 87 | 98 | ]; |
| 88 | 99 | |
| 89 | 100 | if ( isset( $data['category'] ) ) { |
| 90 | 101 | $args['category'] = $data['category']; |
| @@ -101,10 +112,10 @@ | ||
| 101 | 112 | if ( isset( $data['per_page'] ) ) { |
| 102 | 113 | $args['per_page'] = $data['per_page']; |
| 103 | 114 | } |
| 104 | 115 | |
| 105 | - $hash = md5( wp_json_encode( $args ) ); | |
| 106 | - $key = "ablocks_demo_$hash"; | |
| 116 | + $hash = md5( wp_json_encode( $args ) ); | |
| 117 | + $key = "ablocks_demo_$hash"; | |
| 107 | 118 | $has_response = get_transient( $key ); |
| 108 | 119 | if ( $has_response ) { |
| 109 | 120 | wp_send_json_success( $has_response ); |
| 110 | 121 | } |
| @@ -124,16 +135,16 @@ | ||
| 124 | 135 | public function get_single_demo( array $data ) { |
| 125 | 136 | if ( ! $data['id'] ) { |
| 126 | 137 | wp_send_json_error( __( 'id is required.', 'ablocks' ) ); |
| 127 | 138 | } |
| 128 | - $id = absint( $data['id'] ); | |
| 139 | + $id = absint( $data['id'] ); | |
| 129 | 140 | $with_images = isset( $data['with_images'] ) && true === (bool) $data['with_images']; |
| 130 | 141 | |
| 131 | - $key = 'ablocks_demo_item_' . $id; | |
| 142 | + $key = 'ablocks_demo_item_' . $id; | |
| 132 | 143 | $has_response = get_transient( $key ); |
| 133 | 144 | if ( $has_response ) { |
| 134 | 145 | if ( $with_images && ! isset( $has_response['remote_images_parsed'] ) ) { |
| 135 | - $has_response['content'] = Helper::parse_remote_images( $has_response['content'] ); | |
| 146 | + $has_response['content'] = Helper::parse_remote_images( $has_response['content'] ); | |
| 136 | 147 | $has_response['remote_images_parsed'] = true; |
| 137 | 148 | set_transient( $key, $has_response, WEEK_IN_SECONDS ); |
| 138 | 149 | } |
| 139 | 150 | unset( $has_response['remote_images_parsed'] ); |
| @@ -139,9 +150,9 @@ | ||
| 139 | 150 | unset( $has_response['remote_images_parsed'] ); |
| 140 | 151 | wp_send_json_success( $has_response ); |
| 141 | 152 | } |
| 142 | 153 | |
| 143 | - $url = 'https://' . ABLOCKS_TEMPLATE_LIB_HOST . '/wp-json/ablocks_server/v1/ablocks/' . $id; | |
| 154 | + $url = 'https://' . ABLOCKS_TEMPLATE_LIB_HOST . '/wp-json/ablocks_server/v1/ablocks/' . $id; | |
| 144 | 155 | $response = wp_safe_remote_get( $url ); |
| 145 | 156 | if ( is_wp_error( $response ) ) { |
| 146 | 157 | wp_send_json_error( $response->get_error_message() ); |
| 147 | 158 | } |
| @@ -146,10 +157,10 @@ | ||
| 146 | 157 | wp_send_json_error( $response->get_error_message() ); |
| 147 | 158 | } |
| 148 | 159 | |
| 149 | 160 | $response_code = wp_remote_retrieve_response_code( $response ); |
| 150 | - $response = wp_remote_retrieve_body( $response ); | |
| 151 | - $response = json_decode( $response, true ); | |
| 161 | + $response = wp_remote_retrieve_body( $response ); | |
| 162 | + $response = json_decode( $response, true ); | |
| 152 | 163 | if ( $response_code !== 200 ) { |
| 153 | 164 | wp_send_json_error( $response ); |
| 154 | 165 | } |
| 155 | 166 | |
| @@ -156,9 +167,9 @@ | ||
| 156 | 167 | $response = $response['data']; |
| 157 | 168 | if ( $with_images ) { |
| 158 | 169 | $content = $response['content'] ?? null; |
| 159 | 170 | if ( $content ) { |
| 160 | - $response['content'] = Helper::parse_remote_images( wp_unslash( $content ) ); | |
| 171 | + $response['content'] = Helper::parse_remote_images( wp_unslash( $content ) ); | |
| 161 | 172 | $response['remote_images_parsed'] = true; |
| 162 | 173 | } |
| 163 | 174 | } |
| 164 | 175 | set_transient( $key, $response, WEEK_IN_SECONDS ); |
| @@ -173,10 +184,10 @@ | ||
| 173 | 184 | * |
| 174 | 185 | * @return void |
| 175 | 186 | */ |
| 176 | 187 | public function get_demo_categories( array $data ) { |
| 177 | - $type = $data['type'] ?? 'pattern'; | |
| 178 | - $key = "ablocks_demo_categories_$type"; | |
| 188 | + $type = $data['type'] ?? 'pattern'; | |
| 189 | + $key = "ablocks_demo_categories_$type"; | |
| 179 | 190 | $has_response = get_transient( $key ); |
| 180 | 191 | if ( $has_response ) { |
| 181 | 192 | wp_send_json_success( $has_response ); |
| 182 | 193 | } |
| @@ -193,27 +204,27 @@ | ||
| 193 | 204 | */ |
| 194 | 205 | public function get_theme_demos() { |
| 195 | 206 | $demo_config = Helper::get_theme_demo_config(); |
| 196 | 207 | if ( ! $demo_config ) { |
| 197 | - wp_send_json_error([ | |
| 208 | + wp_send_json_error( [ | |
| 198 | 209 | 'message' => 'Current theme demo isn\'t configured.', |
| 199 | - ]); | |
| 210 | + ] ); | |
| 200 | 211 | } |
| 201 | 212 | |
| 202 | - $demos = $demo_config['demos']; | |
| 213 | + $demos = $demo_config['demos']; | |
| 203 | 214 | $categories = []; |
| 204 | 215 | foreach ( $demos as &$demo ) { |
| 205 | 216 | $demo_categories = []; |
| 206 | 217 | foreach ( $demo['categories'] as $category ) { |
| 207 | 218 | if ( is_array( $category ) ) { |
| 208 | - $categories[] = $category; | |
| 219 | + $categories[] = $category; | |
| 209 | 220 | $demo_categories[] = $category; |
| 210 | 221 | } else { |
| 211 | - $demo_category = [ | |
| 222 | + $demo_category = [ | |
| 212 | 223 | 'label' => ucfirst( $category ), |
| 213 | - 'slug' => str_replace( ' ', '-', trim( $category ) ), | |
| 224 | + 'slug' => str_replace( ' ', '-', trim( $category ) ), | |
| 214 | 225 | ]; |
| 215 | - $categories[] = $demo_category; | |
| 226 | + $categories[] = $demo_category; | |
| 216 | 227 | $demo_categories[] = $demo_category; |
| 217 | 228 | } |
| 218 | 229 | } |
| 219 | 230 | $demo['categories'] = $demo_categories; |
| @@ -218,14 +229,14 @@ | ||
| 218 | 229 | } |
| 219 | 230 | $demo['categories'] = $demo_categories; |
| 220 | 231 | } |
| 221 | 232 | |
| 222 | - $preloaded_categories = array_map(fn ( $category) => is_array( $category ) ? $category : [ | |
| 233 | + $preloaded_categories = array_map( fn( $category ) => is_array( $category ) ? $category : [ | |
| 223 | 234 | 'label' => ucfirst( $category ), |
| 224 | - 'slug' => str_replace( ' ', '-', trim( $category ) ), | |
| 225 | - ], $demo_config['preloaded_demo_category']); | |
| 235 | + 'slug' => str_replace( ' ', '-', trim( $category ) ), | |
| 236 | + ], $demo_config['preloaded_demo_category'] ); | |
| 226 | 237 | |
| 227 | - $categories_slugs = array_map( fn ( $category) => $category['slug'], $categories ); | |
| 238 | + $categories_slugs = array_map( fn( $category ) => $category['slug'], $categories ); | |
| 228 | 239 | foreach ( $preloaded_categories as $preloaded_category ) { |
| 229 | 240 | if ( ! in_array( $preloaded_category['slug'], $categories_slugs, true ) ) { |
| 230 | 241 | $categories[] = $preloaded_category; |
| 231 | 242 | } |
| @@ -231,12 +242,12 @@ | ||
| 231 | 242 | } |
| 232 | 243 | } |
| 233 | 244 | |
| 234 | 245 | wp_send_json_success( array( |
| 235 | - 'categories' => $categories, | |
| 236 | - 'preloaded_demo' => $demo_config['preloaded_demo'], | |
| 246 | + 'categories' => $categories, | |
| 247 | + 'preloaded_demo' => $demo_config['preloaded_demo'], | |
| 237 | 248 | 'preloaded_demo_categories' => $preloaded_categories, |
| 238 | - 'demos' => $demos, | |
| 249 | + 'demos' => $demos, | |
| 239 | 250 | ) ); |
| 240 | 251 | } |
| 241 | 252 | |
| 242 | 253 | /** |
| @@ -252,10 +263,10 @@ | ||
| 252 | 263 | } |
| 253 | 264 | |
| 254 | 265 | $dependencies = Sanitizer::sanitize_array_field( $data['dependencies'] ); |
| 255 | 266 | foreach ( $dependencies as $index => $dependency ) { |
| 256 | - $type = 'check_' . ( $dependency['type'] ?? 'plugin' ); | |
| 257 | - $status = Helper::$type( $dependency['slug'] ); | |
| 267 | + $type = 'check_' . ( $dependency['type'] ?? 'plugin' ); | |
| 268 | + $status = Helper::$type( $dependency['slug'] ); | |
| 258 | 269 | $dependencies[ $index ]['status'] = $status; |
| 259 | 270 | if ( isset( $dependency['id'] ) ) { |
| 260 | 271 | $dependencies[ $index ]['id'] = (int) $dependency['id']; |
| 261 | 272 | } |
| @@ -275,14 +286,14 @@ | ||
| 275 | 286 | if ( ! isset( $data['dependency'] ) ) { |
| 276 | 287 | return; |
| 277 | 288 | } |
| 278 | 289 | $dependency = Sanitizer::sanitize_array_field( $data['dependency'] ); |
| 279 | - $method = 'install_and_active_' . ( $dependency['type'] ?? 'plugin' ); | |
| 280 | - $activated = Helper::$method( $dependency['slug'] ); | |
| 290 | + $method = 'install_and_active_' . ( $dependency['type'] ?? 'plugin' ); | |
| 291 | + $activated = Helper::$method( $dependency['slug'] ); | |
| 281 | 292 | if ( is_wp_error( $activated ) ) { |
| 282 | - wp_send_json_error(array( | |
| 293 | + wp_send_json_error( array( | |
| 283 | 294 | 'message' => $activated->get_error_message(), |
| 284 | - )); | |
| 295 | + ) ); | |
| 285 | 296 | } |
| 286 | 297 | |
| 287 | 298 | wp_send_json_success(); |
| 288 | 299 | } |
| @@ -298,18 +309,18 @@ | ||
| 298 | 309 | if ( ! isset( $data['file_url'] ) ) { |
| 299 | 310 | return; |
| 300 | 311 | } |
| 301 | 312 | |
| 302 | - $file_url = $data['file_url']; | |
| 313 | + $file_url = $data['file_url']; | |
| 303 | 314 | $content_file_path = Helper::remote_to_tmp_file( $file_url ); |
| 304 | 315 | |
| 305 | - $customizer_file_url = $data['customizer_file_url'] ?? ''; | |
| 316 | + $customizer_file_url = $data['customizer_file_url'] ?? ''; | |
| 306 | 317 | $customizer_file_path = Helper::remote_to_tmp_file( $customizer_file_url ); |
| 307 | - $widget_file_url = $data['widget_file_url'] ?? ''; | |
| 308 | - $widget_file_path = Helper::remote_to_tmp_file( $widget_file_url ); | |
| 309 | - $codestar_file_url = $data['codestar_file_url'] ?? ''; | |
| 310 | - $codestar_file_path = Helper::remote_to_tmp_file( $codestar_file_url ); | |
| 311 | - $with_images = isset( $data['with_images'] ) && true === $data['with_images']; | |
| 318 | + $widget_file_url = $data['widget_file_url'] ?? ''; | |
| 319 | + $widget_file_path = Helper::remote_to_tmp_file( $widget_file_url ); | |
| 320 | + $codestar_file_url = $data['codestar_file_url'] ?? ''; | |
| 321 | + $codestar_file_path = Helper::remote_to_tmp_file( $codestar_file_url ); | |
| 322 | + $with_images = isset( $data['with_images'] ) && true === $data['with_images']; | |
| 312 | 323 | |
| 313 | 324 | // Start the event stream. |
| 314 | 325 | header( 'Content-Type: text/event-stream, charset=UTF-8' ); |
| 315 | 326 | header( 'Cache-Control: no-store' ); |
| @@ -335,9 +346,33 @@ | ||
| 335 | 346 | // Ensure we're not buffered. |
| 336 | 347 | wp_ob_end_flush_all(); |
| 337 | 348 | flush(); |
| 338 | 349 | |
| 350 | + if ( is_wp_error( $content_file_path ) ) { | |
| 351 | + Helper::emit_sse_message( [ | |
| 352 | + 'action' => 'complete', | |
| 353 | + 'error' => is_string( $codestar_file_path->get_error_message() ) && ! empty( $codestar_file_path->get_error_message() ) ? $codestar_file_path->get_error_code() : __( 'Invalid content path.', 'ablocks' ), | |
| 354 | + ] ); | |
| 355 | + exit; | |
| 356 | + } | |
| 357 | + | |
| 339 | 358 | do_action( 'ablocks/import/before_template_import_start', $data ); |
| 359 | + | |
| 360 | + if ( ! Helper::get_addon_active_status( 'theme-builder' ) && ! Helper::is_fse_theme() ) { | |
| 361 | + $saved_addons = json_decode( get_option( ABLOCKS_ADDONS_SETTINGS_NAME, '{}' ), true ); | |
| 362 | + if ( ! is_array( $saved_addons ) ) { | |
| 363 | + $saved_addons = []; | |
| 364 | + } | |
| 365 | + | |
| 366 | + $addon_slug = 'theme-builder'; | |
| 367 | + $saved_addons[ $addon_slug ] = true; | |
| 368 | + do_action( "ablocks/addons/activated_$addon_slug" ); | |
| 369 | + | |
| 370 | + update_option( ABLOCKS_ADDONS_SETTINGS_NAME, wp_json_encode( $saved_addons ) ); | |
| 371 | + ( new Database() )->create_ablocks_tb_post_type(); | |
| 372 | + ( new Database() )->register_ablocks_tb_meta(); | |
| 373 | + } | |
| 374 | + | |
| 340 | 375 | $template_import = Helper::import_template( $content_file_path, $with_images ); |
| 341 | 376 | if ( ! is_wp_error( $template_import ) ) { |
| 342 | 377 | if ( ! empty( $customizer_file_path ) && ! is_wp_error( $customizer_file_path ) ) { |
| 343 | 378 | CustomizerImporter::import( $customizer_file_path ); |
| @@ -374,18 +409,34 @@ | ||
| 374 | 409 | * |
| 375 | 410 | * @return void |
| 376 | 411 | */ |
| 377 | 412 | private function handle_list_response( string $url, string $key ): void { |
| 378 | - $response = wp_safe_remote_get( $url ); | |
| 413 | + global $wp_version; | |
| 414 | + $response = wp_safe_remote_get( $url, array( | |
| 415 | + 'headers' => array( | |
| 416 | + 'Accept' => 'application/json', | |
| 417 | + 'user-agent' => sprintf( | |
| 418 | + 'aBlocks/%1$s (%2$s; WordPress/%3$s) %4$s', | |
| 419 | + ABLOCKS_VERSION, | |
| 420 | + get_option( 'blogname' ), | |
| 421 | + $wp_version, | |
| 422 | + home_url() | |
| 423 | + ), | |
| 424 | + ), | |
| 425 | + ) ); | |
| 379 | 426 | if ( is_wp_error( $response ) ) { |
| 380 | - wp_send_json_error( $response->get_error_message() ); | |
| 427 | + wp_send_json_error( [ | |
| 428 | + 'message' => $response->get_error_message() | |
| 429 | + ] ); | |
| 381 | 430 | } |
| 382 | 431 | |
| 383 | 432 | $response_code = wp_remote_retrieve_response_code( $response ); |
| 384 | 433 | $response = wp_remote_retrieve_body( $response ); |
| 385 | 434 | $response = json_decode( $response, true ); |
| 386 | - if ( $response_code !== 200 ) { | |
| 387 | - wp_send_json_error( $response ); | |
| 435 | + if ( $response_code !== 200 || isset( $response['message'] ) ) { | |
| 436 | + wp_send_json_error( [ | |
| 437 | + 'message' => $response['message'] | |
| 438 | + ] ); | |
| 388 | 439 | } |
| 389 | 440 | |
| 390 | 441 | set_transient( $key, $response, WEEK_IN_SECONDS ); |
| 391 | 442 | wp_send_json_success( $response ); |