PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / trunk
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). vtrunk
3.0.3 3.0.2 3.0.1 trunk 2.2.14 2.2.15 2.2.16 2.2.17 2.2.18 2.2.19 2.3.0 2.3.1 2.3.10 2.3.11 2.3.12 2.3.13 2.3.14 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.7.91 2.7.92 2.7.93 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0
commercebird / commercebird.php
commercebird Last commit date
admin 6 days ago includes 6 days ago languages 1 year ago mu-plugins 5 months ago templates 2 months ago vendor 6 days ago LICENSE 1 year ago commercebird.php 6 days ago composer.json 3 weeks ago index.php 1 year ago readme.txt 6 days ago wp-dependencies.json 1 month ago
commercebird.php
338 lines
1 <?php
2 /**
3 * Plugin Name: CommerceBird
4 * Plugin URI: https://commercebird.com
5 * Author: CommerceBird
6 * Description: This plugin helps you get the most of CommerceBird AI App and use integrations like Zoho Inventory, Zoho CRM, Exact Online and more. Requires a subscription at CommerceBird.com.
7 * Version: 3.0.3
8 * Requires PHP: 8.2
9 * Requires Plugins: woocommerce
10 * Requires at least: 7.0
11 * Tested up to: 7.0
12 * Text Domain: commercebird
13 * Domain Path: /languages
14 *
15 * License: GNU General Public License v3.0
16 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
17 *
18 * @category Fulfillment
19 * @package CommerceBird
20 * @author Fawad Tiemoerie <info@commercebird.com>
21 * @copyright Copyright (c) 2026, CommerceBird
22 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL-3.0-or-later
23 *
24 * WC requires at least: 10.7.0
25 * WC tested up to: 10.9.1
26 */
27
28 if ( ! defined( 'ABSPATH' ) ) {
29 exit; // Exit if accessed directly.
30 }
31
32 if ( ! defined( 'CMBIRD_VERSION' ) ) {
33 define( 'CMBIRD_VERSION', '3.0.3' );
34 }
35 if ( ! defined( 'CMBIRD_ZI_CATEGORY_MAP_LEGACY_FALLBACK' ) ) {
36 define( 'CMBIRD_ZI_CATEGORY_MAP_LEGACY_FALLBACK', true );
37 }
38 if ( ! defined( 'CMBIRD_PATH' ) ) {
39 define( 'CMBIRD_PATH', plugin_dir_path( __FILE__ ) );
40 }
41 if ( ! defined( 'CMBIRD_URL' ) ) {
42 define( 'CMBIRD_URL', plugin_dir_url( __FILE__ ) );
43 }
44 if ( ! defined( 'CMBIRD_MENU_SLUG' ) ) {
45 define( 'CMBIRD_MENU_SLUG', 'commercebird-app' );
46 }
47
48 require_once CMBIRD_PATH . 'includes/woo-functions.php';
49 require_once CMBIRD_PATH . 'includes/sync/order-backend.php';
50
51 // Load the Jetpack autoloader instead of vendor/autoload.php.
52 require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload_packages.php';
53
54 use Automattic\WooCommerce\Utilities\FeaturesUtil;
55 use WP\MCP\Core\McpAdapter;
56 use CommerceBird\Admin\Actions\Sync\ExactOnlineSync;
57 use CommerceBird\Admin\Actions\Ajax\ExactOnlineAjax;
58 use CommerceBird\Admin\Actions\Sync\ZohoCRMSync;
59 use CommerceBird\API\CMBird_APIs;
60 use CommerceBird\API\CreateOrderWebhook;
61 use CommerceBird\API\Exact;
62 use CommerceBird\API\ProductWebhook;
63 use CommerceBird\API\ShippingWebhook;
64 use CommerceBird\API\Zoho;
65 use CommerceBird\CMBIRD_MCP;
66 use CommerceBird\Plugin;
67
68 /*
69 |--------------------------------------------------------------------------
70 | Activation, deactivation and uninstall event.
71 |--------------------------------------------------------------------------
72 */
73
74 register_activation_hook( __FILE__, array( Plugin::class, 'activate' ) );
75 register_deactivation_hook( __FILE__, array( Plugin::class, 'deactivate' ) );
76 register_uninstall_hook( __FILE__, array( Plugin::class, 'uninstall' ) );
77
78 /*
79 |--------------------------------------------------------------------------
80 | Load the plugin translations
81 |--------------------------------------------------------------------------
82 | Note: WordPress.org automatically loads translations for plugins since WP 4.6.
83 | Manual loading not required for plugins hosted on WordPress.org.
84 */
85
86 /** Loading Purchase Order Class
87 *
88 * @since 1.0.0
89 */
90 function cmbird_purchase_order_class() {
91 if ( class_exists( 'WooCommerce' ) ) {
92 new CMBIRD_Purchase_Order();
93 }
94 }
95 add_action( 'woocommerce_init', 'cmbird_purchase_order_class' );
96 add_action( 'init', array( CMBIRD_PO_Admin_Manager::class, 'init' ), 11 );
97
98 /*
99 |--------------------------------------------------------------------------
100 | Start the plugin
101 |--------------------------------------------------------------------------
102 */
103 Plugin::init();
104
105 /**
106 * Declaring compatibility for WooCommerce HPOS
107 */
108 add_action(
109 'before_woocommerce_init',
110 function () {
111 if ( class_exists( FeaturesUtil::class ) ) {
112 FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
113 FeaturesUtil::declare_compatibility( 'product_instance_caching', __FILE__, true );
114 }
115 }
116 );
117
118 /*
119 --------------------------------------------------------------------------
120 | Install required dependencies
121 |--------------------------------------------------------------------------
122 */
123 add_action(
124 'plugins_loaded',
125 static function () {
126 // Initialize Quotes module.
127 CMBIRD_Quotes::init();
128 // Initialize MCP abilities.
129 CMBIRD_MCP::init();
130 // Only if plan is active via transient subscription_details.
131 $subscription = get_transient( 'subscription_details' );
132 // return if no subscription found.
133 if ( empty( $subscription ) ) {
134 return;
135 } else {
136 WP_Dependency_Installer::instance( __DIR__ )->run();
137 }
138 }
139 );
140
141 /**
142 * Hooks for WC Action Scheduler to import or export products
143 */
144 $cmbird_import_products = new CMBIRD_Products_ZI();
145 $cmbird_import_pricelist = new CMBIRD_Pricelist_ZI();
146 $cmbird_product_class = new CMBIRD_Products_ZI_Export();
147 $cmbird_common_class = new CMBIRD_Common_Functions();
148 $cmbird_contact_class = new CMBIRD_Contact_ZI();
149 $cmbird_category_class = new CMBIRD_Categories_ZI();
150 $cmbird_import_pricelist->wc_b2b_groups();
151 add_action( 'import_group_items_cron', array( $cmbird_import_products, 'sync_groupitem_recursively' ), 10, 2 );
152 add_action( 'import_simple_items_cron', array( $cmbird_import_products, 'sync_items_batch' ), 10, 2 );
153 add_action( 'import_variable_product_cron', array( $cmbird_import_products, 'import_variable_product_variations' ), 10, 2 );
154 add_action( 'sync_zi_product_cron', array( $cmbird_product_class, 'cmbird_zi_products_prepare_sync' ), 10, 2 );
155 add_action( 'sync_zi_pricelist', array( $cmbird_import_pricelist, 'zi_get_pricelist' ), 10, 2 );
156 add_action( 'cmbird_pricelist_addify_page', array( $cmbird_import_pricelist, 'process_addify_page' ), 10, 3 );
157 add_action( 'cmbird_pricelist_wc_b2b_page', array( $cmbird_import_pricelist, 'process_wc_b2b_page' ), 10, 3 );
158 add_action( 'sync_zi_order', array( $cmbird_common_class, 'cmbird_orders_prepare_sync' ), 10, 2 );
159 add_action( 'sync_zi_import_contacts', array( $cmbird_contact_class, 'cmbird_get_zoho_contacts' ), 10, 2 );
160 // Cascade Zoho category mapping deletion when a WC product category is deleted.
161 add_action(
162 'delete_term',
163 static function ( $term_id, $tt_id, $taxonomy ) {
164 if ( 'product_cat' !== $taxonomy ) {
165 return;
166 }
167 ( new \CommerceBird\Admin\Mappings\ZohoCategoryMap() )->forget_term( (int) $term_id );
168 },
169 10,
170 3
171 );
172 // add action to set the zoho rate limit option exceeded to false.
173 add_action( 'cmbird_common', array( CMBIRD_Common_Functions::class, 'set_zoho_rate_limit_option' ) );
174 // Zoho CRM Hooks.
175 add_action( 'sync_zcrm_order', array( $cmbird_common_class, 'cmbird_orders_prepare_sync' ) );
176 add_action( 'sync_zcrm_contact', array( ZohoCRMSync::class, 'cmbird_zcrm_contact_sync' ) );
177 // Exact Online Hooks.
178 $exact_online_sync = new ExactOnlineSync();
179 add_action( 'cmbird_sync_eo', array( $exact_online_sync, 'sync' ), 10, 3 );
180 add_action( 'cmbird_exact_online_sync_orders', array( ExactOnlineSync::class, 'sync_orders_via_cron' ) );
181 add_action( 'cmbird_payment_status', array( ExactOnlineSync::class, 'cmbird_payment_status' ), 10, 1 );
182 add_action( 'cmbird_eo_get_payment_statuses', array( ExactOnlineSync::class, 'get_payment_status_via_cron' ) );
183 add_filter( 'cron_schedules', array( ExactOnlineAjax::instance(), 'register_product_cron_schedules' ) );
184 add_action( 'cmbird_eo_product_mapping_daily', array( ExactOnlineAjax::instance(), 'product_map_cron' ) );
185 add_action( 'cmbird_eo_product_daily_reset', array( ExactOnlineAjax::instance(), 'product_map_daily_reset' ) );
186 // Callback functions for scheduled action to process product or customer chunk.
187 add_action(
188 'cmbird_process_product_chunk',
189 function ( $args ) {
190 if ( ! is_array( $args ) || empty( $args['transient_key'] ) ) {
191 return;
192 }
193 $transient_key = $args['transient_key'];
194 $import_products = $args['import_products'] ?? false;
195 $chunked_products = get_transient( $transient_key );
196 if ( $chunked_products ) {
197 $sync = new ExactOnlineSync();
198 $sync->sync( 'product', $chunked_products, (bool) $import_products );
199 // Remove transient after processing.
200 delete_transient( $transient_key );
201 }
202 },
203 10,
204 1
205 );
206 add_action(
207 'cmbird_process_customer_chunk',
208 function ( $args ) {
209 if ( ! is_array( $args ) || empty( $args['transient_key'] ) ) {
210 return;
211 }
212 $transient_key = $args['transient_key'];
213 $import_customers = $args['import_customers'] ?? false;
214 $chunked_customers = get_transient( $transient_key );
215 if ( $chunked_customers ) {
216 $sync = new ExactOnlineSync();
217 $sync->sync( 'customer', $chunked_customers, (bool) $import_customers );
218 // Remove transient after processing.
219 delete_transient( $transient_key );
220 }
221 },
222 10,
223 1
224 );
225 // Zoho CRM Hooks.
226 add_action( 'init', array( ZohoCRMSync::class, 'refresh_token' ) );
227 // Zoho Inventory Cron Hook for importing items.
228 add_action( 'zi_execute_import_sync', array( Plugin::class, 'dispatch_import_simple_items' ) );
229
230 // add classes to REST API.
231 add_action(
232 'rest_api_init',
233 function () {
234 new Zoho();
235 new Exact();
236 new ProductWebhook();
237 new ShippingWebhook();
238 new CreateOrderWebhook();
239 new CMBird_APIs();
240 $po_controller = new CMBIRD_REST_Shop_Purchase_Controller();
241 $po_controller->register_routes();
242 }
243 );
244
245 add_action(
246 'save_post',
247 function ( $post_id, $post ) {
248 if ( 'wcb2b_group' === $post->post_type ) {
249 delete_option( 'cmbird_wcb2b_groups' );
250 }
251 },
252 10,
253 2
254 );
255
256 /**
257 * Perform actions when the plugin is updated
258 *
259 * @param string $upgrader_object
260 * @param array $options
261 * @return void
262 */
263 add_action( 'upgrader_process_complete', 'cmbird_update_plugin_tasks', 10, 2 );
264
265 /**
266 * Perform tasks when the plugin is updated.
267 *
268 * @param \WP_Upgrader $upgrader_object - Upgrader object.
269 * @param array $options - Options array.
270 *
271 * @see https://developer.wordpress.org/reference/hooks/upgrader_process_complete/
272 */
273 function cmbird_update_plugin_tasks( $upgrader_object, $options ) {
274 $this_plugin = plugin_basename( __FILE__ );
275
276 if ( ! is_array( $options ) ) {
277 return;
278 }
279
280 if ( ! isset( $options['action'], $options['type'], $options['plugins'] ) || ! is_array( $options['plugins'] ) ) {
281 return;
282 }
283
284 if ( 'update' === $options['action'] && 'plugin' === $options['type'] ) {
285 foreach ( $options['plugins'] as $plugin ) {
286 if ( $plugin === $this_plugin ) {
287 // Ensure category mapping table exists before any table-backed migrations run.
288 Plugin::ensure_zi_category_map_table();
289
290 // Perform tasks when the plugin is updated.
291 // Updating meta key from '_cost_price' to '_cogs_total_value'.
292 global $wpdb;
293 $wpdb->query(
294 $wpdb->prepare(
295 "UPDATE {$wpdb->postmeta} SET meta_key = %s WHERE meta_key = %s",
296 '_cogs_total_value',
297 '_cost_price'
298 )
299 );
300 // Enable MCP WooCommerce integration. Remove this when enabled in Woo core.
301 update_option( 'woocommerce_feature_mcp_integration_enabled', 'yes' );
302 update_option( 'woocommerce_feature_cost_of_goods_sold_enabled', 'yes' );
303 update_option( 'woocommerce_feature_fulfillments_enabled', 'no' );
304 // One-time cleanup for old per-minute Zoho API rate limit counters.
305 $wpdb->query(
306 $wpdb->prepare(
307 "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
308 $wpdb->esc_like( 'cmbird_zoho_api_calls_' ) . '%'
309 )
310 );
311 break;
312 }
313 }
314 }
315
316 // One-shot migration of legacy category mapping options into the new table.
317 if ( ! get_option( 'cmbird_zi_category_map_migrated' ) ) {
318 $report = \CommerceBird\Admin\Mappings\ZohoCategoryMap::migrate_legacy_options();
319
320 if ( ! empty( $report['skipped'] ) ) {
321 set_transient( 'cmbird_zi_category_map_migration_report', $report['skipped'], DAY_IN_SECONDS );
322 }
323
324 update_option( 'cmbird_zi_category_map_migrated', '1', false );
325 }
326 }
327
328 /**
329 * Instantiate the MCP adapter. Remove this when its included in Woo core.
330 */
331 // 1. Check if MCP Adapter is available
332 if ( ! class_exists( McpAdapter::class ) ) {
333 // Handle missing dependency (show admin notice, etc.).
334 return;
335 }
336 // 2. Initialize the adapter
337 McpAdapter::instance();
338