PluginProbe
ZIP AI – AI Website Builder & AI Agent / 0.0.13
ZIP AI – AI Website Builder & AI Agent v0.0.13
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
zip-ai / loader.php

loader.php in ZIP AI – AI Website Builder & AI Agent 0.0.13, at loader.php

392 lines 12.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Class.
4 *
5 * @package zip-ai
6 * @since 1.0.0
7 */
8
9 namespace ZipAI\MCP;
10
11 // Exit if accessed directly.
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
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
22 if ( ! class_exists( '\ZipAI\MCP\Plugin' ) ) {
23 /**
24 * Plugin Class
25 *
26 * @since 1.0.0
27 */
28 class Plugin {
29
30 /**
31 * Instance
32 *
33 * @access private
34 * @var self|null Class Instance.
35 * @since 1.0.0
36 */
37 private static $instance;
38
39 /**
40 * The dependency injection container.
41 *
42 * @var Container
43 */
44 protected $container;
45
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;
64 }
65
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' ) );
75
76 $this->container = new Container();
77
78 $this->define_constants();
79
80 // Register Services.
81 $this->register_services();
82
83 // Boot Services.
84 add_action( 'plugins_loaded', array( $this, 'boot_services' ), 5 );
85
86 $this->setup_activation_hooks();
87
88 // Site scanner — event-driven memory enrichment (after auth).
89 // \ZipAI\MCP\Classes\Core\Site_Scanner::register_hooks(); // TODO: class not yet committed.
90
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();
95
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();
101
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 // AOS hover handover — after a scroll entrance, an element's own hover eases again.
124 \ZipAI\MCP\Classes\Core\Aos_Hover_Handover::init();
125
126 // Privacy policy disclosure (WordPress Guideline 7).
127 add_action( 'admin_init', array( $this, 'add_privacy_policy_content' ) );
128 }
129
130 /**
131 * Plugin autoloader — single runtime autoloader for everything the
132 * plugin ships: its own classes (inc/) and the bundled
133 * composer-managed libraries in lib/ (mcp-adapter, php-mcp-schema).
134 * Composer's vendor/autoload.php is dev-tooling only and is never
135 * loaded at runtime.
136 *
137 * @param string $class Fully qualified class name to load.
138 * @return void
139 */
140 public static function autoload( string $class ): void {
141 // Own classes — WordPress-style file names: namespace path
142 // lowercased, CamelCase split with hyphens, underscores as hyphens.
143 // ZipAI\MCP\Classes\Abilities\Core\RunWpCli -> inc/abilities/core/run-wp-cli.php.
144 $own_prefix = 'ZipAI\MCP\Classes\\';
145 if ( 0 === strpos( $class, $own_prefix ) ) {
146 $filename = preg_replace(
147 array( '/([a-z])([A-Z])/', '/_/', '/\\\\/' ),
148 array( '$1-$2', '-', '/' ),
149 substr( $class, strlen( $own_prefix ) )
150 );
151
152 if ( is_string( $filename ) ) {
153 $file = __DIR__ . '/inc/' . strtolower( $filename ) . '.php';
154
155 if ( is_readable( $file ) ) {
156 require_once $file; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- Path is derived from the class name.
157 }
158 }
159 return;
160 }
161
162 // Bundled lib/ packages — strict PSR-4, directory case preserved.
163 $psr4 = array(
164 'WP\MCP\\' => 'lib/mcp-adapter/includes/',
165 'WP\McpSchema\\' => 'lib/php-mcp-schema/src/',
166 );
167
168 foreach ( $psr4 as $prefix => $base_dir ) {
169 if ( 0 === strpos( $class, $prefix ) ) {
170 $file = __DIR__ . '/' . $base_dir . str_replace( '\\', '/', substr( $class, strlen( $prefix ) ) ) . '.php';
171
172 if ( is_readable( $file ) ) {
173 require_once $file; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- Path is derived from a fixed prefix map.
174 }
175 return;
176 }
177 }
178 }
179
180 /**
181 * Register Service Providers.
182 *
183 * @return void
184 */
185 private function register_services() {
186 $this->providers[] = new Core_Service_Provider( $this->container );
187 $this->providers[] = new Abilities_Service_Provider( $this->container );
188
189 foreach ( $this->providers as $provider ) {
190 $provider->register();
191 }
192 }
193
194 /**
195 * Boot Service Providers.
196 *
197 * @return void
198 */
199 public function boot_services() {
200 $this->load_vendor_dependencies();
201
202 foreach ( $this->providers as $provider ) {
203 $provider->boot();
204 }
205 }
206
207 /**
208 * Define the required constants.
209 *
210 * @since 1.0.0
211 * @return void
212 */
213 public function define_constants() {
214 define( 'ZIPAI_MCP_FILE', __DIR__ . '/zip-ai.php' );
215 define( 'ZIPAI_MCP_DIR', plugin_dir_path( ZIPAI_MCP_FILE ) );
216 define( 'ZIPAI_MCP_URL', plugins_url( '/', ZIPAI_MCP_FILE ) );
217 define( 'ZIPAI_MCP_VERSION', '0.0.13' );
218 define( 'ZIPAI_MCP_MENU_SLUG', 'zip-ai' );
219
220 // Base URL for ZIP AI credit server.
221 if ( ! defined( 'ZIPAI_MCP_BASE_URL' ) ) {
222 define( 'ZIPAI_MCP_BASE_URL', 'https://credits.zipwp.com' );
223 }
224
225 if ( ! defined( 'ZIPAI_MCP_MIDDLEWARE' ) ) {
226 define( 'ZIPAI_MCP_MIDDLEWARE', 'https://app.zipwp.com/auth/' );
227 }
228
229 if ( ! defined( 'ZIPAI_API_BASE' ) ) {
230 define( 'ZIPAI_API_BASE', 'https://api.zipwp.com/api/' );
231 }
232
233 // Base URL for direct server calls (e.g. inline-edit). Override via
234 // wp-config.php or the `zipai_brain_url` filter.
235 if ( ! defined( 'ZIPAI_BRAIN_URL' ) ) {
236 define( 'ZIPAI_BRAIN_URL', 'https://brain.zipwp.com' );
237 }
238
239 // API endpoint for credit server.
240 if ( ! defined( 'ZIPAI_MCP_CREDIT_SERVER_API' ) ) {
241 define( 'ZIPAI_MCP_CREDIT_SERVER_API', ZIPAI_MCP_BASE_URL . '/api/' );
242 }
243 }
244
245 /**
246 * Load bundled dependencies (mcp-adapter).
247 *
248 * @since 1.0.0
249 * @return void
250 */
251 private function load_vendor_dependencies() {
252 // Initialize mcp-adapter plugin if not already loaded. It is vendored
253 // in lib/mcp-adapter (git-committed) and its classes are served by the
254 // plugin autoloader (Plugin::autoload). The library self-bootstraps
255 // (defines its own constants, runs its autoloader and calls
256 // \WP\MCP\Plugin::instance()) on require, and its self-autoload expects
257 // a nested vendor/ it doesn't have — so we tell it to skip it, else it
258 // prints a false "Composer autoloader was not found" admin notice and
259 // bails before Plugin::instance().
260 if ( ! defined( 'WP_MCP_AUTOLOAD' ) ) {
261 define( 'WP_MCP_AUTOLOAD', false );
262 }
263 if ( ! defined( 'WP_MCP_VERSION' ) && file_exists( ZIPAI_MCP_DIR . 'lib/mcp-adapter/mcp-adapter.php' ) ) {
264 require_once ZIPAI_MCP_DIR . 'lib/mcp-adapter/mcp-adapter.php';
265 }
266 }
267
268 /**
269 * Setup plugin activation and deactivation hooks.
270 *
271 * @since 1.0.0
272 * @return void
273 */
274 public function setup_activation_hooks() {
275 register_activation_hook( ZIPAI_MCP_FILE, array( $this, 'plugin_activated' ) );
276 register_deactivation_hook( ZIPAI_MCP_FILE, array( $this, 'plugin_deactivated' ) );
277 }
278
279 /**
280 * Plugin activation callback.
281 *
282 * @since 1.0.0
283 * @return void
284 */
285 public function plugin_activated() {
286 // Add the required capability to administrator role.
287 $this->add_plugin_capabilities();
288 }
289
290 /**
291 * Plugin deactivation callback.
292 *
293 * @since 1.0.0
294 * @return void
295 */
296 public function plugin_deactivated() {
297 // Remove the plugin capabilities from all roles.
298 $this->remove_plugin_capabilities();
299
300 // Clear scheduled site scan.
301 \ZipAI\MCP\Classes\Core\Site_Scanner::unschedule();
302 }
303
304 /**
305 * Suggest privacy policy content per WordPress Guideline 7.
306 *
307 * Discloses what data is sent to the ZIP AI cloud service.
308 *
309 * @since 1.0.0
310 * @return void
311 */
312 public function add_privacy_policy_content() {
313 $policy_text = '<h2>ZIP AI Assistant</h2>
314 <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>
315
316 <h3>What data is collected</h3>
317 <p>When authenticated and actively using ZIP AI, the following data may be sent to our servers:</p>
318 <ul>
319 <li><strong>Chat messages</strong> — Messages you send to the AI assistant and the assistant\'s responses.</li>
320 <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>
321 <li><strong>Site identity</strong> — Site title, tagline, language, and domain name.</li>
322 <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>
323 </ul>
324
325 <h3>What data is NOT collected</h3>
326 <ul>
327 <li>Page or post content/body text</li>
328 <li>Customer or visitor personal information</li>
329 <li>Passwords, payment details, or financial data</li>
330 <li>Email addresses of site visitors</li>
331 <li>Analytics or traffic data</li>
332 </ul>
333
334 <h3>How data is used</h3>
335 <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>
336
337 <h3>Data retention</h3>
338 <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>
339
340 <h3>Third-party services</h3>
341 <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>
342 <ul>
343 <li><a href="https://policies.google.com/privacy">Google Privacy Policy</a></li>
344 <li><a href="https://www.anthropic.com/privacy">Anthropic Privacy Policy</a></li>
345 </ul>
346
347 <p>For more information, please see our <a href="https://developer.brainstormforce.com/privacy-policy/">Privacy Policy</a>.</p>';
348
349 wp_add_privacy_policy_content( 'ZIP AI Assistant', $policy_text );
350 }
351
352 /**
353 * Add required capabilities to administrator role.
354 *
355 * @since 1.0.0
356 * @return void
357 */
358 private function add_plugin_capabilities() {
359 // Get the administrator role.
360 $admin_role = get_role( 'administrator' );
361
362 if ( $admin_role ) {
363 // Add the required capability for ZipWP MCP management.
364 $admin_role->add_cap( 'manage_zip_mcp_assistant', true );
365 }
366 }
367
368 /**
369 * Remove plugin capabilities from all roles.
370 *
371 * @since 1.0.0
372 * @return void
373 */
374 private function remove_plugin_capabilities() {
375 // Get all roles.
376 $roles = wp_roles();
377
378 // Remove the capability from all roles that have it.
379 foreach ( $roles->role_objects as $role ) {
380 if ( $role->has_cap( 'manage_zip_mcp_assistant' ) ) {
381 $role->remove_cap( 'manage_zip_mcp_assistant' );
382 }
383 }
384 }
385 }
386
387 /**
388 * Kicking this off by calling 'get_instance()' method
389 */
390 Plugin::get_instance();
391 }
392