| @@ -1,69 +1,58 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | class OsController { |
| 3 | 3 | |
| 4 | - protected $params, | |
| 4 | + protected $params, | |
| 5 | 5 | $files, |
| 6 | - $layout = 'admin', | |
| 7 | - $views_folder = LATEPOINT_VIEWS_ABSPATH_SHARED, | |
| 8 | - $return_format = 'html', | |
| 9 | - $extra_css_classes = [ 'latepoint' ]; | |
| 10 | - public array $fields_to_update = []; | |
| 6 | + $layout = 'admin', | |
| 7 | + $views_folder = LATEPOINT_VIEWS_ABSPATH_SHARED, | |
| 8 | + $return_format = 'html', | |
| 9 | + $extra_css_classes = ['latepoint']; | |
| 10 | + public array $fields_to_update = []; | |
| 11 | 11 | |
| 12 | 12 | // if an action can only be accessed by a backend user, we need to define capabilities that are required |
| 13 | - public array $controller_capabilities = [ 'settings__edit' ]; // default for controller | |
| 14 | - public array $action_capabilities = []; // per action | |
| 13 | + public array $controller_capabilities = ['settings__edit']; // default for controller | |
| 14 | + public array $action_capabilities = []; // per action | |
| 15 | 15 | |
| 16 | - public array $action_access = [ | |
| 17 | - 'customer' => [], | |
| 18 | - 'public' => [], | |
| 19 | - ]; | |
| 16 | + public array $action_access = [ 'customer' => [], 'public' => [] ]; | |
| 20 | 17 | |
| 21 | - public $vars; | |
| 22 | - public $route_name; | |
| 18 | + public $vars; | |
| 19 | + public $route_name; | |
| 23 | 20 | |
| 24 | 21 | |
| 25 | 22 | |
| 26 | - function __construct() { | |
| 27 | - $this->params = $this->get_params(); | |
| 28 | - $this->files = $this->get_files(); | |
| 29 | - $this->set_layout( $this->layout ); | |
| 30 | - $this->vars['page_header'] = __( 'Bookings', 'latepoint' ); | |
| 31 | - $this->vars['breadcrumbs'][] = array( | |
| 32 | - 'label' => __( 'Dashboard', 'latepoint' ), | |
| 33 | - 'link' => OsRouterHelper::build_link( [ 'dashboard', 'index' ] ), | |
| 34 | - ); | |
| 23 | + function __construct(){ | |
| 24 | + $this->params = $this->get_params(); | |
| 25 | + $this->files = $this->get_files(); | |
| 26 | + $this->set_layout($this->layout); | |
| 27 | + $this->vars['page_header'] = __('Bookings', 'latepoint'); | |
| 28 | + $this->vars['breadcrumbs'][] = array('label' => __('Dashboard', 'latepoint'), 'link' => OsRouterHelper::build_link(['dashboard', 'index'] )); | |
| 35 | 29 | |
| 36 | - $this->load_settings(); | |
| 37 | - $this->vars['logged_in_customer'] = OsAuthHelper::get_logged_in_customer(); | |
| 38 | - } | |
| 30 | + $this->load_settings(); | |
| 31 | + $this->vars['logged_in_customer'] = OsAuthHelper::get_logged_in_customer(); | |
| 32 | + } | |
| 39 | 33 | |
| 40 | - public function check_nonce( $action, $custom_nonce = '' ) { | |
| 41 | - $nonce = ! empty( $custom_nonce ) ? $custom_nonce : $this->params['_wpnonce']; | |
| 42 | - if ( ! wp_verify_nonce( $nonce, $action ) ) { | |
| 43 | - if ( $this->get_return_format() == 'json' ) { | |
| 44 | - $this->send_json( | |
| 45 | - array( | |
| 46 | - 'status' => LATEPOINT_STATUS_ERROR, | |
| 47 | - 'message' => __( 'Invalid Request', 'latepoint' ), | |
| 48 | - ) | |
| 49 | - ); | |
| 50 | - } else { | |
| 34 | + public function check_nonce($action, $custom_nonce = ''){ | |
| 35 | + $nonce = !empty($custom_nonce) ? $custom_nonce : $this->params['_wpnonce']; | |
| 36 | + if(!wp_verify_nonce($nonce, $action)){ | |
| 37 | + if($this->get_return_format() == 'json'){ | |
| 38 | + $this->send_json(array('status' => LATEPOINT_STATUS_ERROR, 'message' => __('Invalid Request', 'latepoint'))); | |
| 39 | + }else{ | |
| 51 | 40 | wp_die(); |
| 52 | - } | |
| 41 | + } | |
| 53 | 42 | } |
| 54 | 43 | } |
| 55 | 44 | |
| 56 | - public function can_current_user_access_action( string $action ): bool { | |
| 57 | - if ( in_array( $action, $this->action_access['public'] ) ) { | |
| 45 | + public function can_current_user_access_action(string $action): bool{ | |
| 46 | + if(in_array($action, $this->action_access['public'])){ | |
| 58 | 47 | // public route |
| 59 | 48 | $can = true; |
| 60 | - } elseif ( in_array( $action, $this->action_access['customer'] ) && OsAuthHelper::get_current_user()->customer ) { | |
| 49 | + }elseif(in_array($action, $this->action_access['customer']) && OsAuthHelper::get_current_user()->customer){ | |
| 61 | 50 | // customer route & customer is logged in |
| 62 | 51 | $can = true; |
| 63 | - } else { | |
| 52 | + }else{ | |
| 64 | 53 | // backend route, check for capabilities |
| 65 | - $can = OsAuthHelper::get_current_user()->has_capability( $this->get_capabilities_required_for_action( $action ) ); | |
| 54 | + $can = OsAuthHelper::get_current_user()->has_capability($this->get_capabilities_required_for_action($action)); | |
| 66 | 55 | } |
| 67 | 56 | |
| 68 | 57 | /** |
| 69 | 58 | * Determines if a currently logged in user can access controller's action |
| @@ -75,159 +64,142 @@ | ||
| 75 | 64 | * @param {string} $action Name of the action that is being called |
| 76 | 65 | * @param {LatePoint\Misc\User} $current_user Currently logged in latepoint user |
| 77 | 66 | * @returns {bool} Decision true|false |
| 78 | 67 | */ |
| 79 | - return apply_filters( 'latepoint_can_current_user_access_action', $can, $action, OsAuthHelper::get_current_user() ); | |
| 80 | - } | |
| 68 | + return apply_filters('latepoint_can_current_user_access_action', $can, $action, OsAuthHelper::get_current_user()); | |
| 69 | + } | |
| 81 | 70 | |
| 82 | - public function get_capabilities_required_for_action( $action ) { | |
| 83 | - return OsRolesHelper::get_capabilities_required_for_controller_action( get_class( $this ), $action ); | |
| 71 | + public function get_capabilities_required_for_action($action){ | |
| 72 | + return OsRolesHelper::get_capabilities_required_for_controller_action(get_class($this), $action); | |
| 84 | 73 | } |
| 85 | 74 | |
| 86 | - function generate_css_class( $view_name ) { | |
| 87 | - $class_name_filtered = strtolower( preg_replace( '/^Os(\w+)Controller/i', '$1', static::class ) ); | |
| 88 | - return "latepoint-view-{$class_name_filtered}-{$view_name}"; | |
| 89 | - } | |
| 75 | + function generate_css_class($view_name){ | |
| 76 | + $class_name_filtered = strtolower(preg_replace('/^Os(\w+)Controller/i', '$1', static::class)); | |
| 77 | + return "latepoint-view-{$class_name_filtered}-{$view_name}"; | |
| 78 | + } | |
| 90 | 79 | |
| 91 | - protected function load_settings() { | |
| 92 | - } | |
| 80 | + protected function load_settings(){ | |
| 81 | + } | |
| 93 | 82 | |
| 94 | 83 | |
| 95 | - public function access_not_allowed() { | |
| 96 | - $this->format_render( __FUNCTION__, [], [], true ); | |
| 97 | - exit(); | |
| 98 | - } | |
| 84 | + public function access_not_allowed(){ | |
| 85 | + $this->format_render(__FUNCTION__, [], [], true); | |
| 86 | + exit(); | |
| 87 | + } | |
| 99 | 88 | |
| 100 | - function format_render( $view_name, $extra_vars = array(), $json_return_vars = array(), $from_shared_folder = false ) { | |
| 101 | - echo $this->format_render_return( $view_name, $extra_vars, $json_return_vars, $from_shared_folder ); | |
| 102 | - } | |
| 89 | + function format_render($view_name, $extra_vars = array(), $json_return_vars = array(), $from_shared_folder = false){ | |
| 90 | + echo $this->format_render_return($view_name, $extra_vars, $json_return_vars, $from_shared_folder); | |
| 91 | + } | |
| 103 | 92 | |
| 104 | - // You can pass array to $view_name, ['json_view_name' => ..., 'html_view_name' => ...] | |
| 105 | - function format_render_return( $view_name, $extra_vars = array(), $json_return_vars = array(), $from_shared_folder = false ) { | |
| 106 | - $html = ''; | |
| 107 | - if ( $this->get_return_format() == 'json' ) { | |
| 108 | - if ( is_array( $view_name ) ) { | |
| 109 | - $view_name = $view_name['json_view_name']; | |
| 110 | - } | |
| 111 | - $response_html = $this->render( $this->get_view_uri( $view_name, $from_shared_folder ), 'none', $extra_vars ); | |
| 112 | - $this->send_json( | |
| 113 | - array_merge( | |
| 114 | - array( | |
| 115 | - 'status' => LATEPOINT_STATUS_SUCCESS, | |
| 116 | - 'message' => $response_html, | |
| 117 | - ), | |
| 118 | - $json_return_vars | |
| 119 | - ) | |
| 120 | - ); | |
| 121 | - } else { | |
| 122 | - if ( is_array( $view_name ) ) { | |
| 123 | - $view_name = $view_name['html_view_name']; | |
| 124 | - } | |
| 125 | - $this->extra_css_classes[] = $this->generate_css_class( $view_name ); | |
| 126 | - $this->vars['extra_css_classes'] = $this->extra_css_classes; | |
| 127 | - $html = $this->render( $this->get_view_uri( $view_name, $from_shared_folder ), $this->get_layout(), $extra_vars ); | |
| 128 | - } | |
| 129 | - return $html; | |
| 130 | - } | |
| 93 | + // You can pass array to $view_name, ['json_view_name' => ..., 'html_view_name' => ...] | |
| 94 | + function format_render_return($view_name, $extra_vars = array(), $json_return_vars = array(), $from_shared_folder = false){ | |
| 95 | + $html = ''; | |
| 96 | + if($this->get_return_format() == 'json'){ | |
| 97 | + if(is_array($view_name)) $view_name = $view_name['json_view_name']; | |
| 98 | + $response_html = $this->render($this->get_view_uri($view_name, $from_shared_folder), 'none', $extra_vars); | |
| 99 | + $this->send_json(array_merge(array('status' => LATEPOINT_STATUS_SUCCESS, 'message' => $response_html), $json_return_vars)); | |
| 100 | + }else{ | |
| 101 | + if(is_array($view_name)) $view_name = $view_name['html_view_name']; | |
| 102 | + $this->extra_css_classes[] = $this->generate_css_class($view_name); | |
| 103 | + $this->vars['extra_css_classes'] = $this->extra_css_classes; | |
| 104 | + $html = $this->render($this->get_view_uri($view_name, $from_shared_folder), $this->get_layout(), $extra_vars); | |
| 105 | + } | |
| 106 | + return $html; | |
| 107 | + } | |
| 131 | 108 | |
| 132 | - function set_layout( $layout = 'admin' ) { | |
| 133 | - if ( isset( $this->params['layout'] ) ) { | |
| 134 | - $this->layout = $this->params['layout']; | |
| 135 | - } else { | |
| 136 | - $this->layout = $layout; | |
| 137 | - } | |
| 138 | - } | |
| 109 | + function set_layout($layout = 'admin'){ | |
| 110 | + if(isset($this->params['layout'])){ | |
| 111 | + $this->layout = $this->params['layout']; | |
| 112 | + }else{ | |
| 113 | + $this->layout = $layout; | |
| 114 | + } | |
| 115 | + } | |
| 139 | 116 | |
| 140 | - function get_layout() { | |
| 141 | - return $this->layout; | |
| 142 | - } | |
| 117 | + function get_layout(){ | |
| 118 | + return $this->layout; | |
| 119 | + } | |
| 143 | 120 | |
| 144 | - function set_return_format( $format = 'html' ) { | |
| 145 | - $this->return_format = $format; | |
| 146 | - } | |
| 121 | + function set_return_format($format = 'html'){ | |
| 122 | + $this->return_format = $format; | |
| 123 | + } | |
| 147 | 124 | |
| 148 | - function get_return_format() { | |
| 149 | - return $this->return_format; | |
| 150 | - } | |
| 125 | + function get_return_format(){ | |
| 126 | + return $this->return_format; | |
| 127 | + } | |
| 151 | 128 | |
| 152 | - function send_json( $data, $status_code = null ) { | |
| 153 | - if ( ! empty( $this->fields_to_update ) ) { | |
| 154 | - $data['fields_to_update'] = $this->fields_to_update; | |
| 155 | - } | |
| 156 | - wp_send_json( $data, $status_code ); | |
| 157 | - } | |
| 129 | + function send_json($data, $status_code = null){ | |
| 130 | + if(!empty($this->fields_to_update)) $data['fields_to_update'] = $this->fields_to_update; | |
| 131 | + wp_send_json($data, $status_code); | |
| 132 | + } | |
| 158 | 133 | |
| 159 | - function get_view_uri( $view_name, $from_shared_folder = false ) { | |
| 160 | - if ( $from_shared_folder ) { | |
| 161 | - $view_uri = LATEPOINT_VIEWS_ABSPATH_SHARED . $view_name . '.php'; | |
| 162 | - } else { | |
| 163 | - $view_uri = $this->views_folder . $view_name . '.php'; | |
| 164 | - } | |
| 165 | - return $view_uri; | |
| 166 | - } | |
| 134 | + function get_view_uri($view_name, $from_shared_folder = false){ | |
| 135 | + if($from_shared_folder){ | |
| 136 | + $view_uri = LATEPOINT_VIEWS_ABSPATH_SHARED.$view_name.'.php'; | |
| 137 | + }else{ | |
| 138 | + $view_uri = $this->views_folder.$view_name.'.php'; | |
| 139 | + } | |
| 140 | + return $view_uri; | |
| 141 | + } | |
| 167 | 142 | |
| 168 | - private function get_safe_layout_path( $layout ) { | |
| 169 | - // 1. Remove any path separators and null bytes | |
| 170 | - $layout = str_replace( [ '/', '\\', "\0" ], '', $layout ); | |
| 143 | + private function get_safe_layout_path($layout) { | |
| 144 | + // 1. Remove any path separators and null bytes | |
| 145 | + $layout = str_replace(['/', '\\', "\0"], '', $layout); | |
| 171 | 146 | |
| 172 | - // 2. Remove any dots to prevent directory traversal | |
| 173 | - $layout = str_replace( '.', '', $layout ); | |
| 147 | + // 2. Remove any dots to prevent directory traversal | |
| 148 | + $layout = str_replace('.', '', $layout); | |
| 174 | 149 | |
| 175 | - // 3. Only allow alphanumeric, underscore, and hyphen | |
| 176 | - $layout = preg_replace( '/[^a-zA-Z0-9_-]/', '', $layout ); | |
| 150 | + // 3. Only allow alphanumeric, underscore, and hyphen | |
| 151 | + $layout = preg_replace('/[^a-zA-Z0-9_-]/', '', $layout); | |
| 177 | 152 | |
| 178 | - // 4. Construct the full path | |
| 179 | - $layout_file = $this->add_extension( $layout, '.php' ); | |
| 180 | - $full_path = LATEPOINT_VIEWS_LAYOUTS_ABSPATH . $layout_file; | |
| 153 | + // 4. Construct the full path | |
| 154 | + $layout_file = $this->add_extension($layout, '.php'); | |
| 155 | + $full_path = LATEPOINT_VIEWS_LAYOUTS_ABSPATH . $layout_file; | |
| 181 | 156 | |
| 182 | - // 5. Use realpath to resolve any remaining traversal attempts | |
| 183 | - $real_path = realpath( $full_path ); | |
| 184 | - $base_path = realpath( LATEPOINT_VIEWS_LAYOUTS_ABSPATH ); | |
| 157 | + // 5. Use realpath to resolve any remaining traversal attempts | |
| 158 | + $real_path = realpath($full_path); | |
| 159 | + $base_path = realpath(LATEPOINT_VIEWS_LAYOUTS_ABSPATH); | |
| 185 | 160 | |
| 186 | - // 6. Ensure the resolved path is within the layouts directory | |
| 187 | - if ( $real_path && $base_path && strpos( $real_path, $base_path ) === 0 ) { | |
| 188 | - return $real_path; | |
| 189 | - } | |
| 161 | + // 6. Ensure the resolved path is within the layouts directory | |
| 162 | + if ($real_path && $base_path && strpos($real_path, $base_path) === 0) { | |
| 163 | + return $real_path; | |
| 164 | + } | |
| 190 | 165 | |
| 191 | - return false; | |
| 192 | - } | |
| 166 | + return false; | |
| 167 | + } | |
| 193 | 168 | |
| 194 | - // render view and if needed layout, when layout is rendered - view variable is passed to a layout file | |
| 195 | - function render( $view, $layout = 'none', $extra_vars = array() ) { | |
| 196 | - $this->vars['route_name'] = $this->route_name; | |
| 197 | - extract( $extra_vars ); | |
| 198 | - extract( $this->vars ); | |
| 199 | - ob_start(); | |
| 200 | - if ( $layout != 'none' ) { | |
| 201 | - $layout_path = $this->get_safe_layout_path( $layout ); | |
| 202 | - // rendering layout, view variable will be passed and used in layout file | |
| 203 | - if ( $layout_path ) { | |
| 204 | - include $layout_path; | |
| 205 | - } else { | |
| 206 | - __( 'Invalid layout', 'latepoint' ); | |
| 207 | - } | |
| 208 | - } else { | |
| 209 | - include $this->add_extension( $view, '.php' ); | |
| 210 | - } | |
| 211 | - $response_html = ob_get_clean(); | |
| 212 | - return $response_html; | |
| 213 | - } | |
| 169 | + // render view and if needed layout, when layout is rendered - view variable is passed to a layout file | |
| 170 | + function render($view, $layout = 'none', $extra_vars = array()){ | |
| 171 | + $this->vars['route_name'] = $this->route_name; | |
| 172 | + extract($extra_vars); | |
| 173 | + extract($this->vars); | |
| 174 | + ob_start(); | |
| 175 | + if($layout != 'none'){ | |
| 176 | + $layout_path = $this->get_safe_layout_path($layout); | |
| 177 | + // rendering layout, view variable will be passed and used in layout file | |
| 178 | + if($layout_path){ | |
| 179 | + include $layout_path; | |
| 180 | + }else{ | |
| 181 | + __('Invalid layout', 'latepoint'); | |
| 182 | + } | |
| 183 | + }else{ | |
| 184 | + include $this->add_extension($view, '.php'); | |
| 185 | + } | |
| 186 | + $response_html = ob_get_clean(); | |
| 187 | + return $response_html; | |
| 188 | + } | |
| 214 | 189 | |
| 215 | - /* | |
| 216 | - Adds extension to a file string if its missing | |
| 217 | - */ | |
| 218 | - function add_extension( $string = '', $extension = '.php' ) { | |
| 219 | - if ( substr( $string, -strlen( $extension ) ) === $extension ) { | |
| 220 | - return $string; | |
| 221 | - } else { | |
| 222 | - return $string . $extension; | |
| 223 | - } | |
| 224 | - } | |
| 190 | + /* | |
| 191 | + Adds extension to a file string if its missing | |
| 192 | + */ | |
| 193 | + function add_extension($string = '', $extension = '.php'){ | |
| 194 | + if(substr($string, -strlen($extension))===$extension) return $string; | |
| 195 | + else return $string.$extension; | |
| 196 | + } | |
| 225 | 197 | |
| 226 | - function get_files() { | |
| 198 | + function get_files(){ | |
| 227 | 199 | return OsParamsHelper::get_files(); |
| 228 | 200 | } |
| 229 | 201 | |
| 230 | - function get_params() { | |
| 231 | - return OsParamsHelper::get_params(); | |
| 232 | - } | |
| 233 | -} | |
| 202 | + function get_params(){ | |
| 203 | + return OsParamsHelper::get_params(); | |
| 204 | + } | |
| 205 | +} | |