PageRenderTime 77ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/wc-aelia-foundation-classes/src/lib/classes/base/plugin/aelia-plugin.php

https://bitbucket.org/sunny_rawat/generation-clay
PHP | 924 lines | 405 code | 112 blank | 407 comment | 56 complexity | 393ce9aea0827b130b47898cfaf09374 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, Apache-2.0
  1. <?php
  2. namespace Aelia\WC;
  3. if(!defined('ABSPATH')) exit; // Exit if accessed directly
  4. use \ReflectionClass;
  5. use \Exception;
  6. use \WC_Admin_Reports;
  7. if(!class_exists('Aelia\WC\Aelia_Plugin')) {
  8. interface IAelia_Plugin {
  9. public function settings_controller();
  10. public function messages_controller();
  11. public static function instance();
  12. public static function settings();
  13. public function setup();
  14. public static function cleanup();
  15. }
  16. // Load general functions file
  17. require_once('general_functions.php');
  18. /**
  19. * Implements a base plugin class to be used to implement WooCommerce plugins.
  20. */
  21. class Aelia_Plugin implements IAelia_Plugin {
  22. // @var string The plugin version.
  23. public static $version = '0.1.0';
  24. // @var string The plugin slug
  25. public static $plugin_slug = 'wc-aelia-plugin';
  26. // @var string The plugin text domain
  27. public static $text_domain = 'wc-aelia-plugin';
  28. // @var string The plugin name
  29. public static $plugin_name = 'wc-aelia-plugin';
  30. // @var string The folder and file name of the main plugin file. This may
  31. // not be the same file where the main plugin class is located, as many
  32. // plugin use the main file as a simple loader.
  33. public $main_plugin_file;
  34. // @var string The base name of the plugin directory
  35. protected $plugin_directory;
  36. // @var Aelia\WC\Settings The object that will handle plugin's settings.
  37. protected $_settings_controller;
  38. // @var Aelia\WC\Messages The object that will handle plugin's messages.
  39. protected $_messages_controller;
  40. // @var Aelia_SessionManager The session manager
  41. protected $_session;
  42. // @var Settings The instances of the settings controllers used by the various plugins. Used for caching.
  43. protected static $_settings = array();
  44. // @var bool Indicates if the setup process of the plugin is running
  45. protected $running_setup = false;
  46. protected $paths = array(
  47. // This array will contain the paths used by the plugin
  48. );
  49. protected $urls = array(
  50. // This array will contain the URLs used by the plugin
  51. );
  52. // @var Aelia\WC\Logger The logger used by the class.
  53. protected $logger;
  54. // @var string The class name to use as a prefix for log messages.
  55. protected $class_for_log = '';
  56. /**
  57. * Returns the class name to use as a prefix for log messages.
  58. *
  59. * @return string
  60. * @since 1.6.1.150728
  61. */
  62. protected function get_class_for_log() {
  63. if(empty($this->class_for_log)) {
  64. $reflection = new \ReflectionClass($this);
  65. $this->class_for_log = $reflection->getShortName();
  66. }
  67. return $this->class_for_log;
  68. }
  69. /**
  70. * Logs a message.
  71. *
  72. * @param string message The message to log.
  73. * @param bool debug Indicates if the message is for debugging. Debug messages
  74. * are not saved if the "debug mode" flag is turned off.
  75. */
  76. public function log($message, $debug = true) {
  77. // Prefix message with the class name, for easier identification
  78. $message = sprintf('[%s] %s',
  79. $this->get_class_for_log(),
  80. $message);
  81. $this->get_logger()->log($message, $debug);
  82. }
  83. /**
  84. * Returns the instance of the logger used by the plugin.
  85. *
  86. * @return \Aelia\WC\Logger.
  87. * @since 1.6.1.150728
  88. */
  89. public function get_logger() {
  90. if(empty($this->logger)) {
  91. $this->logger = new Logger(static::$plugin_slug);
  92. }
  93. return $this->logger;
  94. }
  95. /**
  96. * Returns the URL to use to check for plugin updates.
  97. *
  98. * @param string plugin_slug The plugin slug.
  99. * @return string
  100. */
  101. protected function get_update_url($plugin_slug) {
  102. return 'http://wpupdate.aelia.co?action=get_metadata&slug=' . $plugin_slug;
  103. }
  104. /**
  105. * Checks for plugin updates.
  106. */
  107. public function check_for_updates($plugin_file, $plugin_slug = null) {
  108. if(empty($plugin_slug)) {
  109. $plugin_slug = static::$plugin_slug;
  110. }
  111. // Debug
  112. //var_dump($this->path('vendor') . '/yahnis-elsts/plugin-update-checker/plugin-update-checker.php');die();
  113. require_once(WC_AeliaFoundationClasses::instance()->path('vendor') . '/yahnis-elsts/plugin-update-checker/plugin-update-checker.php');
  114. $MyUpdateChecker = \PucFactory::buildUpdateChecker(
  115. $this->get_update_url($plugin_slug),
  116. $plugin_file,
  117. $plugin_slug
  118. );
  119. }
  120. /**
  121. * Returns global instance of WooCommerce.
  122. *
  123. * @return object The global instance of WooCommerce.
  124. */
  125. protected function wc() {
  126. return wc();
  127. }
  128. /**
  129. * Returns the session manager.
  130. *
  131. * @return Aelia_SessionManager The session manager instance.
  132. */
  133. protected function session() {
  134. if(empty($this->_session)) {
  135. $this->_session = new Aelia_SessionManager();
  136. }
  137. return $this->_session;
  138. }
  139. /**
  140. * Returns the instance of the Settings Controller used by the plugin.
  141. *
  142. * @return Aelia_Settings.
  143. */
  144. public function settings_controller() {
  145. return $this->_settings_controller;
  146. }
  147. /**
  148. * Returns the instance of the Messages Controller used by the plugin.
  149. *
  150. * @return Aelia_Messages.
  151. */
  152. public function messages_controller() {
  153. return $this->_messages_controller;
  154. }
  155. /**
  156. * Returns the instance of the plugin.
  157. *
  158. * @return Aelia_Plugin.
  159. */
  160. public static function instance() {
  161. return $GLOBALS[static::$plugin_slug];
  162. }
  163. /**
  164. * Returns the plugin path.
  165. *
  166. * @return string
  167. */
  168. public static function plugin_path() {
  169. $reflection_class = new ReflectionClass(get_called_class());
  170. return dirname($reflection_class->getFileName());
  171. }
  172. /**
  173. * Returns the Settings Controller used by the plugin.
  174. *
  175. * @return Aelia\WC\Settings.
  176. */
  177. public static function settings() {
  178. return self::$_settings[static::$plugin_slug];
  179. }
  180. /**
  181. * Returns the Messages Controller used by the plugin.
  182. *
  183. * @return Aelia\WC\Messages.
  184. */
  185. public static function messages() {
  186. return self::instance()->messages_controller();
  187. }
  188. /**
  189. * Retrieves an error message from the internal Messages object.
  190. *
  191. * @param mixed error_code The Error Code.
  192. * @return string The Error Message corresponding to the specified Code.
  193. */
  194. public function get_error_message($error_code) {
  195. return $this->_messages_controller->get_error_message($error_code);
  196. }
  197. /**
  198. * Indicates if current visitor is a bot.
  199. *
  200. * @return bool
  201. * @since 1.5.6.150402
  202. */
  203. protected static function visitor_is_bot() {
  204. $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
  205. $bot_types = 'bot|crawl|slurp|spider';
  206. $result = !empty($user_agent) ? preg_match("/$bot_types/", $user_agent) > 0 : false;
  207. return apply_filters('wc_aelia_visitor_is_bot', $result);
  208. }
  209. /**
  210. * Ensures that the WooCommerce session is initialised. The method implements
  211. * checks to prevent redundant initialisations, in order to improve
  212. * performances.
  213. */
  214. public static function init_woocommerce_session() {
  215. /* WooCommerce 2.1+ - Initialise session, if needed. WooCommerce 2.0
  216. * and earlier initialise the session automatically as startup.
  217. */
  218. if(version_compare(wc()->version, '2.1', '>=')) {
  219. // If WooCommerce session was not initialised, start it
  220. if(!Aelia_SessionManager::has_session()) {
  221. // Only start the session if the visitor is not a bot
  222. if(!self::visitor_is_bot()) {
  223. // Initialise the session only if the visitor is not a bot. Bots don't use
  224. // sessions and don't benefit from them, anyway
  225. do_action('woocommerce_set_cart_cookies', true);
  226. }
  227. }
  228. }
  229. }
  230. /**
  231. * Triggers an error displaying the message associated to an error code.
  232. *
  233. * @param mixed error_code The Error Code.
  234. * @param int error_type The type of Error to raise.
  235. * @param array error_args An array of arguments to pass to the vsprintf()
  236. * function which will format the error message.
  237. * @param bool show_backtrace Indicates if a backtrace should be displayed
  238. * after the error message.
  239. * @return string The formatted error message.
  240. */
  241. public function trigger_error($error_code, $error_type = E_USER_NOTICE, array $error_args = array(), $show_backtrace = false) {
  242. $error_message = $this->get_error_message($error_code);
  243. $message = vsprintf($error_message, $error_args);
  244. if($show_backtrace) {
  245. $e = new Exception();
  246. $backtrace = $e->getTraceAsString();
  247. $message .= " \n" . $backtrace;
  248. }
  249. return trigger_error($message, $error_type);
  250. }
  251. /**
  252. * Sets the hook handlers for WC and WordPress.
  253. */
  254. protected function set_hooks() {
  255. add_action('init', array($this, 'wordpress_loaded'));
  256. add_action('admin_init', array($this, 'run_updates'));
  257. // Called after all plugins have loaded
  258. add_action('plugins_loaded', array($this, 'plugins_loaded'));
  259. add_action('woocommerce_init', array($this, 'woocommerce_loaded'), 1);
  260. add_action('admin_enqueue_scripts', array($this, 'load_admin_scripts'));
  261. add_action('wp_enqueue_scripts', array($this, 'load_frontend_scripts'));
  262. // Register Widgets
  263. add_action('widgets_init', array($this, 'register_widgets'));
  264. // Ajax
  265. $ajax_action = $this->ajax_action();
  266. if(!empty($ajax_action)) {
  267. add_action('wp_ajax_' . $ajax_action, array($this, 'aelia_ajax_request'));
  268. }
  269. $nopriv_ajax_action = $this->nopriv_ajax_action();
  270. if(!empty($nopriv_ajax_action)) {
  271. add_action('wp_ajax_nopriv_' . $nopriv_ajax_action, array($this, 'aelia_ajax_request'));
  272. }
  273. // Automatic updates
  274. add_filter('aelia_register_plugins_to_update', array($this, 'aelia_register_plugins_to_update'), 10, 1);
  275. }
  276. /**
  277. * Returns the full path corresponding to the specified key.
  278. *
  279. * @param key The path key.
  280. * @return string
  281. */
  282. public function path($key) {
  283. return isset($this->paths[$key]) ? $this->paths[$key] : '';
  284. }
  285. /**
  286. * Builds and stores the paths used by the plugin.
  287. */
  288. protected function set_paths() {
  289. $this->paths['plugin'] = WP_PLUGIN_DIR . '/' . $this->plugin_dir() . '/src';
  290. $this->paths['languages'] = WP_PLUGIN_DIR . '/' . $this->plugin_dir() . '/languages';
  291. $this->paths['languages_rel'] = $this->plugin_dir() . '/languages';
  292. $this->paths['lib'] = $this->path('plugin') . '/lib';
  293. $this->paths['views'] = $this->path('plugin') . '/views';
  294. $this->paths['admin_views'] = $this->path('views') . '/admin';
  295. $this->paths['classes'] = $this->path('lib') . '/classes';
  296. $this->paths['widgets'] = $this->path('classes') . '/widgets';
  297. $this->paths['vendor'] = $this->path('plugin') . '/vendor';
  298. $this->paths['design'] = $this->path('plugin') . '/design';
  299. $this->paths['css'] = $this->path('design') . '/css';
  300. $this->paths['images'] = $this->path('design') . '/images';
  301. $this->paths['js'] = $this->path('plugin') . '/js';
  302. $this->paths['js_admin'] = $this->path('js') . '/admin';
  303. $this->paths['js_frontend'] = $this->path('js') . '/frontend';
  304. }
  305. /**
  306. * Builds and stores the URLs used by the plugin.
  307. */
  308. protected function set_urls() {
  309. $this->urls['plugin'] = plugins_url() . '/' . $this->plugin_dir() . '/src';
  310. $this->urls['design'] = $this->url('plugin') . '/design';
  311. $this->urls['css'] = $this->url('design') . '/css';
  312. $this->urls['images'] = $this->url('design') . '/images';
  313. $this->urls['js'] = $this->url('plugin') . '/js';
  314. $this->urls['js_admin'] = $this->url('js') . '/admin';
  315. $this->urls['js_frontend'] = $this->url('js') . '/frontend';
  316. }
  317. /**
  318. * Returns the URL corresponding to the specified key.
  319. *
  320. * @param key The URL key.
  321. * @return string
  322. */
  323. public function url($key) {
  324. return isset($this->urls[$key]) ? $this->urls[$key] : '';
  325. }
  326. /**
  327. * Returns the directory in which the plugin is stored. Only the base name of
  328. * the directory is returned (i.e. without path).
  329. *
  330. * @return string
  331. */
  332. public function plugin_dir() {
  333. if(empty($this->plugin_directory)) {
  334. $reflector = new ReflectionClass($this);
  335. $this->plugin_directory = basename(dirname(dirname($reflector->getFileName())));
  336. }
  337. return $this->plugin_directory;
  338. }
  339. /**
  340. * Constructor.
  341. *
  342. * @param Aelia\WC\Settings settings_controller The controller that will handle
  343. * the plugin settings.
  344. * @param Aelia\WC\Messages messages_controller The controller that will handle
  345. * the messages produced by the plugin.
  346. */
  347. public function __construct($settings_controller = null, $messages_controller = null) {
  348. // Set plugin's paths
  349. $this->set_paths();
  350. // Set plugin's URLs
  351. $this->set_urls();
  352. $this->_settings_controller = $settings_controller;
  353. $this->_messages_controller = empty($messages_controller) ? new Messages : $messages_controller;
  354. // Set all required hooks
  355. $this->set_hooks();
  356. // indicates we are running the admin
  357. if(is_admin()) {
  358. // ...
  359. }
  360. // indicates we are being served over ssl
  361. if(is_ssl()) {
  362. // ...
  363. }
  364. // Store the settings controller in a cache, for better performance
  365. // @since 1.6.10.151105
  366. if(!is_array(self::$_settings)) {
  367. self::$_settings = array();
  368. }
  369. self::$_settings[static::$plugin_slug] = $settings_controller;
  370. // Set schedules, if needed
  371. $this->set_cron_schedules();
  372. }
  373. /**
  374. * Run the updates required by the plugin. This method runs at every load, but
  375. * the updates are executed only once. This allows the plugin to run the
  376. * updates automatically, without requiring deactivation and rectivation.
  377. *
  378. * @return bool
  379. */
  380. public function run_updates() {
  381. // Run updates only when in Admin area. This should occur automatically
  382. // when plugin is activated, since it's done in the Admin area. Updates
  383. // are also NOT executed during Ajax calls
  384. if(!is_admin() || self::doing_ajax()) {
  385. return;
  386. }
  387. $installer_class = get_class($this) . '_Install';
  388. if(!class_exists($installer_class)) {
  389. return;
  390. }
  391. $installer = new $installer_class();
  392. return $installer->update(static::$plugin_slug, static::$version);
  393. }
  394. /**
  395. * Returns an instance of the class. This method should be implemented by
  396. * descendant classes to return a pre-configured instance of the plugin class,
  397. * complete with the appropriate settings controller.
  398. *
  399. * @return Aelia\WC\Aelia_Plugin
  400. * @throws Aelia\WC\NotImplementedException
  401. */
  402. public static function factory() {
  403. throw new NotImplementedException();
  404. }
  405. /**
  406. * Take care of anything that needs to be done as soon as WordPress finished
  407. * loading.
  408. */
  409. public function wordpress_loaded() {
  410. if(!is_admin()) {
  411. $this->register_common_frontend_scripts();
  412. }
  413. }
  414. /**
  415. * Performs operation when all plugins have been loaded.
  416. */
  417. public function plugins_loaded() {
  418. load_plugin_textdomain(static::$text_domain, false, $this->path('languages_rel') . '/');
  419. }
  420. /**
  421. * Performs operation when woocommerce has been loaded.
  422. */
  423. public function woocommerce_loaded() {
  424. // To be implemented by descendant classes
  425. }
  426. /**
  427. * Registers all the Widgets used by the plugin.
  428. */
  429. public function register_widgets() {
  430. // Register the required widgets
  431. //$this->register_widget('Aelia\WC\Template_Widget');
  432. }
  433. /**
  434. * Determines if one of plugin's admin pages is being rendered. Override it
  435. * if plugin implements pages in the Admin section.
  436. *
  437. * @return bool
  438. */
  439. protected function rendering_plugin_admin_page() {
  440. return false;
  441. }
  442. /**
  443. * Registers the script and style files required in the backend (even outside
  444. * of plugin's pages). Extend in descendant plugins.
  445. */
  446. protected function register_common_admin_scripts() {
  447. // Dummy
  448. }
  449. /**
  450. * Registers the script and style files needed by the admin pages of the
  451. * plugin. Extend in descendant plugins.
  452. */
  453. protected function register_plugin_admin_scripts() {
  454. // Admin scripts
  455. wp_register_script(static::$plugin_slug . '-admin',
  456. $this->url('plugin') . '/js/admin/admin.js',
  457. array('jquery'),
  458. null,
  459. false);
  460. // Admin styles
  461. wp_register_style(static::$plugin_slug . '-admin',
  462. $this->url('plugin') . '/design/css/admin.css',
  463. array(),
  464. null,
  465. 'all');
  466. }
  467. /**
  468. * Registers the script and style files required in the frontend (even outside
  469. * of plugin's pages).
  470. */
  471. protected function register_common_frontend_scripts() {
  472. // Scripts
  473. wp_register_script(static::$plugin_slug . '-frontend',
  474. $this->url('plugin') . '/js/frontend/frontend.js',
  475. array('jquery'),
  476. null,
  477. true);
  478. // Styles
  479. wp_register_style(static::$plugin_slug . '-frontend',
  480. $this->url('plugin') . '/design/css/frontend.css',
  481. array(),
  482. null,
  483. 'all');
  484. }
  485. /**
  486. * Loads Styles and JavaScript for the Admin pages.
  487. */
  488. public function load_admin_scripts() {
  489. // Register common JS for the backend
  490. $this->register_common_admin_scripts();
  491. if($this->rendering_plugin_admin_page()) {
  492. // Load Admin scripts only on plugin settings page
  493. $this->register_plugin_admin_scripts();
  494. // Styles - Enqueue styles required for plugin Admin page
  495. wp_enqueue_style(static::$plugin_slug . '-admin');
  496. // JavaScript - Enqueue scripts required for plugin Admin page
  497. // Enqueue the required Admin scripts
  498. wp_enqueue_script(static::$plugin_slug . '-admin');
  499. }
  500. }
  501. /**
  502. * Loads Styles and JavaScript for the frontend. Extend as needed in
  503. * descendant classes.
  504. */
  505. public function load_frontend_scripts() {
  506. // Enqueue the required Frontend stylesheets
  507. //wp_enqueue_style(static::$plugin_slug . '-frontend');
  508. // JavaScript
  509. //wp_enqueue_script(static::$plugin_slug . '-frontend');
  510. }
  511. /**
  512. * Returns the full path and file name of the specified template, if such file
  513. * exists.
  514. *
  515. * @param string template_name The name of the template.
  516. * @return string
  517. */
  518. public function get_template_file($template_name) {
  519. $template = '';
  520. /* Look for the following:
  521. * - yourtheme/{plugin_slug}-{template_name}.php
  522. * - yourtheme/{plugin_slug}/{template_name}.php
  523. */
  524. $template = locate_template(array(
  525. static::$plugin_slug . "-{$template_name}.php",
  526. static::$plugin_slug . '/' . "{$template_name}.php"
  527. ));
  528. // If template could not be found, get default one
  529. if(empty($template)) {
  530. $default_template_file = $this->path('views') . '/' . "{$template_name}.php";
  531. if(file_exists($default_template_file)) {
  532. $template = $default_template_file;
  533. }
  534. }
  535. // If template does not exist, trigger a warning to inform the site administrator
  536. if(empty($template)) {
  537. $this->trigger_error(Messages::ERR_INVALID_TEMPLATE,
  538. E_USER_WARNING,
  539. array(static::$plugin_slug, $template_name));
  540. }
  541. return $template;
  542. }
  543. /**
  544. * Setup function. Called when plugin is enabled.
  545. */
  546. public function setup() {
  547. }
  548. /**
  549. * Cleanup function. Called when plugin is uninstalled.
  550. */
  551. public static function cleanup() {
  552. if(!defined('WP_UNINSTALL_PLUGIN')) {
  553. return;
  554. }
  555. }
  556. /**
  557. * Registers a widget class.
  558. *
  559. * @param string widget_class The widget class to register.
  560. * @param bool stop_on_error Indicates if the function should raise an error
  561. * if the Widget Class doesn't exist or cannot be loaded.
  562. * @return bool True, if the Widget was registered correctly, False otherwise.
  563. */
  564. protected function register_widget($widget_class, $stop_on_error = true) {
  565. if(!class_exists($widget_class)) {
  566. if($stop_on_error === true) {
  567. $this->trigger_error(\Aelia\WC\Messages::ERR_INVALID_WIDGET_CLASS,
  568. E_USER_WARNING, array($widget_class));
  569. }
  570. return false;
  571. }
  572. register_widget($widget_class);
  573. return true;
  574. }
  575. /**
  576. * Indicates if we are processing an Ajax call.
  577. *
  578. * @return bool
  579. */
  580. public static function doing_ajax() {
  581. return defined('DOING_AJAX') && DOING_AJAX;
  582. }
  583. /**
  584. * Indicates if we are rendering a frontend page. In case of Ajax calls, this
  585. * method checks if the call was made in the backend by looking at its
  586. * arguments.
  587. *
  588. * @return bool
  589. * @since 1.6.3.15815
  590. */
  591. public static function is_frontend() {
  592. return !is_admin() || (
  593. self::doing_ajax() &&
  594. !in_array(strtolower(get_value('action', $_REQUEST)), array(
  595. // The following actions are called in the backend. If they are used, then
  596. // we are in the backend, regardless of the fact that we are using Ajax
  597. 'woocommerce_load_variations',
  598. 'woocommerce_add_variation',
  599. 'woocommerce_remove_variations',
  600. 'woocommerce_link_all_variations',
  601. 'woocommerce_bulk_edit_variations',
  602. )));
  603. }
  604. /**
  605. * Indicates if we are preparing a report. The logic to determine which
  606. * report is being rendered was copied from WC_Admin_Reports class.
  607. *
  608. * @param mixed reports The report ID, or an array of report IDs. The function
  609. * will return true if we are rendering any of them.
  610. * @return bool
  611. * @since 1.5.19.150625
  612. * @see WC_Admin_Reports::output()
  613. */
  614. public static function doing_reports($reports = array()) {
  615. // Check if we are rendering a report page
  616. if(is_admin() && isset($_GET['page']) && ($_GET['page'] === 'wc-reports')) {
  617. /* If the "reports" argument is empty, we are just checking if we are
  618. * rendering ANY report page
  619. */
  620. if(empty($reports)) {
  621. return true;
  622. }
  623. if(!is_array($reports)) {
  624. $reports = array($reports);
  625. }
  626. $available_reports = WC_Admin_Reports::get_reports();
  627. $first_tab = array_keys($available_reports);
  628. $current_tab = ! empty($_GET['tab']) ? sanitize_title($_GET['tab']) : $first_tab[0];
  629. $current_report = isset($_GET['report']) ? sanitize_title($_GET['report']) : current(array_keys($available_reports[ $current_tab ]['reports']));
  630. return empty($reports) || in_array($current_report, $reports);
  631. }
  632. return false;
  633. }
  634. /**
  635. * Indicates if we are on the "order edit" page.
  636. *
  637. * @return int|false The ID of the order being modified, or false if we are
  638. * on another page.
  639. * @since 1.5.19.150625
  640. */
  641. public static function editing_order() {
  642. if(!empty($_GET['action']) && ($_GET['action'] == 'edit') && !empty($_GET['post'])) {
  643. global $post;
  644. if(!empty($post) && ($post->post_type == 'shop_order')) {
  645. return $post->ID;
  646. }
  647. }
  648. return false;
  649. }
  650. /**
  651. * Sets the Cron schedules required by the plugin.
  652. *
  653. * @since 1.6.0.150724
  654. */
  655. protected function set_cron_schedules() {
  656. // To be implemented by descendant class
  657. }
  658. /**
  659. * Returns the Nonce ID used by the Ajax call handled by the plugin.
  660. *
  661. * @since 1.7.3.160531
  662. */
  663. protected function ajax_nonce_id() {
  664. return self::$plugin_slug . '-nonce';
  665. }
  666. /**
  667. * Returns the action used to route Ajax calls to this plugin.
  668. *
  669. * @return string
  670. * @since 1.7.3.160531
  671. */
  672. protected function ajax_action() {
  673. return '';
  674. }
  675. /**
  676. * Returns the action used to route Ajax calls to this plugin for anonymous
  677. * users (i.e "nopriv" Ajax calls).
  678. *
  679. * @return string
  680. * @since 1.7.3.160531
  681. */
  682. protected function nopriv_ajax_action() {
  683. return $this->ajax_action();
  684. }
  685. /**
  686. * Returns a list of valid Ajax commands.
  687. *
  688. * @param string command The command to validate.
  689. * @return bool
  690. * @since 1.7.3.160531
  691. */
  692. protected function get_valid_ajax_commands() {
  693. return array();
  694. }
  695. /**
  696. * Indicates if an Ajax command is valid.
  697. *
  698. * @param string command The command to validate.
  699. * @return bool
  700. * @since 1.7.3.160531
  701. */
  702. protected function is_valid_ajax_command($command) {
  703. $ajax_callbacks = $this->get_valid_ajax_commands();
  704. return isset($ajax_callbacks[$command]) && is_callable($ajax_callbacks[$command]);
  705. }
  706. /**
  707. * Returns the callback associated to an Ajax command.
  708. *
  709. * @param string ajax_command The ajax command.
  710. * @return callable|null The callback to invoke, or null if the command is not
  711. * valid.
  712. * @since 1.7.3.160531
  713. */
  714. protected function get_ajax_callback($ajax_command) {
  715. if($this->is_valid_ajax_command($ajax_command)) {
  716. $ajax_callbacks = $this->get_valid_ajax_commands();
  717. return $ajax_callbacks[$ajax_command];
  718. }
  719. return null;
  720. }
  721. /**
  722. * Validates an Ajax request.
  723. *
  724. * @return int Zero if the Ajax request is valid, otherwise an error number.
  725. * @since 1.7.3.160531
  726. */
  727. protected function validate_ajax_request() {
  728. $result = Definitions::RES_OK;
  729. // Verify nonce
  730. if(apply_filters('wc_aelia_afc_should_validate_ajax_nonce', true)) {
  731. if(check_ajax_referer($this->ajax_nonce_id(), '_ajax_nonce', false)) {
  732. $result = Definitions::ERR_AJAX_INVALID_REFERER;
  733. }
  734. }
  735. // Additional check to verify that it's a valid Ajax request
  736. //if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) ||
  737. // strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
  738. // $result = Definitions::ERR_INVALID_AJAX_REQUEST;
  739. //}
  740. // Check that a command was passed
  741. if($result == Definitions::RES_OK) {
  742. if(empty($_REQUEST[Definitions::ARG_AJAX_COMMAND])) {
  743. $result = Definitions::ERR_AJAX_COMMAND_MISSING;
  744. }
  745. }
  746. // Check that the command is valid
  747. if($result == Definitions::RES_OK) {
  748. if(empty($_REQUEST[Definitions::ARG_AJAX_COMMAND]) ||
  749. !$this->is_valid_ajax_command($_REQUEST[Definitions::ARG_AJAX_COMMAND])) {
  750. $result = Definitions::ERR_AJAX_INVALID_COMMAND;
  751. }
  752. }
  753. // Allow further validation
  754. $result = apply_filters('wc_aelia_afc_validate_ajax_request', $result);
  755. if($result != Definitions::RES_OK) {
  756. status_header(400);
  757. wp_send_json(apply_filters('wc_aelia_afc_invalid_request_response', array(
  758. 'result' => $result,
  759. )));
  760. }
  761. return $result;
  762. }
  763. /**
  764. * Handles Ajax calls. This method is a central handler for all Ajax calls. It
  765. * performs some validation before handing over the actual execution to
  766. * the appropriate callback.
  767. *
  768. * @since 1.7.3.160531
  769. */
  770. public function aelia_ajax_request() {
  771. if($this->validate_ajax_request() != Definitions::RES_OK) {
  772. exit;
  773. }
  774. // Get the callback to use for the Ajax request
  775. $callback = $this->get_ajax_callback($_REQUEST[Definitions::ARG_AJAX_COMMAND]);
  776. $result = call_user_func($callback);
  777. wp_send_json($result);
  778. }
  779. /**
  780. * Allows the plugin to register itself for automatic updates.
  781. *
  782. * @param array The array of the plugins to update, structured as follows:
  783. * array(
  784. * 'free' => <Array of free plugins>,
  785. * 'premium' => <Array of premium plugins, which require licence activation>,
  786. * )
  787. * @return array The array of plugins to update, with the details of this
  788. * plugin added to it.
  789. * @since 1.7.0.150818
  790. */
  791. public function aelia_register_plugins_to_update(array $plugins_to_update) {
  792. return $plugins_to_update;
  793. }
  794. /**
  795. * Sets the the folder and file name of the main plugin file.
  796. *
  797. * WHY
  798. * The "main plugin file" information cannot be retrieved with __FILE__. The
  799. * main plugin file is actually just a loader, which takes care of loading
  800. * the actual plugin class. A call to __FILE__ from this plugin class would,
  801. * therefore, return the wrong information. By allowing the loader to set
  802. * the plugin file, we can always get the correct information.
  803. *
  804. * @param string plugin_file A string indicating the main plugin file.
  805. * @since 1.7.1.150824
  806. */
  807. public function set_main_plugin_file($plugin_file) {
  808. //$this->main_plugin_file = untrailingslashit(plugin_basename($plugin_file));
  809. $this->main_plugin_file = $plugin_file;
  810. }
  811. }
  812. }