PluginProbe
ZIP AI – AI Website Builder & AI Agent / 0.0.12
ZIP AI – AI Website Builder & AI Agent v0.0.12
0.0.13 0.0.12 0.0.11 0.0.10 0.0.9 trunk 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8
← All changes | loader.php +298 -222 0.0.4 → 0.0.12 View file →
@@ -2,12 +2,12 @@
2 2 /**
3 3 * Plugin Class.
4 4 *
5 5 * @package zip-ai
6 - * @since 0.0.1
6 + * @since 1.0.0
7 7 */
8 8
9 -namespace ZipAI;
9 +namespace ZipAI\MCP;
10 10
11 11 // Exit if accessed directly.
12 12 if ( ! defined( 'ABSPATH' ) ) {
13 13 exit;
@@ -12,221 +12,310 @@
12 12 if ( ! defined( 'ABSPATH' ) ) {
13 13 exit;
14 14 }
15 15
16 -use ZipAI\Classes\Core\Container;
17 -use ZipAI\Classes\Providers\Core_Service_Provider;
18 -use ZipAI\Classes\Providers\Abilities_Service_Provider;
19 -use ZipAI\Classes\Cli\CLI_Commands;
20 -use ZipAI\Classes\Core\Helper;
16 +use ZipAI\MCP\Classes\Core\Container;
17 +use ZipAI\MCP\Classes\Providers\Core_Service_Provider;
18 +use ZipAI\MCP\Classes\Providers\Abilities_Service_Provider;
19 +use ZipAI\MCP\Classes\Core\Helper;
20 +use ZipAI\MCP\Classes\Core\Service_Provider;
21 21
22 -/**
23 - * Plugin Class
24 - *
25 - * @since 0.0.1
26 - */
27 -class Plugin {
28 -
22 +if ( ! class_exists( '\ZipAI\MCP\Plugin' ) ) {
29 23 /**
30 - * Instance
24 + * Plugin Class
31 25 *
32 - * @access private
33 - * @var object Class Instance.
34 - * @since 0.0.1
26 + * @since 1.0.0
35 27 */
36 - private static $instance;
28 + class Plugin {
37 29
38 - /**
39 - * The dependency injection container.
40 - *
41 - * @var Container
42 - */
43 - protected $container;
30 + /**
31 + * Instance
32 + *
33 + * @access private
34 + * @var self|null Class Instance.
35 + * @since 1.0.0
36 + */
37 + private static $instance;
44 38
45 - /**
46 - * Service Providers.
47 - *
48 - * @var array
49 - */
50 - protected $providers = array();
39 + /**
40 + * The dependency injection container.
41 + *
42 + * @var Container
43 + */
44 + protected $container;
51 45
52 - /**
53 - * Initiator
54 - *
55 - * @since 0.0.1
56 - * @return object initialized object of class.
57 - */
58 - public static function get_instance() {
59 - if ( ! isset( self::$instance ) ) {
60 - self::$instance = new self();
46 + /**
47 + * Service Providers.
48 + *
49 + * @var array<int, Service_Provider>
50 + */
51 + protected $providers = array();
52 +
53 + /**
54 + * Initiator
55 + *
56 + * @since 1.0.0
57 + * @return object initialized object of class.
58 + */
59 + public static function get_instance() {
60 + if ( ! isset( self::$instance ) ) {
61 + self::$instance = new self();
62 + }
63 + return self::$instance;
61 64 }
62 - return self::$instance;
63 - }
64 65
65 - /**
66 - * Constructor
67 - *
68 - * @since 0.0.1
69 - */
70 - public function __construct() {
71 - $this->container = new Container();
66 + /**
67 + * Constructor
68 + *
69 + * @since 1.0.0
70 + */
71 + public function __construct() {
72 + // Must be first — everything below (Container included) autoloads
73 + // through it.
74 + spl_autoload_register( array( __CLASS__, 'autoload' ) );
72 75
73 - $this->define_constants();
74 -
75 - // Register Services.
76 - $this->register_services();
76 + $this->container = new Container();
77 77
78 - // Boot Services.
79 - add_action( 'plugins_loaded', array( $this, 'boot_services' ), 5 );
78 + $this->define_constants();
79 +
80 + // Register Services.
81 + $this->register_services();
80 82
81 - $this->setup_activation_hooks();
82 - $this->register_cli_commands();
83 + // Boot Services.
84 + add_action( 'plugins_loaded', array( $this, 'boot_services' ), 5 );
83 85
84 - // Translations: WordPress.org auto-loads the plugin text domain
85 - // on-demand since 4.6, so we no longer call
86 - // `load_plugin_textdomain()` explicitly. Shipped `.pot` lives in
87 - // `/languages/zip-ai.pot`; `.mo` files are delivered by
88 - // GlotPress via the standard plugin update channel.
86 + $this->setup_activation_hooks();
89 87
90 - // Site scanner — event-driven memory enrichment (after auth).
91 - // \ZipAI\Classes\Core\Site_Scanner::register_hooks(); // TODO: class not yet committed.
88 + // Site scanner — event-driven memory enrichment (after auth).
89 + // \ZipAI\MCP\Classes\Core\Site_Scanner::register_hooks(); // TODO: class not yet committed.
92 90
93 - // Privacy policy disclosure (WordPress Guideline 7).
94 - add_action( 'admin_init', array( $this, 'add_privacy_policy_content' ) );
95 - }
91 + // Code snippet executor — runs AI-created snippets (PHP/JS/CSS/HTML).
92 + // This is the ONLY persistent hook needed — it auto-loads all snippets
93 + // created by any tool (cookie consent, tracking codes, custom CSS, etc.)
94 + \ZipAI\MCP\Classes\Core\Snippet_Executor::init();
96 95
97 - /**
98 - * Register Service Providers.
99 - */
100 - private function register_services() {
101 - $this->providers[] = new Core_Service_Provider( $this->container );
102 - $this->providers[] = new Abilities_Service_Provider( $this->container );
96 + // Plugin abilities toggler — listens for `activated_plugin` and
97 + // enables MCP abilities for mapped slugs regardless of activation
98 + // path (server-side ability, browser-proxied REST, admin UI,
99 + // WP-CLI). Idempotent + slug-map gated.
100 + \ZipAI\MCP\Classes\Core\Plugin_Abilities_Toggler::init();
103 101
104 - foreach ( $this->providers as $provider ) {
105 - $provider->register();
102 + // Abilities input normalizer — lets the chat call no-input readonly
103 + // abilities over the browser Abilities run-route (GET can't carry a
104 + // JSON object, so a schema without a top-level `default` — e.g. Astra's
105 + // typography abilities — would 400 "input is not of type object").
106 + \ZipAI\MCP\Classes\Core\Abilities_Input_Normalizer::init();
107 +
108 + // Imported-chrome reader — renders imported header/footer template
109 + // parts verbatim on ANY classic theme via a `template_include`
110 + // canvas takeover when `zipai_chrome_mode === 'takeover'` (written
111 + // by the importer) or a page carries the standalone marker meta.
112 + // Inert on block themes (FSE renders the parts natively) and on
113 + // sites that never imported. Registering the option doubles as the
114 + // backend's capability probe.
115 + \ZipAI\MCP\Classes\Core\Imported_Chrome::init();
116 +
117 + // Site blueprint — the plan the site was built from; never autoloads.
118 + \ZipAI\MCP\Classes\Core\Site_Blueprint::init();
119 +
120 + // JSON-LD — the build's schema.org blocks, printed in `<head>`.
121 + \ZipAI\MCP\Classes\Core\Json_Ld::init();
122 +
123 + // Privacy policy disclosure (WordPress Guideline 7).
124 + add_action( 'admin_init', array( $this, 'add_privacy_policy_content' ) );
106 125 }
107 - }
108 126
109 - /**
110 - * Boot Service Providers.
111 - */
112 - public function boot_services() {
113 - $this->load_vendor_dependencies();
127 + /**
128 + * Plugin autoloader — single runtime autoloader for everything the
129 + * plugin ships: its own classes (inc/) and the bundled
130 + * composer-managed libraries in lib/ (mcp-adapter, php-mcp-schema).
131 + * Composer's vendor/autoload.php is dev-tooling only and is never
132 + * loaded at runtime.
133 + *
134 + * @param string $class Fully qualified class name to load.
135 + * @return void
136 + */
137 + public static function autoload( string $class ): void {
138 + // Own classes — WordPress-style file names: namespace path
139 + // lowercased, CamelCase split with hyphens, underscores as hyphens.
140 + // ZipAI\MCP\Classes\Abilities\Core\RunWpCli -> inc/abilities/core/run-wp-cli.php.
141 + $own_prefix = 'ZipAI\MCP\Classes\\';
142 + if ( 0 === strpos( $class, $own_prefix ) ) {
143 + $filename = preg_replace(
144 + array( '/([a-z])([A-Z])/', '/_/', '/\\\\/' ),
145 + array( '$1-$2', '-', '/' ),
146 + substr( $class, strlen( $own_prefix ) )
147 + );
114 148
115 - foreach ( $this->providers as $provider ) {
116 - $provider->boot();
149 + if ( is_string( $filename ) ) {
150 + $file = __DIR__ . '/inc/' . strtolower( $filename ) . '.php';
151 +
152 + if ( is_readable( $file ) ) {
153 + require_once $file; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- Path is derived from the class name.
154 + }
155 + }
156 + return;
157 + }
158 +
159 + // Bundled lib/ packages — strict PSR-4, directory case preserved.
160 + $psr4 = array(
161 + 'WP\MCP\\' => 'lib/mcp-adapter/includes/',
162 + 'WP\McpSchema\\' => 'lib/php-mcp-schema/src/',
163 + );
164 +
165 + foreach ( $psr4 as $prefix => $base_dir ) {
166 + if ( 0 === strpos( $class, $prefix ) ) {
167 + $file = __DIR__ . '/' . $base_dir . str_replace( '\\', '/', substr( $class, strlen( $prefix ) ) ) . '.php';
168 +
169 + if ( is_readable( $file ) ) {
170 + require_once $file; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- Path is derived from a fixed prefix map.
171 + }
172 + return;
173 + }
174 + }
117 175 }
118 - }
119 176
120 - /**
121 - * Define the required constants.
122 - *
123 - * @since 0.0.1
124 - * @return void
125 - */
126 - public function define_constants() {
127 - define( 'ZIP_AI_FILE', __DIR__ . '/zip-ai.php' );
128 - define( 'ZIP_AI_DIR', plugin_dir_path( ZIP_AI_FILE ) );
129 - define( 'ZIP_AI_URL', plugins_url( '/', ZIP_AI_FILE ) );
130 - define( 'ZIP_AI_VERSION', '0.0.4' );
131 - define( 'ZIP_AI_MENU_SLUG', 'zip-ai' );
177 + /**
178 + * Register Service Providers.
179 + *
180 + * @return void
181 + */
182 + private function register_services() {
183 + $this->providers[] = new Core_Service_Provider( $this->container );
184 + $this->providers[] = new Abilities_Service_Provider( $this->container );
132 185
133 - // Base URL for Zip AI credit server (Laravel app).
134 - if ( ! defined( 'ZIP_AI_BASE_URL' ) ) {
135 - define( 'ZIP_AI_BASE_URL', 'https://credits.startertemplates.com' );
186 + foreach ( $this->providers as $provider ) {
187 + $provider->register();
188 + }
136 189 }
137 190
138 - if ( ! defined( 'ZIP_AI_MIDDLEWARE' ) ) {
139 - define( 'ZIP_AI_MIDDLEWARE', 'https://app.zipwp.com/auth/' );
191 + /**
192 + * Boot Service Providers.
193 + *
194 + * @return void
195 + */
196 + public function boot_services() {
197 + $this->load_vendor_dependencies();
198 +
199 + foreach ( $this->providers as $provider ) {
200 + $provider->boot();
201 + }
140 202 }
141 203
142 - if ( ! defined( 'ZIP_AI_API_BASE' ) ) {
143 - define( 'ZIP_AI_API_BASE', 'https://api.zipwp.com/api/' );
204 + /**
205 + * Define the required constants.
206 + *
207 + * @since 1.0.0
208 + * @return void
209 + */
210 + public function define_constants() {
211 + define( 'ZIPAI_MCP_FILE', __DIR__ . '/zip-ai.php' );
212 + define( 'ZIPAI_MCP_DIR', plugin_dir_path( ZIPAI_MCP_FILE ) );
213 + define( 'ZIPAI_MCP_URL', plugins_url( '/', ZIPAI_MCP_FILE ) );
214 + define( 'ZIPAI_MCP_VERSION', '0.0.12' );
215 + define( 'ZIPAI_MCP_MENU_SLUG', 'zip-ai' );
216 +
217 + // Base URL for ZIP AI credit server.
218 + if ( ! defined( 'ZIPAI_MCP_BASE_URL' ) ) {
219 + define( 'ZIPAI_MCP_BASE_URL', 'https://credits.zipwp.com' );
220 + }
221 +
222 + if ( ! defined( 'ZIPAI_MCP_MIDDLEWARE' ) ) {
223 + define( 'ZIPAI_MCP_MIDDLEWARE', 'https://app.zipwp.com/auth/' );
224 + }
225 +
226 + if ( ! defined( 'ZIPAI_API_BASE' ) ) {
227 + define( 'ZIPAI_API_BASE', 'https://api.zipwp.com/api/' );
228 + }
229 +
230 + // Base URL for direct server calls (e.g. inline-edit). Override via
231 + // wp-config.php or the `zipai_brain_url` filter.
232 + if ( ! defined( 'ZIPAI_BRAIN_URL' ) ) {
233 + define( 'ZIPAI_BRAIN_URL', 'https://brain.zipwp.com' );
234 + }
235 +
236 + // API endpoint for credit server.
237 + if ( ! defined( 'ZIPAI_MCP_CREDIT_SERVER_API' ) ) {
238 + define( 'ZIPAI_MCP_CREDIT_SERVER_API', ZIPAI_MCP_BASE_URL . '/api/' );
239 + }
144 240 }
145 241
146 - // API endpoint for credit server.
147 - if ( ! defined( 'ZIP_AI_CREDIT_SERVER_API' ) ) {
148 - define( 'ZIP_AI_CREDIT_SERVER_API', ZIP_AI_BASE_URL . '/api/' );
242 + /**
243 + * Load bundled dependencies (mcp-adapter).
244 + *
245 + * @since 1.0.0
246 + * @return void
247 + */
248 + private function load_vendor_dependencies() {
249 + // Initialize mcp-adapter plugin if not already loaded. It is vendored
250 + // in lib/mcp-adapter (git-committed) and its classes are served by the
251 + // plugin autoloader (Plugin::autoload). The library self-bootstraps
252 + // (defines its own constants, runs its autoloader and calls
253 + // \WP\MCP\Plugin::instance()) on require, and its self-autoload expects
254 + // a nested vendor/ it doesn't have — so we tell it to skip it, else it
255 + // prints a false "Composer autoloader was not found" admin notice and
256 + // bails before Plugin::instance().
257 + if ( ! defined( 'WP_MCP_AUTOLOAD' ) ) {
258 + define( 'WP_MCP_AUTOLOAD', false );
259 + }
260 + if ( ! defined( 'WP_MCP_VERSION' ) && file_exists( ZIPAI_MCP_DIR . 'lib/mcp-adapter/mcp-adapter.php' ) ) {
261 + require_once ZIPAI_MCP_DIR . 'lib/mcp-adapter/mcp-adapter.php';
262 + }
149 263 }
150 - }
151 264
152 - /**
153 - * Load vendor dependencies (mcp-adapter).
154 - *
155 - * @since 0.0.1
156 - * @return void
157 - */
158 - private function load_vendor_dependencies() {
159 - // Boot the upstream `wordpress/mcp-adapter` library directly via its
160 - // Plugin singleton. We skip its own `mcp-adapter.php` bootstrap because
161 - // that file (a) defines `WP_MCP_*` constants that conflict with the
162 - // reserved `WP_` prefix and (b) runs its own Autoloader which expects a
163 - // nested `vendor/autoload.php` that does not exist after Composer
164 - // flattens dependencies. Our parent classmap (composer.json) already
165 - // includes every `\WP\MCP\*` class via PSR-4, so calling
166 - // `Plugin::instance()` triggers the library's setup directly.
167 - if ( class_exists( \WP\MCP\Plugin::class ) ) {
168 - \WP\MCP\Plugin::instance();
265 + /**
266 + * Setup plugin activation and deactivation hooks.
267 + *
268 + * @since 1.0.0
269 + * @return void
270 + */
271 + public function setup_activation_hooks() {
272 + register_activation_hook( ZIPAI_MCP_FILE, array( $this, 'plugin_activated' ) );
273 + register_deactivation_hook( ZIPAI_MCP_FILE, array( $this, 'plugin_deactivated' ) );
169 274 }
170 - }
171 275
172 - /**
173 - * Setup plugin activation and deactivation hooks.
174 - *
175 - * @since 0.0.1
176 - * @return void
177 - */
178 - public function setup_activation_hooks() {
179 - register_activation_hook( ZIP_AI_FILE, array( $this, 'plugin_activated' ) );
180 - register_deactivation_hook( ZIP_AI_FILE, array( $this, 'plugin_deactivated' ) );
181 - }
276 + /**
277 + * Plugin activation callback.
278 + *
279 + * @since 1.0.0
280 + * @return void
281 + */
282 + public function plugin_activated() {
283 + // Add the required capability to administrator role.
284 + $this->add_plugin_capabilities();
285 + }
182 286
183 - /**
184 - * Plugin activation callback.
185 - *
186 - * @since 0.0.1
187 - * @return void
188 - */
189 - public function plugin_activated() {
190 - // Add the required capability to administrator role.
191 - // HMAC shared-secret registration with the remote credit server is
192 - // deferred until the user explicitly authenticates (see
193 - // AJAX_Handlers::zip_ai_save_auth_settings). Nothing is sent to any
194 - // external service on activation.
195 - $this->add_plugin_capabilities();
196 - }
287 + /**
288 + * Plugin deactivation callback.
289 + *
290 + * @since 1.0.0
291 + * @return void
292 + */
293 + public function plugin_deactivated() {
294 + // Remove the plugin capabilities from all roles.
295 + $this->remove_plugin_capabilities();
197 296
198 - /**
199 - * Plugin deactivation callback.
200 - *
201 - * @since 0.0.1
202 - * @return void
203 - */
204 - public function plugin_deactivated() {
205 - // Remove the plugin capabilities from all roles.
206 - $this->remove_plugin_capabilities();
297 + // Clear scheduled site scan.
298 + \ZipAI\MCP\Classes\Core\Site_Scanner::unschedule();
299 + }
207 300
208 - // Clear scheduled site scan.
209 - \ZipAI\Classes\Core\Site_Scanner::unschedule();
210 - }
301 + /**
302 + * Suggest privacy policy content per WordPress Guideline 7.
303 + *
304 + * Discloses what data is sent to the ZIP AI cloud service.
305 + *
306 + * @since 1.0.0
307 + * @return void
308 + */
309 + public function add_privacy_policy_content() {
310 + $policy_text = '<h2>ZIP AI Assistant</h2>
311 +<p>This site uses the ZIP AI Assistant plugin ("ZIP AI"), which connects to a cloud-based AI service operated by Starter Templates (Starter Templates, a Brainstorm Force product).</p>
211 312
212 - /**
213 - * Suggest privacy policy content per WordPress Guideline 7.
214 - *
215 - * Discloses what data is sent to the Zip AI SaaS platform.
216 - *
217 - * @since 0.0.1
218 - * @return void
219 - */
220 - public function add_privacy_policy_content() {
221 - $policy_text = '<h2>Zip AI</h2>
222 -<p>This site uses the Zip AI plugin, which connects to a cloud-based AI service operated by Starter Templates (Starter Templates, a Brainstorm Force product).</p>
223 -
224 313 <h3>What data is collected</h3>
225 -<p>When authenticated and actively using Zip AI, the following data may be sent to our servers:</p>
314 +<p>When authenticated and actively using ZIP AI, the following data may be sent to our servers:</p>
226 315 <ul>
227 316 <li><strong>Chat messages</strong> — Messages you send to the AI assistant and the assistant\'s responses.</li>
228 -<li><strong>Site structure data</strong> — Page titles, post counts, active plugin names, active theme name, and content categories. This helps Zip AI understand your site and provide relevant suggestions.</li>
317 +<li><strong>Site structure data</strong> — Page titles, post counts, active plugin names, active theme name, and content categories. This helps ZIP AI understand your site and provide relevant suggestions.</li>
229 318 <li><strong>Site identity</strong> — Site title, tagline, language, and domain name.</li>
230 319 <li><strong>E-commerce data</strong> (if applicable) — Product counts, product categories, currency, and whether reviews are enabled. No individual product details, prices, or customer data is sent.</li>
231 320 </ul>
232 321
@@ -239,74 +328,61 @@
239 328 <li>Analytics or traffic data</li>
240 329 </ul>
241 330
242 331 <h3>How data is used</h3>
243 -<p>Data is used solely to power the AI assistant\'s responses and to build a memory of your site preferences so you don\'t have to repeat yourself across conversations. You can clear all stored memory at any time via the "Clear Site Memory" option in the Zip AI menu.</p>
332 +<p>Data is used solely to power the AI assistant\'s responses and to build a memory of your site preferences so you don\'t have to repeat yourself across conversations. You can clear all stored memory at any time via the "Clear Site Memory" option in the ZIP AI menu.</p>
244 333
245 334 <h3>Data retention</h3>
246 335 <p>Chat messages and memory data are stored on our servers for as long as your account is active. You can request deletion at any time by clearing your site memory or contacting support.</p>
247 336
248 337 <h3>Third-party services</h3>
249 -<p>Zip AI uses AI language models (such as Google Gemini and Anthropic Claude) to process your messages. Your messages may be sent to these providers for processing. Please refer to their respective privacy policies:</p>
338 +<p>ZIP AI uses AI language models (such as Google Gemini and Anthropic Claude) to process your messages. Your messages may be sent to these providers for processing. Please refer to their respective privacy policies:</p>
250 339 <ul>
251 340 <li><a href="https://policies.google.com/privacy">Google Privacy Policy</a></li>
252 341 <li><a href="https://www.anthropic.com/privacy">Anthropic Privacy Policy</a></li>
253 342 </ul>
254 343
255 -<p>For more information, please see our <a href="https://store.brainstormforce.com/privacy-policy/">Privacy Policy</a>.</p>';
344 +<p>For more information, please see our <a href="https://developer.brainstormforce.com/privacy-policy/">Privacy Policy</a>.</p>';
256 345
257 - wp_add_privacy_policy_content( 'Zip AI', $policy_text );
258 - }
346 + wp_add_privacy_policy_content( 'ZIP AI Assistant', $policy_text );
347 + }
259 348
260 - /**
261 - * Add required capabilities to administrator role.
262 - *
263 - * @since 0.0.1
264 - * @return void
265 - */
266 - private function add_plugin_capabilities() {
267 - // Get the administrator role.
268 - $admin_role = get_role( 'administrator' );
349 + /**
350 + * Add required capabilities to administrator role.
351 + *
352 + * @since 1.0.0
353 + * @return void
354 + */
355 + private function add_plugin_capabilities() {
356 + // Get the administrator role.
357 + $admin_role = get_role( 'administrator' );
269 358
270 - if ( $admin_role ) {
271 - // Add the required capability for ZipWP MCP management.
272 - $admin_role->add_cap( 'manage_zip_ai_assistant', true );
359 + if ( $admin_role ) {
360 + // Add the required capability for ZipWP MCP management.
361 + $admin_role->add_cap( 'manage_zip_mcp_assistant', true );
362 + }
273 363 }
274 - }
275 364
276 - /**
277 - * Remove plugin capabilities from all roles.
278 - *
279 - * @since 0.0.1
280 - * @return void
281 - */
282 - private function remove_plugin_capabilities() {
283 - // Get all roles.
284 - $roles = wp_roles();
365 + /**
366 + * Remove plugin capabilities from all roles.
367 + *
368 + * @since 1.0.0
369 + * @return void
370 + */
371 + private function remove_plugin_capabilities() {
372 + // Get all roles.
373 + $roles = wp_roles();
285 374
286 - // Remove the capability from all roles that have it.
287 - foreach ( $roles->role_objects as $role ) {
288 - if ( $role->has_cap( 'manage_zip_ai_assistant' ) ) {
289 - $role->remove_cap( 'manage_zip_ai_assistant' );
375 + // Remove the capability from all roles that have it.
376 + foreach ( $roles->role_objects as $role ) {
377 + if ( $role->has_cap( 'manage_zip_mcp_assistant' ) ) {
378 + $role->remove_cap( 'manage_zip_mcp_assistant' );
379 + }
290 380 }
291 381 }
292 382 }
293 383
294 384 /**
295 - * Register WP-CLI commands.
296 - *
297 - * @since 0.0.1
298 - * @return void
385 + * Kicking this off by calling 'get_instance()' method
299 386 */
300 - private function register_cli_commands() {
301 - if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
302 - return;
303 - }
304 -
305 - \WP_CLI::add_command( 'zip-ai', CLI_Commands::class );
306 - }
387 + Plugin::get_instance();
307 388 }
308 -
309 -/**
310 - * Kicking this off by calling 'get_instance()' method
311 - */
312 -Plugin::get_instance();