includes(); $this->maybe_upgrade_schema(); CrewCommerce_Team_Accounts::get_instance(); CrewCommerce_Approvals::get_instance(); CrewCommerce_Order_Tracking::get_instance(); CrewCommerce_Frontend_Dashboard::get_instance(); CrewCommerce_Invitations::get_instance(); CrewCommerce_Privacy::get_instance(); CrewCommerce_Admin_Dashboard::get_instance(); add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts')); add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts')); add_filter('plugin_action_links_' . plugin_basename(CREWCOMMERCE_PLUGIN_FILE), array($this, 'plugin_action_links')); /** * Fires once CrewCommerce has loaded all of its components. Add-ons * that extend CrewCommerce should hook in here. */ do_action('crewcommerce_loaded'); } /** * Create or update the tables when the schema version changes, so an * update doesn't need a reactivation. */ private function maybe_upgrade_schema() { if (get_option('crewcommerce_schema_version') === CREWCOMMERCE_SCHEMA_VERSION) { return; } $this->create_tables(); update_option('crewcommerce_schema_version', CREWCOMMERCE_SCHEMA_VERSION); } private function includes() { require_once CREWCOMMERCE_PLUGIN_DIR . 'includes/class-team-accounts.php'; require_once CREWCOMMERCE_PLUGIN_DIR . 'includes/class-approvals.php'; require_once CREWCOMMERCE_PLUGIN_DIR . 'includes/class-order-tracking.php'; require_once CREWCOMMERCE_PLUGIN_DIR . 'includes/class-frontend-dashboard.php'; require_once CREWCOMMERCE_PLUGIN_DIR . 'includes/class-invitations.php'; require_once CREWCOMMERCE_PLUGIN_DIR . 'includes/class-privacy.php'; require_once CREWCOMMERCE_PLUGIN_DIR . 'admin/admin-dashboard.php'; // Development-only demo data tool. Not shipped in the release zip, and // only loaded when both constants are set in wp-config.php. $dummy_data_file = CREWCOMMERCE_PLUGIN_DIR . 'includes/class-dummy-data.php'; if (defined('WP_DEBUG') && WP_DEBUG && defined('CREWCOMMERCE_DEV_TOOLS') && CREWCOMMERCE_DEV_TOOLS && file_exists($dummy_data_file)) { require_once $dummy_data_file; } } /** * Front-end assets, only on My Account and the order-received page. */ public function enqueue_scripts() { if (!function_exists('is_account_page') || !(is_account_page() || is_wc_endpoint_url('order-received'))) { return; } wp_enqueue_style('crewcommerce', CREWCOMMERCE_PLUGIN_URL . 'assets/css/crewcommerce.css', array(), CREWCOMMERCE_VERSION); if (!is_user_logged_in()) { return; } wp_enqueue_script('crewcommerce', CREWCOMMERCE_PLUGIN_URL . 'assets/js/crewcommerce.js', array('jquery'), CREWCOMMERCE_VERSION, true); wp_localize_script('crewcommerce', 'crewcommerce_ajax', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('crewcommerce_nonce'), 'i18n' => array( 'fill_required' => __('Please fill in all required fields.', 'crewcommerce'), 'sending' => __('Sending…', 'crewcommerce'), 'send_invitation' => __('Send Invitation', 'crewcommerce'), 'admin_demote' => __('This person is the company Admin. Changing their role hands the Admin role to someone else. Continue?', 'crewcommerce'), 'admin_transferred' => __('The Admin role was handed over. The page will reload.', 'crewcommerce'), 'confirm_remove' => __('Remove this team member?', 'crewcommerce'), 'confirm_approve' => __('Approve this order?', 'crewcommerce'), 'confirm_reject' => __('Reject this order?', 'crewcommerce'), 'reason_required' => __('Please give a reason for rejecting.', 'crewcommerce'), 'confirm_claim' => __('Claim this order? You will become responsible for approving or rejecting it.', 'crewcommerce'), 'approved' => __('Approved', 'crewcommerce'), 'rejected' => __('Rejected', 'crewcommerce'), 'waiting' => __('waiting', 'crewcommerce'), 'pending_approvals' => __('Pending Approvals', 'crewcommerce'), /* translators: %s: order number */ 'confirm_cancel' => __('Cancel the approval request for order #%s? The order will be put on hold.', 'crewcommerce'), 'cancelled' => __('Cancelled', 'crewcommerce'), 'error' => __('Something went wrong. Please try again.', 'crewcommerce'), ), )); } /** * Admin assets: CrewCommerce's own screens, plus the WooCommerce order * screens where the CrewCommerce order box appears. */ public function admin_enqueue_scripts($hook) { $screen = function_exists('get_current_screen') ? get_current_screen() : null; $order_screen = $screen && in_array($screen->id, array('shop_order', 'woocommerce_page_wc-orders', 'edit-shop_order'), true); if (strpos($hook, 'crewcommerce') === false && !$order_screen) { return; } wp_enqueue_style('crewcommerce-admin', CREWCOMMERCE_PLUGIN_URL . 'assets/css/admin.css', array(), CREWCOMMERCE_VERSION); if ($order_screen) { return; } wp_enqueue_script('crewcommerce-admin', CREWCOMMERCE_PLUGIN_URL . 'assets/js/admin.js', array('jquery'), CREWCOMMERCE_VERSION, true); wp_localize_script('crewcommerce-admin', 'crewcommerce_admin_ajax', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('crewcommerce_admin_nonce'), 'i18n' => array( 'required' => __('Required.', 'crewcommerce'), /* translators: %s: company name */ 'confirm_delete' => __('Delete “%s” and all its team memberships? This cannot be undone. Orders and customer accounts are kept.', 'crewcommerce'), 'sending' => __('Sending…', 'crewcommerce'), 'send_invitation' => __('Send Invitation', 'crewcommerce'), 'saved' => __('Saved', 'crewcommerce'), 'confirm_remove' => __('Remove this team member?', 'crewcommerce'), 'approve_notes' => __('Approval notes (optional):', 'crewcommerce'), 'reject_reason' => __('Rejection reason (required):', 'crewcommerce'), 'reason_required' => __('A rejection reason is required.', 'crewcommerce'), 'confirm_claim' => __('Claim this order? You will become responsible for approving or rejecting it.', 'crewcommerce'), ), )); } public function plugin_action_links($links) { $settings = sprintf('%s', esc_url(admin_url('admin.php?page=crewcommerce-settings')), esc_html__('Settings', 'crewcommerce')); array_unshift($links, $settings); return $links; } /** * On a multisite network activation WordPress runs this once in total, so * loop over every site. */ public function activate($network_wide = false) { if (is_multisite() && $network_wide) { foreach (get_sites(array('fields' => 'ids', 'number' => 0)) as $site_id) { switch_to_blog($site_id); $this->activate_single_site(); restore_current_blog(); } return; } $this->activate_single_site(); } private function activate_single_site() { $this->create_tables(); add_option('crewcommerce_settings', array( 'approval_threshold' => 1000, 'require_approval_roles' => array('requester'), )); add_option('crewcommerce_schema_version', CREWCOMMERCE_SCHEMA_VERSION); // 'init' has already run during activation, so let the next request // flush the rewrite rules once the endpoints are registered. delete_option('crewcommerce_endpoints_version'); flush_rewrite_rules(); } public function activate_new_site($new_site) { if (!is_multisite()) { return; } if (!function_exists('is_plugin_active_for_network')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if (!is_plugin_active_for_network(plugin_basename(CREWCOMMERCE_PLUGIN_FILE))) { return; } switch_to_blog($new_site->blog_id); $this->activate_single_site(); restore_current_blog(); } public function deactivate($network_wide = false) { if (is_multisite() && $network_wide) { foreach (get_sites(array('fields' => 'ids', 'number' => 0)) as $site_id) { switch_to_blog($site_id); delete_option('crewcommerce_endpoints_version'); restore_current_blog(); } } else { delete_option('crewcommerce_endpoints_version'); } flush_rewrite_rules(); } /** * Team memberships and approval workflows. dbDelta() only adds what is * missing, so this is safe to run on every schema upgrade. */ private function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); // spending_limit is kept on the membership row so data from earlier // versions (and the Pro add-on) stays where it was. $members = "CREATE TABLE {$wpdb->prefix}crewcommerce_team_members ( id mediumint(9) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL, company_id bigint(20) NOT NULL, role varchar(50) NOT NULL DEFAULT 'requester', permissions text, spending_limit decimal(10,2) DEFAULT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY user_company (user_id, company_id), KEY user_id (user_id), KEY company_id (company_id) ) {$charset_collate};"; $workflows = "CREATE TABLE {$wpdb->prefix}crewcommerce_approval_workflows ( id mediumint(9) NOT NULL AUTO_INCREMENT, order_id bigint(20) NOT NULL, requester_id bigint(20) NOT NULL, approver_id bigint(20), status varchar(50) NOT NULL DEFAULT 'pending', notes text, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY order_id (order_id), KEY requester_id (requester_id), KEY approver_id (approver_id) ) {$charset_collate};"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($members); dbDelta($workflows); } /** Only on the Plugins screen, for people who can act on it. */ public function woocommerce_missing_notice() { $screen = function_exists('get_current_screen') ? get_current_screen() : null; if (!$screen || 'plugins' !== $screen->id || !current_user_can('activate_plugins')) { return; } $plugin = 'woocommerce/woocommerce.php'; if (file_exists(WP_PLUGIN_DIR . '/' . $plugin)) { $message = __('CrewCommerce needs WooCommerce, which is installed but not active.', 'crewcommerce'); $label = __('Activate WooCommerce', 'crewcommerce'); $url = wp_nonce_url(admin_url('plugins.php?action=activate&plugin=' . rawurlencode($plugin)), 'activate-plugin_' . $plugin); $can = current_user_can('activate_plugin', $plugin); } else { $message = __('CrewCommerce needs WooCommerce, which is not installed.', 'crewcommerce'); $label = __('Install WooCommerce', 'crewcommerce'); $url = wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=woocommerce'), 'install-plugin_woocommerce'); $can = current_user_can('install_plugins'); } echo '

' . esc_html($message); if ($can) { echo ' ' . esc_html($label) . ''; } echo '

'; } }