PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.2.0
LatePoint – Calendar Booking Plugin for Appointments and Events v5.2.0
5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / controllers / controller.php
latepoint / lib / controllers Last commit date
activities_controller.php 11 months ago auth_controller.php 9 months ago booking_form_settings_controller.php 1 year ago bookings_controller.php 1 year ago calendars_controller.php 9 months ago carts_controller.php 1 year ago controller.php 9 months ago customer_cabinet_controller.php 9 months ago customers_controller.php 9 months ago dashboard_controller.php 9 months ago default_agent_controller.php 1 year ago events_controller.php 1 year ago form_fields_controller.php 9 months ago integrations_controller.php 9 months ago invoices_controller.php 1 year ago manage_booking_by_key_controller.php 1 year ago manage_order_by_key_controller.php 1 year ago notifications_controller.php 1 year ago orders_controller.php 1 year ago pro_controller.php 1 year ago process_jobs_controller.php 9 months ago processes_controller.php 1 year ago search_controller.php 1 year ago services_controller.php 9 months ago settings_controller.php 1 year ago steps_controller.php 9 months ago stripe_connect_controller.php 9 months ago support_topics_controller.php 1 year ago todos_controller.php 1 year ago transactions_controller.php 1 year ago wizard_controller.php 1 year ago
controller.php
205 lines
1 <?php
2 class OsController {
3
4 protected $params,
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 = [];
11
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
15
16 public array $action_access = [ 'customer' => [], 'public' => [] ];
17
18 public $vars;
19 public $route_name;
20
21
22
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'] ));
29
30 $this->load_settings();
31 $this->vars['logged_in_customer'] = OsAuthHelper::get_logged_in_customer();
32 }
33
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{
40 wp_die();
41 }
42 }
43 }
44
45 public function can_current_user_access_action(string $action): bool{
46 if(in_array($action, $this->action_access['public'])){
47 // public route
48 $can = true;
49 }elseif(in_array($action, $this->action_access['customer']) && OsAuthHelper::get_current_user()->customer){
50 // customer route & customer is logged in
51 $can = true;
52 }else{
53 // backend route, check for capabilities
54 $can = OsAuthHelper::get_current_user()->has_capability($this->get_capabilities_required_for_action($action));
55 }
56
57 /**
58 * Determines if a currently logged in user can access controller's action
59 *
60 * @since 4.7.0
61 * @hook latepoint_can_current_user_access_action
62 *
63 * @param {bool} $can Decision true|false
64 * @param {string} $action Name of the action that is being called
65 * @param {LatePoint\Misc\User} $current_user Currently logged in latepoint user
66 * @returns {bool} Decision true|false
67 */
68 return apply_filters('latepoint_can_current_user_access_action', $can, $action, OsAuthHelper::get_current_user());
69 }
70
71 public function get_capabilities_required_for_action($action){
72 return OsRolesHelper::get_capabilities_required_for_controller_action(get_class($this), $action);
73 }
74
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 }
79
80 protected function load_settings(){
81 }
82
83
84 public function access_not_allowed(){
85 $this->format_render(__FUNCTION__, [], [], true);
86 exit();
87 }
88
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 }
92
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 }
108
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 }
116
117 function get_layout(){
118 return $this->layout;
119 }
120
121 function set_return_format($format = 'html'){
122 $this->return_format = $format;
123 }
124
125 function get_return_format(){
126 return $this->return_format;
127 }
128
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 }
133
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 }
142
143 private function get_safe_layout_path($layout) {
144 // 1. Remove any path separators and null bytes
145 $layout = str_replace(['/', '\\', "\0"], '', $layout);
146
147 // 2. Remove any dots to prevent directory traversal
148 $layout = str_replace('.', '', $layout);
149
150 // 3. Only allow alphanumeric, underscore, and hyphen
151 $layout = preg_replace('/[^a-zA-Z0-9_-]/', '', $layout);
152
153 // 4. Construct the full path
154 $layout_file = $this->add_extension($layout, '.php');
155 $full_path = LATEPOINT_VIEWS_LAYOUTS_ABSPATH . $layout_file;
156
157 // 5. Use realpath to resolve any remaining traversal attempts
158 $real_path = realpath($full_path);
159 $base_path = realpath(LATEPOINT_VIEWS_LAYOUTS_ABSPATH);
160
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 }
165
166 return false;
167 }
168
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 }
189
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 }
197
198 function get_files(){
199 return OsParamsHelper::get_files();
200 }
201
202 function get_params(){
203 return OsParamsHelper::get_params();
204 }
205 }