PluginProbe ʕ •ᴥ•ʔ
Starter Sites & Templates by Neve / trunk
Starter Sites & Templates by Neve vtrunk
1.4.0 1.3.0 1.2.29 1.2.28 1.2.6 1.2.7 1.2.8 1.2.9 trunk 1.0.10 1.0.11 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 1.1.22 1.1.23 1.1.24 1.1.25 1.1.26 1.1.27 1.1.28 1.1.29 1.1.3 1.1.30 1.1.31 1.1.32 1.1.33 1.1.34 1.1.35 1.1.36 1.1.37 1.1.38 1.1.39 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.3 1.2.4 1.2.5
templates-patterns-collection / includes / WP_Cli.php
templates-patterns-collection / includes Last commit date
Importers 2 months ago Admin.php 1 week ago Editor.php 1 year ago Elementor.php 1 year ago License.php 1 year ago Logger.php 2 years ago Main.php 1 week ago Rest_Server.php 2 weeks ago Sites_Listing.php 2 weeks ago Starter_Ranking.php 1 week ago TI_Beaver.php 1 year ago WP_Cli.php 3 months ago White_Label_Config.php 3 years ago
WP_Cli.php
421 lines
1 <?php
2 /**
3 * WP CLI commands.
4 *
5 * Author: Andrei Baicus <andrei@themeisle.com>
6 * Created on: 26/06/2019
7 *
8 * @package templates-patterns-collection
9 */
10
11 namespace TIOB;
12
13 use TIOB\Importers\Content_Importer;
14 use TIOB\Importers\Helpers\Helper;
15 use TIOB\Importers\Helpers\Slug_Mapping;
16 use TIOB\Importers\Plugin_Importer;
17 use TIOB\Importers\Theme_Mods_Importer;
18 use TIOB\Importers\Widgets_Importer;
19
20 /**
21 * Class WP_Cli
22 */
23 class WP_Cli {
24 use Helper;
25
26 /**
27 * Command namespace version.
28 *
29 * @var string Version string.
30 */
31 const CLI_NAMESPACE = 'themeisle-si';
32 /**
33 * List of commands.
34 *
35 * @var array List of REST controllers.
36 */
37 private $commands = array(
38 'import' => 'import',
39 'list_sites' => 'list',
40 );
41
42 /**
43 * All sites data.
44 *
45 * @var array
46 */
47 private $data = array();
48
49 /**
50 * Theme mods importer.
51 *
52 * @var Theme_Mods_Importer
53 */
54 private $theme_mods_importer;
55
56 /**
57 * Content importer.
58 *
59 * @var Content_Importer
60 */
61 private $content_importer;
62
63 /**
64 * Widgets importer.
65 *
66 * @var Widgets_Importer
67 */
68 private $widgets_importer;
69
70 /**
71 * Plugins importer.
72 *
73 * @var Plugin_Importer
74 */
75 private $plugin_importer;
76
77 /**
78 * Setup class props.
79 */
80 private function setup_props() {
81 $theme_support = get_theme_support( 'themeisle-demo-import' );
82 $this->data = $theme_support[0]['remote'];
83 $this->theme_mods_importer = new Theme_Mods_Importer();
84 $this->content_importer = new Content_Importer();
85 $this->widgets_importer = new Widgets_Importer();
86 $this->plugin_importer = new Plugin_Importer();
87 }
88
89 /**
90 * Load the WP CLI commands.
91 */
92 public function load_commands() {
93 foreach ( $this->commands as $callback => $command ) {
94 try {
95 \WP_CLI::add_command( self::CLI_NAMESPACE . ' ' . $command, array( $this, $callback ) );
96 } catch ( \Exception $e ) {
97 error_log( 'Error loading cli commnands' . $e->getMessage() );
98 }
99 }
100 }
101
102 /**
103 * Get all sites as (string) $slug => (array) $args
104 *
105 * @param string|boolean $builder what editor to get sites for.
106 *
107 * @return array
108 */
109 private function get_all_sites( $builder = false ) {
110 $this->setup_props();
111 $all_sites = array();
112
113 foreach ( $this->data as $editor => $sites ) {
114
115 if ( $builder !== false && strpos( $editor, $builder ) === false ) {
116 continue;
117 }
118 foreach ( $sites as $slug => $data ) {
119 $this->data[ $editor ][ $slug ]['slug'] = $slug;
120 $this->data[ $editor ][ $slug ]['editor'] = $editor;
121 $all_sites[ $slug ] = $this->data[ $editor ][ $slug ];
122 }
123 }
124
125 return $all_sites;
126 }
127
128 /**
129 * Import single starter site.
130 *
131 * ## OPTIONS
132 *
133 * <slug>
134 * : The slug of the starter site to import. T
135 *
136 *
137 * ## EXAMPLES
138 *
139 * wp themeisle-si import neve-restaurant
140 *
141 * @param array $args inline args.
142 * @param array $assoc_args associative args.
143 *
144 */
145 public function import( $args, $assoc_args ) {
146 $this->setup_props();
147
148 $sites = $this->get_all_sites();
149 $site_slug = $args[0];
150 if ( ! array_key_exists( $site_slug, $sites ) ) {
151 \WP_CLI::warning( "No site to import with the slug {$site_slug}." );
152
153 return;
154 }
155
156 $site = $sites[ $site_slug ];
157 if ( isset( $site['url'] ) ) {
158 Slug_Mapping::register_source_url( $site['url'] );
159 }
160
161 $json_array = $this->get_starter_site_json( $site );
162 $this->import_plugins_for_starter_site( $json_array );
163 $xml = $this->get_starter_site_xml( $site, $json_array );
164 \WP_CLI::line( 'Importing content file...' );
165 $this->import_xml_file( $xml, array_merge( array( 'demoSlug' => $site_slug ), $json_array ), $site['editor'] );
166 \WP_CLI::line( 'Done!' );
167 $this->import_theme_mods( $json_array );
168 $this->setup_pages( $json_array, $args[0] );
169 $this->import_widgets( $json_array );
170 }
171
172 /**
173 * Import widgets
174 *
175 * @param array $json site json data.
176 */
177 private function import_widgets( $json ) {
178 if ( ! isset( $json['widgets'] ) || empty( $json['widgets'] ) ) {
179 return;
180 }
181 $this->widgets_importer->actually_import( $json['widgets'] );
182 }
183
184 /**
185 * Setup pages
186 *
187 * @param array $json site json data.
188 * @param string $demo_slug the demo slug.
189 */
190 private function setup_pages( $json, $demo_slug ) {
191 if ( isset( $json['front_page'] ) ) {
192 $this->content_importer->setup_front_page( $json['front_page'], $demo_slug );
193 } else {
194 \WP_CLI::warning( 'Incorrect front page arguments.' );
195 }
196
197 if ( isset( $json['shop_pages'] ) ) {
198 $this->content_importer->setup_shop_pages( $json['shop_pages'], $demo_slug );
199 } else {
200 \WP_CLI::warning( 'No shop page arguments.' );
201 }
202 }
203
204 /**
205 * Import theme mods
206 *
207 * @param array $json site json data.
208 */
209 private function import_theme_mods( $json ) {
210
211 if ( isset( $json['theme_mods'] ) && ! empty( $json['theme_mods'] ) ) {
212 array_walk(
213 $json['theme_mods'],
214 function ( &$item ) {
215 $item = $this->replace_image_urls( $item );
216 $item = Slug_Mapping::rewrite_value( $item );
217 }
218 );
219
220 foreach ( $json['theme_mods'] as $key => $value ) {
221 if ( $key === '__ti_import_menus_location' ) {
222 continue;
223 }
224 if ( $value === 'true' ) {
225 $value = true;
226 }
227
228 if ( $value === 'false' ) {
229 $value = false;
230 }
231
232 set_theme_mod( $key, $value );
233 }
234 }
235
236 if ( isset( $json['wp_options'] ) && ! empty( $json['wp_options'] ) ) {
237 foreach ( $json['wp_options'] as $key => $value ) {
238 $value = Slug_Mapping::rewrite_value( $value );
239 if ( $value === 'true' ) {
240 $value = true;
241 }
242
243 if ( $value === 'false' ) {
244 $value = false;
245 }
246 update_option( $key, $value );
247 }
248 }
249
250 // Set nav menu locations.
251 if ( isset( $json['theme_mods']['__ti_import_menus_location'] ) ) {
252 $this->theme_mods_importer->setup_nav_menus( $json['theme_mods']['__ti_import_menus_location'] );
253 }
254 \WP_CLI::success( 'Theme mods imported.' );
255 }
256
257 /**
258 * Import XML file
259 *
260 * @param string $path XML file path.
261 * @param array $json json data for site.
262 * @param string $editor page builder.
263 */
264 private function import_xml_file( $path, $json, $editor ) {
265 if ( ! file_exists( $path ) || ! is_readable( $path ) ) {
266 \WP_CLI::warning( "Cannot import XML file. Either the file is not readable or it does not exist ({$path})" );
267 }
268 $this->content_importer->import_file( $path, $json, $editor );
269 $this->content_importer->maybe_bust_elementor_cache();
270 \WP_CLI::success( 'Content imported.' );
271 }
272
273 /**
274 * Installs and activates all mandatory and recommended plugins.
275 *
276 * @param array $json_data site json data.
277 */
278 private function import_plugins_for_starter_site( $json_data ) {
279 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
280 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
281 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
282 require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
283
284 $all_plugins = array();
285
286 if ( isset( $json_data['recommended_plugins'] ) ) {
287 $all_plugins = array_merge( $all_plugins, array_keys( $json_data['recommended_plugins'] ) );
288 }
289
290 if ( isset( $json_data['mandatory_plugins'] ) ) {
291 $all_plugins = array_merge( $all_plugins, array_keys( $json_data['mandatory_plugins'] ) );
292 }
293
294 $all_plugins = array_combine( $all_plugins, $all_plugins );
295 $all_plugins = array_fill_keys( $all_plugins, true );
296
297 \WP_CLI::line( 'Installing...' );
298 \WP_CLI::print_value( $all_plugins );
299
300 $this->plugin_importer->run_plugins_install( $all_plugins );
301
302 \WP_CLI::success( 'Plugins installed and activated' );
303 }
304
305 /**
306 * Lists starter sites.
307 *
308 * ## OPTIONS
309 *
310 * [--field=<field>]
311 * : Which field to list.
312 * ---
313 * default: null
314 * options:
315 * - slug
316 * - editor
317 * - source
318 * - title
319 * - url
320 * ---
321 *
322 * [--editor=<editor>]
323 * : For which editor to list.
324 * ---
325 * default: null
326 * options:
327 * - gutenberg
328 * - elementor
329 * - beaver
330 * - brizy
331 * - divi
332 * - thrive
333 * ---
334 *
335 * [--show-url=<bool>]
336 * : Should display URLs (true / false).
337 * ---
338 * default: false
339 * options:
340 * - true
341 * - false
342 * ---
343 *
344 * ## EXAMPLES
345 *
346 * wp ti-starter-sites list --source=local --show-url=false
347 *
348 * @param array $args inline args.
349 * @param array $assoc_args associative args.
350 *
351 */
352 public function list_sites( $args, $assoc_args ) {
353 $fields = array(
354 'title',
355 'slug',
356 'editor',
357 );
358
359 if ( $assoc_args['show-url'] === 'true' ) {
360 $fields[] = 'url';
361 }
362
363 $filtered_by_editor = $assoc_args['editor'] !== null;
364
365 $sites = $filtered_by_editor ? $this->get_all_sites( $assoc_args['editor'] ) : $this->get_all_sites();
366
367 if ( $assoc_args['field'] ) {
368 if ( in_array( $assoc_args['field'], $fields, true ) ) {
369 $formatter = new \WP_CLI\Formatter( $assoc_args, null );
370 $formatter->display_items( $sites, array( $assoc_args['field'] ) );
371 } else {
372 \WP_CLI::error( 'Error' );
373 }
374
375 return;
376 }
377
378 \WP_CLI\Utils\format_items( 'table', $sites, $fields );
379 }
380
381 /**
382 * Get the starter site XML.
383 *
384 * @param array $site site data array.
385 * @param array $json site json data.
386 *
387 * @return string
388 */
389 private function get_starter_site_xml( $site, $json ) {
390 set_time_limit( 0 );
391 \WP_CLI::line( 'Saving... ' . $json['content_file'] );
392 $response_file = wp_remote_get( $json['content_file'] );
393 $content_file_path = $this->content_importer->save_xhr_return_path( wp_remote_retrieve_body( $response_file ) );
394 \WP_CLI::line( 'Saved content file in ' . $content_file_path );
395
396 return $content_file_path;
397 }
398
399 /**
400 * Get starter site JSON.
401 *
402 * @param array $site site data array.
403 *
404 * @return array
405 */
406 private function get_starter_site_json( $site ) {
407 $request = wp_remote_get( $site['url'] . 'wp-json/ti-demo-data/data' );
408 $response_code = wp_remote_retrieve_response_code( $request );
409 if ( $response_code !== 200 || empty( $request['body'] ) || ! isset( $request['body'] ) ) {
410 \WP_CLI::warning( 'Cannot get site json data.' );
411 }
412
413 $json = json_decode( $request['body'], true );
414
415 return $json;
416 }
417 }
418
419 $ti_ob_cli = new WP_Cli();
420 $ti_ob_cli->load_commands();
421