PluginProbe
wePOS – Point Of Sale (POS) for WooCommerce & Dokan / trunk
wePOS – Point Of Sale (POS) for WooCommerce & Dokan vtrunk
2.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.10 1.1.11 1.1.12 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 All 36 releases
wepos / wepos.php

wepos.php in wePOS – Point Of Sale (POS) for WooCommerce & Dokan trunk, at wepos.php

542 lines 15.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: wePOS - Point Of Sale (POS) for WooCommerce & Dokan
4 Plugin URI: https://wedevs.com/wepos
5 Description: A beautiful and fast Point of Sale (POS) system for WooCommerce & Dokan
6 Version: 2.0.1
7 Author: weDevs
8 Author URI: https://wedevs.com/
9 Text Domain: wepos
10 Requires Plugins: woocommerce
11 Domain Path: /languages
12 WC requires at least: 10.5.0
13 WC tested up to: 10.7.0
14 License: GPL2
15 License URI: https://www.gnu.org/licenses/gpl-2.0.html
16 */
17
18 /**
19 * Copyright (c) YEAR weDevs (email: info@wedevs.com). All rights reserved.
20 *
21 * Released under the GPL license
22 * http://www.opensource.org/licenses/gpl-license.php
23 *
24 * This is an add-on for WordPress
25 * http://wordpress.org/
26 *
27 * **********************************************************************
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 2 of the License, or
31 * (at your option) any later version.
32 *
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
41 * **********************************************************************
42 */
43
44 // don't call the file directly
45 if ( ! defined( 'ABSPATH' ) ) {
46 exit;
47 }
48
49 /**
50 * wePOS class
51 *
52 * @class wePOS The class that holds the entire wePOS plugin
53 */
54 final class WePOS {
55
56 /**
57 * Plugin version
58 *
59 * @var string
60 */
61 public $version = '2.0.1';
62
63 /**
64 * Holds various class instances
65 *
66 * @var array
67 */
68 private $container = [];
69
70 /**
71 * Constructor for the wePOS class
72 *
73 * Sets up all the appropriate hooks and actions
74 * within our plugin.
75 */
76 public function __construct() {
77 require_once __DIR__ . '/vendor/autoload.php';
78
79 $this->define_constants();
80 $this->includes();
81
82 register_activation_hook( __FILE__, [ $this, 'activate' ] );
83 register_deactivation_hook( __FILE__, [ $this, 'deactivate' ] );
84
85 add_action( 'init', [ $this, 'add_rewrite_rules' ] );
86 add_filter( 'query_vars', [ $this, 'register_query_var' ] );
87
88 // Declaring High Performance Order Storage Support
89 add_action( 'before_woocommerce_init', [ $this, 'declare_woocommerce_feature_compatibility' ] );
90
91 add_action( 'plugins_loaded', [ $this, 'woocommerce_not_loaded' ], 11 );
92
93 // Admin notice for WooCommerce dependency
94 add_action( 'admin_notices', [ $this, 'render_woocommerce_dependency_notice' ] );
95
96 add_action( 'woocommerce_loaded', [ $this, 'init_plugin' ] );
97 add_action( 'woocommerce_init', [ $this, 'on_wc_init' ] );
98
99
100 // Handle Appsero tracker
101 $this->appsero_init_tracker_wepos();
102 }
103
104 /**
105 * Missing WooCommerce notice
106 *
107 * @since 1.1.9
108 *
109 * @return void
110 */
111 public function render_woocommerce_dependency_notice() {
112 // Check wooCommerce is available and active
113 $has_woocommerce = $this->has_woocommerce();
114
115 if ( $has_woocommerce ) {
116 return;
117 }
118
119 // Check if woocommerce installed
120 $woocommerce_installed = $this->is_woocommerce_installed();
121
122 if ( current_user_can( 'activate_plugins' ) ) {
123 require_once WEPOS_PATH . '/templates/woocommerce-dependency-notice.php';
124 }
125 }
126
127 /**
128 * Add High Performance Order Storage Support
129 *
130 * @since 1.3.1
131 * @see https://developer.woocommerce.com/docs/hpos-extension-recipe-book/
132 *
133 * @return void
134 */
135 public function declare_woocommerce_feature_compatibility() {
136 if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
137 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', WEPOS_FILE, true );
138 }
139 }
140
141 /**
142 * Handles scenarios when WooCommerce is not active
143 *
144 * @since 1.1.9
145 *
146 * @return void
147 */
148 public function woocommerce_not_loaded() {
149 if ( did_action( 'woocommerce_loaded' ) || ! is_admin() ) {
150 return;
151 }
152 }
153
154 /**
155 * Check whether woocommerce is installed and active
156 *
157 * @since 1.1.9
158 *
159 * @return bool
160 */
161 public function has_woocommerce() {
162 return class_exists( 'WooCommerce' );
163 }
164
165 /**
166 * Check whether woocommerce is installed
167 *
168 * @since 1.1.9
169 *
170 * @return bool
171 */
172 public function is_woocommerce_installed() {
173 return in_array( 'woocommerce/woocommerce.php', array_keys( get_plugins() ), true );
174 }
175
176 /**
177 * Get the template path.
178 *
179 * @since 1.1.9
180 *
181 * @return string
182 */
183 public function template_path() {
184 return apply_filters( 'wepos_template_path', 'wepos/' );
185 }
186
187 /**
188 * Add the required rewrite rules
189 *
190 * @return void
191 */
192 public function add_rewrite_rules() {
193 add_rewrite_rule( '^wepos/?$', 'index.php?wepos=true', 'top' );
194
195 if ( get_transient( 'wepos-flush-rewrites' ) ) {
196 flush_rewrite_rules( true );
197 delete_transient( 'wepos-flush-rewrites' );
198 }
199 }
200
201 /**
202 * Register our query vars
203 *
204 * @param array $vars
205 *
206 * @return array
207 */
208 public function register_query_var( $vars ) {
209 $vars[] = 'wepos';
210
211 return $vars;
212 }
213
214 /**
215 * Initializes the wePOS() class
216 *
217 * Checks for an existing wePOS() instance
218 * and if it doesn't find one, creates it.
219 *
220 * @return \WePOS
221 */
222 public static function init() {
223 static $instance = false;
224
225 if ( ! $instance ) {
226 $instance = new WePOS();
227 }
228
229 return $instance;
230 }
231
232 /**
233 * Magic getter to bypass referencing plugin.
234 *
235 * @param $prop
236 *
237 * @return mixed
238 */
239 public function __get( $prop ) {
240 if ( array_key_exists( $prop, $this->container ) ) {
241 return $this->container[ $prop ];
242 }
243
244 return $this->{$prop};
245 }
246
247 /**
248 * Magic isset to bypass referencing plugin.
249 *
250 * @param $prop
251 *
252 * @return mixed
253 */
254 public function __isset( $prop ) {
255 return isset( $this->{$prop} ) || isset( $this->container[ $prop ] );
256 }
257
258 /**
259 * Define the constants
260 *
261 * @return void
262 */
263 public function define_constants() {
264 define( 'WEPOS_VERSION', $this->version );
265 define( 'WEPOS_FILE', __FILE__ );
266 define( 'WEPOS_PATH', dirname( WEPOS_FILE ) );
267 define( 'WEPOS_INCLUDES', WEPOS_PATH . '/includes' );
268 define( 'WEPOS_URL', plugins_url( '', WEPOS_FILE ) );
269 define( 'WEPOS_ASSETS', WEPOS_URL . '/assets' );
270 }
271
272 /**
273 * Load the plugin after all plugins are loaded
274 *
275 * @return void
276 */
277 public function init_plugin() {
278 // Manual unzip/file-replacement updates bypass activation hooks, so
279 // backfill default role capabilities here as a safe, idempotent sync.
280 $installer = new WeDevs\WePOS\Installer();
281 $installer->maybe_sync_capabilities();
282
283 $this->init_hooks();
284
285 do_action( 'wepos_loaded' );
286 }
287
288 /**
289 * Placeholder for activation function
290 *
291 * Nothing being called here yet.
292 *
293 * @return void
294 */
295 public function activate() {
296 $installer = new WeDevs\WePOS\Installer();
297
298 $installer->run();
299 }
300
301 /**
302 * Placeholder for deactivation function
303 *
304 * Nothing being called here yet.
305 *
306 * @return void
307 */
308 public function deactivate() {
309 // Remove wepos capabilities from roles that received them on activation
310 $roles_to_clean = [ 'administrator', 'shop_manager', 'editor' ];
311 foreach ( $roles_to_clean as $role_slug ) {
312 $role = get_role( $role_slug );
313 if ( $role ) {
314 $role->remove_cap( 'access_wepos' );
315 $role->remove_cap( 'manage_wepos' );
316 }
317 }
318
319 // Legacy Dokan cleanup
320 $users_query = new WP_User_Query( [
321 'role__in' => [ 'seller', 'vendor_staff' ]
322 ] );
323 $users = $users_query->get_results();
324
325 if ( count( $users ) > 0 ) {
326 foreach ( $users as $user ) {
327 $user->remove_cap( 'publish_shop_orders' );
328 $user->remove_cap( 'list_users' );
329 }
330 }
331 }
332
333 /**
334 * Include the required files
335 *
336 * @return void
337 */
338 public function includes() {
339 require_once WEPOS_INCLUDES . '/functions.php';
340 }
341
342 /**
343 * Initialize the hooks
344 *
345 * @return void
346 */
347 public function init_hooks() {
348 add_action( 'init', [ $this, 'init_classes' ] );
349 add_action( 'init', [ $this, 'localization_setup' ] );
350 add_action( 'wepos_loaded', [ $this, 'load_payment_gateways' ] );
351 }
352
353 /**
354 * Instantiate the required classes
355 *
356 * @return void
357 */
358 public function init_classes() {
359 if (is_admin()) {
360 $this->container['admin'] = new WeDevs\WePOS\Admin\Admin();
361 $this->container['settings'] = new WeDevs\WePOS\Admin\Settings();
362 $this->container['dashboard'] = new WeDevs\WePOS\Admin\Dashboard();
363 $this->container['appearance'] = new WeDevs\WePOS\Admin\Appearance();
364
365 new WeDevs\WePOS\Admin\Products();
366 new WeDevs\WePOS\Admin\Updates();
367 new WeDevs\WePOS\Admin\LimitedTimePromotion();
368 new WeDevs\WePOS\Admin\Discounts();
369 } else {
370 $this->container['frontend'] = new WeDevs\WePOS\Frontend();
371 }
372
373 if ( class_exists( 'WeDevs_Dokan' ) ) {
374 $this->container['dokan'] = new WeDevs\WePOS\Dokan();
375 }
376
377 $this->container['common'] = new WeDevs\WePOS\Common();
378 $this->container['rest'] = new WeDevs\WePOS\REST\Manager();
379
380 // Use React assets instead of Vue.js assets
381 $layout_style = wepos_get_option( 'pos_layout_style', 'wepos_appearance', 'latest' );
382
383 if (is_admin()) {
384 $this->container['assets'] = new WeDevs\WePOS\Assets();
385 } else {
386 if ('latest' === $layout_style) {
387 $this->container['assets'] = new WeDevs\WePOS\ReactAssets();
388 } else {
389 $this->container['assets'] = new WeDevs\WePOS\Assets();
390
391 // Register the shared React components handle even when the
392 // legacy Vue frontend is active. Extensions (e.g. wepos-pro)
393 // may still enqueue their own React bundles that declare
394 // `wepos-react-components` as a dependency — without this
395 // registration WP_Scripts logs "called incorrectly" notices.
396 add_action( 'wepos_enqueue_scripts', [ $this, 'register_shared_react_handle' ], 5 );
397 }
398 }
399 }
400
401 /**
402 * Register the shared wepos-react-components script handle on the
403 * frontend so extensions that depend on it can enqueue cleanly even
404 * when the legacy Vue UI is the primary renderer.
405 *
406 * @return void
407 */
408 public function register_shared_react_handle() {
409 if ( wp_script_is( 'wepos-react-components', 'registered' ) ) {
410 return;
411 }
412
413 $asset_file = WEPOS_PATH . '/build/wepos-components.asset.php';
414 $script_file = WEPOS_PATH . '/build/wepos-components.js';
415
416 if ( ! file_exists( $script_file ) ) {
417 return;
418 }
419
420 $asset_data = file_exists( $asset_file ) ? include $asset_file : [ 'dependencies' => [], 'version' => WEPOS_VERSION ];
421
422 wp_register_script(
423 'wepos-react-components',
424 WEPOS_URL . '/build/wepos-components.js',
425 isset( $asset_data['dependencies'] ) ? $asset_data['dependencies'] : [],
426 isset( $asset_data['version'] ) ? $asset_data['version'] : WEPOS_VERSION,
427 true
428 );
429 }
430
431 /**
432 * Initialize plugin for localization
433 *
434 * @uses load_plugin_textdomain()
435 */
436 public function localization_setup() {
437 load_plugin_textdomain( 'wepos', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
438 }
439
440 /**
441 * Load the payment gateways.
442 *
443 * @since 1.3.1
444 *
445 * @return void
446 */
447 public function load_payment_gateways() {
448 // Payment gateway manager
449 $this->container['gateways'] = new \WeDevs\WePOS\Gateways\Manager();
450 }
451
452 /**
453 * On WC init, include cart required files in REST request
454 *
455 * @since 1.0.5
456 *
457 * @return void
458 */
459 public function on_wc_init() {
460 if ( wc()->is_rest_api_request() ) {
461 $namespace = '/wepos/v1/';
462
463 $rest_bases = [
464 'products',
465 ];
466
467 foreach ( $rest_bases as $rest_base ) {
468 $endpoint = $namespace . $rest_base;
469
470 if ( strpos( $_SERVER['REQUEST_URI'], $endpoint ) ) {
471 $this->include_wc_files();
472 break;
473 }
474 }
475 }
476 }
477
478 /**
479 * Initialize the plugin tracker
480 *
481 * @return void
482 */
483 public function appsero_init_tracker_wepos() {
484 if ( ! class_exists( 'WeDevs\WePOS\Dependencies\Appsero\Client' ) ) {
485 return;
486 }
487
488 $client = new WeDevs\WePOS\Dependencies\Appsero\Client( '48fa1273-3e91-4cd6-9c07-d18ad6bc2f54', 'wePos', __FILE__ );
489
490 // Active insights
491 $client->insights()
492 ->add_extra( function () {
493 $products = wc_get_products( [ 'fields' => 'ids', 'paginate' => true ] );
494 $orders = wc_get_orders( [ 'fields' => 'ids', 'paginate' => true ] );
495
496 return [
497 'products' => $products->total,
498 'orders' => $orders->total
499 ];
500 } )
501 ->init();
502 }
503
504 /**
505 * Include cart required files in REST request
506 *
507 * @since 1.0.5
508 *
509 * @return void
510 */
511 public function include_wc_files() {
512 if ( ! wc()->cart ) {
513 include_once WC_ABSPATH . 'includes/wc-cart-functions.php';
514 include_once WC_ABSPATH . 'includes/wc-notice-functions.php';
515 include_once WC_ABSPATH . 'includes/class-wc-cart.php';
516 include_once WC_ABSPATH . 'includes/class-wc-tax.php';
517 include_once WC_ABSPATH . 'includes/class-wc-shipping-zones.php';
518 include_once WC_ABSPATH . 'includes/class-wc-customer.php';
519 include_once WC_ABSPATH . 'includes/class-wc-session-handler.php';
520
521 // Session class, handles session data for users - can be overwritten if custom handler is needed.
522 $session_class = apply_filters( 'woocommerce_session_handler', 'WC_Session_Handler' );
523 wc()->session = new $session_class();
524 wc()->session->init();
525
526 wc()->customer = new WC_Customer( get_current_user_id(), true );
527 // Cart needs the customer info.
528 wc()->cart = new WC_Cart();
529
530 // Customer should be saved during shutdown.
531 add_action( 'shutdown', [ wc()->customer, 'save' ], 10 );
532 }
533 }
534 } // wePOS
535
536 function wepos() {
537 return WePOS::init();
538 }
539
540 // Kick off plugin
541 wepos();
542