PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / trunk
LatePoint – Calendar Booking Plugin for Appointments and Events vtrunk
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 1 month ago auth_controller.php 3 months ago booking_form_settings_controller.php 3 months ago bookings_controller.php 12 hours ago calendars_controller.php 3 months ago carts_controller.php 12 hours ago controller.php 3 months ago customer_cabinet_controller.php 2 months ago customers_controller.php 12 hours ago dashboard_controller.php 2 months ago default_agent_controller.php 3 months ago events_controller.php 3 months ago form_fields_controller.php 1 week ago integrations_controller.php 3 months ago invoices_controller.php 12 hours ago manage_booking_by_key_controller.php 3 months ago manage_order_by_key_controller.php 3 months ago notifications_controller.php 3 months ago orders_controller.php 12 hours ago pro_controller.php 2 weeks ago process_jobs_controller.php 3 months ago processes_controller.php 1 month ago razorpay_connect_controller.php 1 week ago search_controller.php 3 months ago services_controller.php 3 months ago settings_controller.php 2 months ago steps_controller.php 2 weeks ago stripe_connect_controller.php 1 week ago support_topics_controller.php 3 months ago todos_controller.php 3 months ago transactions_controller.php 12 hours ago wizard_controller.php 1 week ago
controller.php
234 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 = [
17 'customer' => [],
18 'public' => [],
19 ];
20
21 public $vars;
22 public $route_name;
23
24
25
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 );
35
36 $this->load_settings();
37 $this->vars['logged_in_customer'] = OsAuthHelper::get_logged_in_customer();
38 }
39
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 {
51 wp_die();
52 }
53 }
54 }
55
56 public function can_current_user_access_action( string $action ): bool {
57 if ( in_array( $action, $this->action_access['public'] ) ) {
58 // public route
59 $can = true;
60 } elseif ( in_array( $action, $this->action_access['customer'] ) && OsAuthHelper::get_current_user()->customer ) {
61 // customer route & customer is logged in
62 $can = true;
63 } else {
64 // backend route, check for capabilities
65 $can = OsAuthHelper::get_current_user()->has_capability( $this->get_capabilities_required_for_action( $action ) );
66 }
67
68 /**
69 * Determines if a currently logged in user can access controller's action
70 *
71 * @since 4.7.0
72 * @hook latepoint_can_current_user_access_action
73 *
74 * @param {bool} $can Decision true|false
75 * @param {string} $action Name of the action that is being called
76 * @param {LatePoint\Misc\User} $current_user Currently logged in latepoint user
77 * @returns {bool} Decision true|false
78 */
79 return apply_filters( 'latepoint_can_current_user_access_action', $can, $action, OsAuthHelper::get_current_user() );
80 }
81
82 public function get_capabilities_required_for_action( $action ) {
83 return OsRolesHelper::get_capabilities_required_for_controller_action( get_class( $this ), $action );
84 }
85
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 }
90
91 protected function load_settings() {
92 }
93
94
95 public function access_not_allowed() {
96 $this->format_render( __FUNCTION__, [], [], true );
97 exit();
98 }
99
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 }
103
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 }
131
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 }
139
140 function get_layout() {
141 return $this->layout;
142 }
143
144 function set_return_format( $format = 'html' ) {
145 $this->return_format = $format;
146 }
147
148 function get_return_format() {
149 return $this->return_format;
150 }
151
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 }
158
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 }
167
168 private function get_safe_layout_path( $layout ) {
169 // 1. Remove any path separators and null bytes
170 $layout = str_replace( [ '/', '\\', "\0" ], '', $layout );
171
172 // 2. Remove any dots to prevent directory traversal
173 $layout = str_replace( '.', '', $layout );
174
175 // 3. Only allow alphanumeric, underscore, and hyphen
176 $layout = preg_replace( '/[^a-zA-Z0-9_-]/', '', $layout );
177
178 // 4. Construct the full path
179 $layout_file = $this->add_extension( $layout, '.php' );
180 $full_path = LATEPOINT_VIEWS_LAYOUTS_ABSPATH . $layout_file;
181
182 // 5. Use realpath to resolve any remaining traversal attempts
183 $real_path = realpath( $full_path );
184 $base_path = realpath( LATEPOINT_VIEWS_LAYOUTS_ABSPATH );
185
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 }
190
191 return false;
192 }
193
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 }
214
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 }
225
226 function get_files() {
227 return OsParamsHelper::get_files();
228 }
229
230 function get_params() {
231 return OsParamsHelper::get_params();
232 }
233 }
234