Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 115 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
| SettingsController | |
0.00% |
0 / 115 |
|
0.00% |
0 / 6 |
1260 | |
0.00% |
0 / 1 |
| register_routes | |
0.00% |
0 / 27 |
|
0.00% |
0 / 1 |
2 | |||
| get_item | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| update_item | |
0.00% |
0 / 42 |
|
0.00% |
0 / 1 |
272 | |||
| get_current_settings | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
72 | |||
| initialize | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
30 | |||
| validate_twitter_id | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
| 1 | <?php |
| 2 | namespace NewfoldLabs\WP\Module\Onboarding\RestApi; |
| 3 | |
| 4 | use NewfoldLabs\WP\Module\Onboarding\Permissions; |
| 5 | use NewfoldLabs\WP\Module\Onboarding\Data\Options; |
| 6 | use NewfoldLabs\WP\Module\Onboarding\Data\Config; |
| 7 | use NewfoldLabs\WP\Module\Onboarding\WP_Config; |
| 8 | |
| 9 | /** |
| 10 | * Class SettingsController |
| 11 | */ |
| 12 | class SettingsController { |
| 13 | |
| 14 | /** |
| 15 | * The namespace of this controller's route. |
| 16 | * |
| 17 | * @var string |
| 18 | */ |
| 19 | protected $namespace = 'newfold-onboarding/v1'; |
| 20 | |
| 21 | /** |
| 22 | * The endpoint base |
| 23 | * |
| 24 | * @var string |
| 25 | */ |
| 26 | protected $rest_base = '/settings'; |
| 27 | |
| 28 | /** |
| 29 | * Array of defaults for the option. |
| 30 | * |
| 31 | * Shouldn't be requested directly, use $this->get_defaults(); |
| 32 | * |
| 33 | * @var array |
| 34 | */ |
| 35 | protected $defaults = array( |
| 36 | 'facebook_site' => '', // Text field. |
| 37 | 'instagram_url' => '', |
| 38 | 'linkedin_url' => '', |
| 39 | 'myspace_url' => '', |
| 40 | 'og_default_image' => '', // Text field. |
| 41 | 'og_default_image_id' => '', |
| 42 | 'og_frontpage_title' => '', // Text field. |
| 43 | 'og_frontpage_desc' => '', // Text field. |
| 44 | 'og_frontpage_image' => '', // Text field. |
| 45 | 'og_frontpage_image_id' => '', |
| 46 | 'opengraph' => true, |
| 47 | 'pinterest_url' => '', |
| 48 | 'pinterestverify' => '', |
| 49 | 'twitter' => true, |
| 50 | 'twitter_site' => '', // Text field. |
| 51 | 'twitter_card_type' => 'summary_large_image', |
| 52 | 'youtube_url' => '', |
| 53 | 'wikipedia_url' => '', |
| 54 | 'other_social_urls' => array(), |
| 55 | 'mastodon_url' => '', |
| 56 | ); |
| 57 | |
| 58 | /** |
| 59 | * Validate these URL keys in the data provided |
| 60 | * |
| 61 | * @var array |
| 62 | */ |
| 63 | protected $social_urls_to_validate = array( |
| 64 | 'facebook_site', |
| 65 | 'instagram_url', |
| 66 | 'linkedin_url', |
| 67 | 'twitter_site', |
| 68 | 'myspace_url', |
| 69 | 'pinterest_url', |
| 70 | 'youtube_url', |
| 71 | 'wikipedia_url', |
| 72 | 'other_social_urls', |
| 73 | 'mastodon_url', |
| 74 | ); |
| 75 | |
| 76 | /** |
| 77 | * Store for invalid urls |
| 78 | * |
| 79 | * @var array |
| 80 | */ |
| 81 | protected $invalid_urls = array(); |
| 82 | |
| 83 | /** |
| 84 | * Registers the settings route |
| 85 | */ |
| 86 | public function register_routes() { |
| 87 | \register_rest_route( |
| 88 | $this->namespace, |
| 89 | $this->rest_base, |
| 90 | array( |
| 91 | array( |
| 92 | 'methods' => \WP_REST_Server::READABLE, |
| 93 | 'callback' => array( $this, 'get_item' ), |
| 94 | 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), |
| 95 | ), |
| 96 | array( |
| 97 | 'methods' => \WP_REST_Server::EDITABLE, |
| 98 | 'callback' => array( $this, 'update_item' ), |
| 99 | 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), |
| 100 | ), |
| 101 | ) |
| 102 | ); |
| 103 | |
| 104 | \register_rest_route( |
| 105 | $this->namespace, |
| 106 | $this->rest_base . '/initialize', |
| 107 | array( |
| 108 | array( |
| 109 | 'methods' => \WP_REST_Server::EDITABLE, |
| 110 | 'callback' => array( $this, 'initialize' ), |
| 111 | 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), |
| 112 | ), |
| 113 | ) |
| 114 | ); |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Retrieves the settings handled by the plugin. |
| 119 | * |
| 120 | * @return \WP_REST_Response |
| 121 | */ |
| 122 | public function get_item() { |
| 123 | return new \WP_REST_Response( $this->get_current_settings() ); |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Updates settings for the settings object. |
| 128 | * |
| 129 | * @param \WP_REST_Request $request Full details about the request. |
| 130 | * |
| 131 | * @return \WP_REST_Response|\WP_Error |
| 132 | */ |
| 133 | public function update_item( \WP_REST_Request $request ) { |
| 134 | $settings = $this->get_current_settings(); |
| 135 | $params = $request->get_json_params(); |
| 136 | |
| 137 | // Check if $params is an array, else return the current settings that we have. |
| 138 | if ( ! is_array( $params ) ) { |
| 139 | return $settings; |
| 140 | } |
| 141 | |
| 142 | // check if all the param keys are present in the yoast social keys |
| 143 | foreach ( $params as $param_key => $param_value ) { |
| 144 | if ( ! array_key_exists( $param_key, $this->defaults ) ) { |
| 145 | $this->invalid_urls[] = $param_key; |
| 146 | unset( $params[ $param_key ] ); |
| 147 | continue; |
| 148 | } |
| 149 | |
| 150 | // check for proper url |
| 151 | if ( in_array( $param_key, $this->social_urls_to_validate, true ) ) { |
| 152 | switch ( $param_key ) { |
| 153 | case 'twitter_site': |
| 154 | if ( ! empty( $params['twitter_site'] ) ) { |
| 155 | $twitter_id = $this->validate_twitter_id( $params['twitter_site'] ); |
| 156 | if ( false === $twitter_id ) { |
| 157 | $this->invalid_urls[] = 'twitter_site'; |
| 158 | unset( $params['twitter_site'] ); |
| 159 | } else { |
| 160 | $params['twitter_site'] = $twitter_id; |
| 161 | } |
| 162 | } |
| 163 | break; |
| 164 | case 'other_social_urls': |
| 165 | $filtered_social_urls = array(); |
| 166 | foreach ( $param_value as $param_key_osu => $param_url ) { |
| 167 | if ( ! empty( $param_url ) ) { |
| 168 | if ( \wp_http_validate_url( $param_url ) ) { |
| 169 | $filtered_social_urls[] = \sanitize_text_field( $param_url ); |
| 170 | } else { |
| 171 | $this->invalid_urls[] = $param_key_osu; |
| 172 | } |
| 173 | } |
| 174 | } |
| 175 | $params[ $param_key ] = $filtered_social_urls; |
| 176 | break; |
| 177 | default: |
| 178 | $param[ $param_key ] = \sanitize_text_field( $param_value ); |
| 179 | if ( ! empty( $param_value ) && ! \wp_http_validate_url( $param_value ) ) { |
| 180 | $this->invalid_urls[] = $param_key; |
| 181 | unset( $params[ $param_key ] ); |
| 182 | } |
| 183 | break; |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | $settings = array_merge( $settings, $params ); |
| 188 | |
| 189 | \update_option( Options::get_option_name( 'wpseo_social', false ), $settings ); |
| 190 | |
| 191 | if ( ! empty( $this->invalid_urls ) ) { |
| 192 | $error_keys = implode( ', ', $this->invalid_urls ); |
| 193 | return new \WP_Error( |
| 194 | 'invalid_urls', |
| 195 | "Invalid url(s) provided for {$error_keys}.", |
| 196 | array( 'status' => 400 ) |
| 197 | ); |
| 198 | } |
| 199 | return $this->get_item(); |
| 200 | } |
| 201 | |
| 202 | /** |
| 203 | * Retrieve the existing saved array of settings |
| 204 | * |
| 205 | * @return array $settings List of the settings and their values |
| 206 | */ |
| 207 | public function get_current_settings() { |
| 208 | |
| 209 | $social_data = \get_option( Options::get_option_name( 'wpseo_social', false ), false ); |
| 210 | // incase yoast plugin is not installed then we need to save the values in the yoast_wp_options_key |
| 211 | if ( false === $social_data ) { |
| 212 | |
| 213 | // initialize an array with default values |
| 214 | $social_data = $this->defaults; |
| 215 | |
| 216 | // update database |
| 217 | \add_option( Options::get_option_name( 'wpseo_social', false ), $social_data ); |
| 218 | } |
| 219 | // add the full url for twitter cause only the handle is saved in the database |
| 220 | $twitter_handle = $this->validate_twitter_id( $social_data['twitter_site'] ); |
| 221 | if ( ( ! empty( $social_data['twitter_site'] ) ) && ( false !== $twitter_handle ) ) { |
| 222 | $social_data['twitter_site'] = 'https://www.twitter.com/' . $twitter_handle; |
| 223 | } |
| 224 | |
| 225 | $filtered_social_urls = array(); |
| 226 | // handle other social urls for onboarding |
| 227 | foreach ( $social_data['other_social_urls'] as $index => $social_url ) { |
| 228 | if ( ! empty( $social_url ) ) { |
| 229 | if ( preg_match( '/(?:https?:\/\/)?(www\.)?yelp\.com/', $social_url ) ) { |
| 230 | $filtered_social_urls['yelp_url'] = $social_url; |
| 231 | } elseif ( preg_match( '/(?:https?:\/\/)?(www\.)?tiktok\.com/', $social_url ) ) { |
| 232 | $filtered_social_urls['tiktok_url'] = $social_url; |
| 233 | } else { |
| 234 | $filtered_social_urls[ 'social_url_' . $index ] = $social_url; |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | $social_data['other_social_urls'] = $filtered_social_urls; |
| 239 | return $social_data; |
| 240 | } |
| 241 | |
| 242 | /** |
| 243 | * Initialize WordPress Options, Permalinks and Configuration. |
| 244 | * |
| 245 | * @return \WP_REST_Response |
| 246 | */ |
| 247 | public function initialize() { |
| 248 | |
| 249 | if ( \get_option( Options::get_option_name( 'settings_initialized' ), false ) ) { |
| 250 | return new \WP_REST_Response( |
| 251 | array(), |
| 252 | 200 |
| 253 | ); |
| 254 | } |
| 255 | |
| 256 | // Update wp_options |
| 257 | $init_options = Options::get_initialization_options(); |
| 258 | foreach ( $init_options as $option_key => $option_value ) { |
| 259 | \update_option( Options::get_option_name( $option_key, false ), $option_value ); |
| 260 | } |
| 261 | // Can't be part of initialization constants as they are static. |
| 262 | \update_option( Options::get_option_name( 'start_date' ), gmdate( 'U' ) ); |
| 263 | |
| 264 | // Flush permalinks |
| 265 | flush_rewrite_rules(); |
| 266 | |
| 267 | // Add constants to the WordPress configuration (wp-config.php) |
| 268 | $wp_config_constants = Config::get_wp_config_initialization_constants(); |
| 269 | $wp_config = new WP_Config(); |
| 270 | foreach ( $wp_config_constants as $constant_key => $constant_value ) { |
| 271 | if ( $wp_config->constant_exists( $constant_key ) ) { |
| 272 | $wp_config->update_constant( $constant_key, $constant_value ); |
| 273 | continue; |
| 274 | } |
| 275 | $wp_config->add_constant( $constant_key, $constant_value ); |
| 276 | } |
| 277 | |
| 278 | \update_option( Options::get_option_name( 'settings_initialized' ), true ); |
| 279 | |
| 280 | return new \WP_REST_Response( |
| 281 | array(), |
| 282 | 201 |
| 283 | ); |
| 284 | } |
| 285 | |
| 286 | /** |
| 287 | * Validates a twitter id. |
| 288 | * |
| 289 | * @param string $twitter_id The twitter id to be validated. |
| 290 | * @param bool $strip_at_sign Whether or not to strip the `@` sign. |
| 291 | * |
| 292 | * @return string|false The validated twitter id or false if it is not valid. |
| 293 | */ |
| 294 | private function validate_twitter_id( $twitter_id, $strip_at_sign = true ) { |
| 295 | $twitter_id = ( $strip_at_sign ) ? sanitize_text_field( ltrim( $twitter_id, '@' ) ) : sanitize_text_field( $twitter_id ); |
| 296 | |
| 297 | /* |
| 298 | * From the Twitter documentation about twitter screen names: |
| 299 | * Typically a maximum of 15 characters long, but some historical accounts may exist with longer names. |
| 300 | * A username can only contain alphanumeric characters (letters A-Z, numbers 0-9) with the exception of underscores. |
| 301 | * |
| 302 | * @link https://support.twitter.com/articles/101299-why-can-t-i-register-certain-usernames |
| 303 | */ |
| 304 | if ( preg_match( '`^[A-Za-z0-9_]{1,25}$`', $twitter_id ) ) { |
| 305 | return $twitter_id; |
| 306 | } |
| 307 | |
| 308 | if ( preg_match( '`^http(?:s)?://(?:www\.)?twitter\.com/(?P<handle>[A-Za-z0-9_]{1,25})/?$`', $twitter_id, $matches ) ) { |
| 309 | return $matches['handle']; |
| 310 | } |
| 311 | |
| 312 | return false; |
| 313 | } |
| 314 | } |