PluginProbe
BetterLinks – Link Shortener, Link Cloaking, Redirects, Affiliate Link Manager & MCP / trunk
BetterLinks – Link Shortener, Link Cloaking, Redirects, Affiliate Link Manager & MCP vtrunk
3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 3.0.0 2.4.13 2.4.12 2.4.11 2.4.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 All 110 releases
betterlinks / includes / API / Settings.php

Settings.php in BetterLinks – Link Shortener, Link Cloaking, Redirects, Affiliate Link Manager & MCP trunk, at includes/API/Settings.php

204 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace BetterLinks\API;
4 if ( ! defined( 'ABSPATH' ) ) { exit; }
5
6 use BetterLinks\Admin\Cache;
7 use BetterLinks\Traits\ArgumentSchema;
8
9 class Settings extends Controller {
10
11 use ArgumentSchema;
12
13 /**
14 * Initialize hooks and option name
15 */
16 public function __construct() {
17 add_action( 'rest_api_init', array( $this, 'register_routes' ) );
18 }
19
20 /**
21 * Register the routes for the objects of the controller.
22 */
23 public function register_routes() {
24 $endpoint = '/settings/';
25 register_rest_route(
26 $this->namespace,
27 $endpoint,
28 array(
29 array(
30 'methods' => \WP_REST_Server::READABLE,
31 'callback' => array( $this, 'get_items' ),
32 'permission_callback' => array( $this, 'get_items_permissions_check' ),
33 'args' => $this->get_settings_schema(),
34 ),
35 )
36 );
37
38 register_rest_route(
39 $this->namespace,
40 $endpoint,
41 array(
42 array(
43 'methods' => \WP_REST_Server::EDITABLE,
44 'callback' => array( $this, 'update_item' ),
45 'permission_callback' => array( $this, 'permissions_check' ),
46 'args' => $this->get_settings_schema(),
47 ),
48 )
49 );
50 }
51
52 /**
53 * Get betterlinks
54 *
55 * @param WP_REST_Request $request Full data about the request.
56 * @return WP_Error|WP_REST_Request
57 */
58 public function get_items( $request ) {
59 $response = Cache::get_json_settings();
60 return new \WP_REST_Response(
61 array(
62 'success' => true,
63 'data' => json_encode( $response ),
64 ),
65 200
66 );
67 }
68
69 /**
70 * Create OR Update betterlinks
71 *
72 * @param WP_REST_Request $request Full data about the request.
73 * @return WP_Error|WP_REST_Request
74 */
75 public function create_item( $request ) {
76 return new \WP_REST_Response(
77 array(
78 'success' => true,
79 'data' => array(),
80 ),
81 200
82 );
83 }
84
85 /**
86 * Create OR Update betterlinks
87 *
88 * @param WP_REST_Request $request Full data about the request.
89 * @return WP_Error|WP_REST_Request
90 */
91 public function update_item( $request ) {
92 $helper = new \BetterLinks\Helper();
93 $response = $request->get_params();
94 $response = $helper::sanitize_text_or_array_field( $response );
95
96 $response['uncloaked_categories'] = isset( $response['uncloaked_categories'] ) && is_string( $response['uncloaked_categories'] ) ? json_decode( $response['uncloaked_categories'] ) : array();
97 $response['affiliate_disclosure_text'] = isset( $response['affiliate_disclosure_text'] ) && is_string( $response['affiliate_disclosure_text'] ) ? $response['affiliate_disclosure_text'] : '';
98
99 // Validate and sanitize excluded IPs
100 if ( isset( $response['excluded_ips'] ) ) {
101 if ( is_array( $response['excluded_ips'] ) ) {
102 $response['excluded_ips'] = array_values( array_filter( array_map( function( $ip ) {
103 $ip = sanitize_text_field( trim( $ip ) );
104 // Validate IP address (IPv4 or IPv6)
105 return filter_var( $ip, FILTER_VALIDATE_IP ) ? $ip : null;
106 }, $response['excluded_ips'] ) ) );
107 } else {
108 $response['excluded_ips'] = array();
109 }
110 }
111
112 // Pro Logics
113 $response = apply_filters( 'betterlinkspro/admin/update_settings', $response );
114
115 // Handle custom SVG icon sanitization
116 if ( ! empty( $response['autolink_custom_icon'] ) ) {
117 // Use the sanitize_custom_svg method if it exists, otherwise use custom wp_kses for SVG
118 if ( class_exists( '\BetterLinksPro\Frontend\AutoLinks' ) && method_exists( '\BetterLinksPro\Frontend\AutoLinks', 'sanitize_custom_svg' ) ) {
119 $response['autolink_custom_icon'] = \BetterLinksPro\Frontend\AutoLinks::sanitize_custom_svg( $response['autolink_custom_icon'] );
120 } else {
121 // Custom wp_kses with SVG allowed elements as fallback
122 $allowed_svg = array(
123 'svg' => array( 'class' => array(), 'width' => array(), 'height' => array(), 'viewbox' => array(), 'viewBox' => array(), 'fill' => array(), 'xmlns' => array() ),
124 'path' => array( 'd' => array(), 'stroke' => array(), 'stroke-width' => array(), 'stroke-linecap' => array(), 'stroke-linejoin' => array(), 'fill' => array() ),
125 'g' => array( 'fill' => array(), 'stroke' => array() ),
126 'circle' => array( 'cx' => array(), 'cy' => array(), 'r' => array(), 'fill' => array(), 'stroke' => array() ),
127 'rect' => array( 'x' => array(), 'y' => array(), 'width' => array(), 'height' => array(), 'fill' => array(), 'stroke' => array() ),
128 );
129 $response['autolink_custom_icon'] = wp_kses( $response['autolink_custom_icon'], $allowed_svg );
130 }
131 }
132
133 if ( ! empty( $response['fbs']['enable_fbs'] ) ) {
134 $category = ! empty( $response['fbs']['cat_id'] ) ? sanitize_text_field( $response['fbs']['cat_id'] ) : 1;
135 $category = $helper::insert_new_category( $category );
136 $response['fbs']['cat_id'] = $category;
137 }
138
139 update_option( BETTERLINKS_CUSTOM_DOMAIN_MENU, !empty( $response['enable_custom_domain_menu'] ) ? $response['enable_custom_domain_menu'] : false );
140
141 $response = json_encode( $response );
142 if ( $response ) {
143 update_option( BETTERLINKS_LINKS_OPTION_NAME, $response );
144 Cache::write_json_settings();
145 }
146 // regenerate links for wildcards option update
147 $helper::clear_query_cache();
148 $helper::write_links_inside_json();
149
150 // Recompute which categories the dashboard hides under the settings that
151 // were JUST saved. The SPA received this list at page load (via
152 // wp_localize_script) and toggling "show the Link in Bio category" changes
153 // it — without the fresh list in the response, the app keeps filtering the
154 // category out until a hard reload, which read as "bio links never show".
155 $hidden_term_ids = apply_filters( 'betterlinks/dashboard_hidden_term_ids', array(), (array) json_decode( $response, true ) );
156 $hidden_term_ids = array_values( array_unique( array_filter( array_map( 'intval', (array) $hidden_term_ids ) ) ) );
157
158 return new \WP_REST_Response(
159 array(
160 'success' => true,
161 'data' => $response ? $response : array(),
162 'hidden_term_ids' => $hidden_term_ids,
163 ),
164 200
165 );
166 }
167
168 /**
169 * Delete betterlinks
170 *
171 * @param WP_REST_Request $request Full data about the request.
172 * @return WP_Error|WP_REST_Request
173 */
174 public function delete_item( $request ) {
175 return new \WP_REST_Response(
176 array(
177 'success' => true,
178 'data' => array(),
179 ),
180 200
181 );
182 }
183
184 /**
185 * Check if a given request has access to update a setting
186 *
187 * @param WP_REST_Request $request Full data about the request.
188 * @return WP_Error|bool
189 */
190 public function get_items_permissions_check( $request ) {
191 return apply_filters( 'betterlinks/api/settings_get_items_permissions_check', current_user_can( 'manage_options' ) );
192 }
193
194 /**
195 * Check if a given request has access to update a setting
196 *
197 * @param WP_REST_Request $request Full data about the request.
198 * @return WP_Error|bool
199 */
200 public function permissions_check( $request ) {
201 return apply_filters( 'betterlinks/api/settings_update_items_permissions_check', current_user_can( 'manage_options' ) );
202 }
203 }
204