_menu_slug . '-' . 'settings-edit_form' * Example: amoforms-settings-edit_form * @var array */ protected $_admin_menu_items = [ 'Edit Fields' => 'settings', 'Form Settings' => 'settings-edit_form', 'Email Settings' => 'settings-edit_email', 'Form Preview' => 'settings-form_preview', 'Account' => 'settings-edit_account', 'Entries' => 'entries', ]; /** * Ajax endpoints. * The resulting values ​​will be as: $this->_ajax_prefix . 'add_field' * Example: amoforms_add_field * @var array */ protected $_ajax_actions = [ 'private' => [ // Fields settings 'Add field' => 'add_field', 'Duplicate field' => 'duplicate_field', 'Delete field' => 'delete_field', 'Edit field' => 'edit_field', 'Update fields' => 'update_fields', 'Update submit button' => 'update_submit_button', // Account settings 'Check amo user is free' => 'check_email', 'Check amo acc credentials' => 'has_connection', 'Check amo form settings' => 'update_form', 'Check amo email settings' => 'update_email', // Other 'Delete all forms' => 'delete_all_forms', ], 'protected' => [ 'Submit amo form' => 'submit', ], 'public' => [ ], ]; /** * @since 1.0.0 */ protected function __construct() { $this->_is_ajax = (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtoupper($_SERVER['HTTP_X_REQUESTED_WITH']) === 'XMLHTTPREQUEST'); $this->_page = !empty($_GET['page']) ? (string)$_GET['page'] : ''; $parts = explode('-', $this->_page); if (!empty($parts[1])) { $this->_controller = $parts[1]; } elseif (isset($_GET['controller'])) { $this->_controller = $_GET['controller']; } else { $this->_controller = 'Settings'; } $this->_action = !empty($_REQUEST['action']) ? $_REQUEST['action'] : (!empty($parts[2]) ? $parts[2] : 'index'); if ($this->_is_ajax && strpos($this->_action, $this->_ajax_prefix) === 0) { $this->_action = str_replace($this->_ajax_prefix, '', $this->_action); } $this->init_admin_menu(); $this->init_ajax_actions(); } /** * Check, whether the request is ajax * @since 2.5.0 * @return bool */ public function is_ajax() { return $this->_is_ajax; } /** * Get admin menu items with their full actions * @since 2.8.0 * @return array */ public function get_admin_menu_items() { $result = []; foreach ($this->_admin_menu_items as $name => $action) { $result[$name] = $this->_menu_slug . ($action ? '-' . $action : ''); } return $result; } /** * Init admin menu * @since 1.0.0 */ protected function init_admin_menu() { //TODO: check capabilities in controller add_action('admin_menu', function () { add_menu_page($this->_menu_title, $this->_menu_title, $this->_settings_capability, $this->_main_menu_slug, [$this, 'navigate']); foreach ($this->get_admin_menu_items() as $title => $action) { add_submenu_page($this->_main_menu_slug, $title, $title, $this->_settings_capability, $action, [$this, 'navigate']); } }); } /** * Init ajax actions * @since 2.0.1 */ protected function init_ajax_actions() { foreach($this->_ajax_actions as $type => $actions) { foreach ($actions as $action) { $action = $this->_ajax_prefix . $action; switch($type) { case 'private': add_action("wp_ajax_{$action}", [$this, 'navigate_ajax']); break; case 'protected': add_action("wp_ajax_{$action}", [$this, 'navigate_ajax']); add_action("wp_ajax_nopriv_{$action}", [$this, 'navigate_ajax']); break; case 'public': add_action("wp_ajax_nopriv_{$action}", [$this, 'navigate_ajax']); break; } } } } /** * Navigate to controller and action * @since 1.0.0 * @throws Exceptions\Validate */ public function navigate() { try { $controller_name = '\\' . __NAMESPACE__ . '\\Controllers\\' . ucfirst($this->_controller); $action = $this->_action . '_action'; if (!class_exists($controller_name)) { throw new Validate('Undefined controller'); } $controller = new $controller_name(); if (!method_exists($controller, $action)) { throw new Validate('Undefined action'); } $controller->$action(); } catch (\Exception $e) { Helpers::handle_exception($e); } } /** * Navigate for ajax requests * @since 2.0.0 */ public function navigate_ajax() { header('Cache-Control: no-cache, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Content-type: application/json'); $this->navigate(); die; } }