File "onboarding.php"
Full Path: /home/fresvfqn/waterdamagerestorationandrepairsmithtown.com/wp-content/plugins/surerank/inc/api/onboarding.php
File size: 17.67 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Onboarding class
*
* Handles onboarding related REST API endpoints for the SureRank plugin.
*
* @package SureRank\Inc\API
*/
namespace SureRank\Inc\API;
use SureRank\Inc\Admin\Update_Timestamp;
use SureRank\Inc\Functions\Requests;
use SureRank\Inc\Functions\Send_Json;
use SureRank\Inc\Functions\Settings;
use SureRank\Inc\Functions\Update;
use SureRank\Inc\Traits\Get_Instance;
use WP_REST_Request;
use WP_REST_Server;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
const DEFAULT_USER_DETAILS = [
'first_name' => '',
'last_name' => '',
'email' => '',
'skip' => 'no',
'lead' => false,
];
/**
* Class Onboarding
*
* Handles onboarding related REST API endpoints.
*/
class Onboarding extends Api_Base {
use Get_Instance;
/**
* Route Onboarding
*/
protected const ONBOARDING = '/onboarding';
/**
* Register API routes.
*
* @since 1.0.0
* @return void
*/
public function register_routes() {
register_rest_route(
$this->get_api_namespace(),
self::ONBOARDING,
[
'methods' => WP_REST_Server::CREATABLE,
'callback' => [ $this, 'save_website_details' ],
'permission_callback' => [ $this, 'validate_permission' ],
'args' => [
'first_name' => [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'required' => false,
'validate_callback' => static function( $value ) {
return is_string( $value );
},
],
'last_name' => [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'required' => false,
'validate_callback' => static function( $value ) {
return is_string( $value );
},
],
'email' => [
'type' => 'string',
'sanitize_callback' => 'sanitize_email',
'required' => false,
'validate_callback' => static function( $value ) {
return filter_var( $value, FILTER_VALIDATE_EMAIL ) !== false;
},
],
'website_type' => [
'type' => 'string',
'required' => false,
'description' => __( 'Type of the website.', 'surerank' ),
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => static function( $value ) {
return is_string( $value );
},
],
'website_name' => [
'type' => 'string',
'required' => false,
'description' => __( 'Name of the website.', 'surerank' ),
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => static function( $value ) {
return is_string( $value );
},
],
'website_owner_name' => [
'type' => 'string',
'required' => false,
'description' => __( 'Name of the website owner.', 'surerank' ),
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => static function( $value ) {
return is_string( $value );
},
],
'website_owner_phone' => [
'type' => 'string',
'required' => false,
'description' => __( 'Phone number of the website owner.', 'surerank' ),
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => static function( $value ) {
return is_string( $value );
},
],
'organization_type' => [
'type' => 'string',
'required' => false,
'description' => __( 'Type of the organization.', 'surerank' ),
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => static function( $value ) {
return is_string( $value );
},
],
'about_page' => [
'type' => 'integer',
'required' => false,
'sanitize_callback' => 'absint',
],
'contact_page' => [
'type' => 'integer',
'required' => false,
'sanitize_callback' => 'absint',
],
'social_profiles' => [
'type' => 'object',
'required' => false,
'description' => __( 'Social profiles URLs.', 'surerank' ),
'properties' => array_fill_keys(
self::get_social_profile_keys(),
[
'type' => 'string',
'sanitize_callback' => 'esc_url_raw',
'validate_callback' => static function( $value ) {
return filter_var( $value, FILTER_VALIDATE_URL ) !== false;
},
]
),
],
'website_logo' => [
'type' => 'string',
'required' => false,
],
],
]
);
}
/**
* Update common onboarding data.
*
* @since 1.0.0
* @param array<string, mixed> $data Onboarding data.
* @return bool
*/
public static function update_common_onboarding_data( $data ) {
if ( empty( $data ) ) {
return false;
}
$instance = self::get_instance();
$defaults = [
'website_type' => '',
'website_name' => '',
'website_owner_name' => '',
'organization_type' => 'Organization',
'website_owner_phone' => '',
'website_logo' => '',
'first_name' => '',
'last_name' => '',
'email' => '',
'about_page' => 0,
'contact_page' => 0,
'social_profiles' => [],
];
$data = wp_parse_args(
$data,
$defaults
);
$settings = Settings::get();
$instance->set_onboarding_data( $data, $settings );
$updated_onboarding = $instance->process_onboarding_data( $data, $settings );
$updated_settings = Update::option( SURERANK_SETTINGS, $settings );
if ( $updated_onboarding && $updated_settings ) {
$instance->set_schemas_pages( $data, $settings );
Update_Timestamp::timestamp_option();
return true;
}
return false;
}
/**
* Save Website Details
*
* @since 1.0.0
* @param WP_REST_Request<array<string, mixed>> $request Request object.
* @return void
*/
public function save_website_details( $request ) {
$data = $request->get_params();
if ( empty( $data ) ) {
Send_Json::error( [ 'message' => __( 'Invalid data provided', 'surerank' ) ] );
}
if ( self::update_common_onboarding_data( $data ) ) {
Send_Json::success( [ 'message' => __( 'Settings updated successfully', 'surerank' ) ] );
}
Update::option( 'surerank_onboarding_completed', true );
Send_Json::error( [ 'message' => __( 'Failed to update settings', 'surerank' ) ] );
}
/**
* Set Schemas Pages
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return void
*/
public function set_schemas_pages( $data, $settings ) {
$this->set_about_page( $data, $settings );
$this->set_contact_page( $data, $settings );
}
/**
* Set About Page
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return bool|int
*/
public function set_about_page( $data, &$settings ) {
$about_page = $data['about_page'] ?? 0;
if ( ! $about_page ) {
return false;
}
$default_schemas = Settings::prepare_schemas( $settings, 'page', $about_page, true );
$schema = $this->find_schema_by_type( $settings, 'WebPage' );
$default_schemas[ $schema ]['fields']['@type'] = 'AboutPage';
$default_schemas[ $schema ]['type'] = 'AboutPage';
$schemas = [
'schemas' => $default_schemas,
];
return Update::post_meta( $about_page, 'surerank_settings_schemas', $schemas );
}
/**
* Set Contact Page
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return bool|int
*/
public function set_contact_page( $data, &$settings ) {
$contact_page = $data['contact_page'] ?? 0;
if ( ! $contact_page ) {
return false;
}
$default_schemas = Settings::prepare_schemas( $settings, 'page', $contact_page, true );
$schema = $this->find_schema_by_type( $settings, 'WebPage' );
$default_schemas[ $schema ]['fields']['@type'] = 'ContactPage';
$default_schemas[ $schema ]['type'] = 'ContactPage';
$schemas = [
'schemas' => $default_schemas,
];
return Update::post_meta( $contact_page, 'surerank_settings_schemas', $schemas );
}
/**
* Save Onboarding Data
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @return bool
*/
public function save_onboarding_data( $data ) {
return Update::option( 'surerank_settings_onboarding', $data );
}
/**
* Set Website Details
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return void
*/
public function set_website_details( $data, &$settings ) {
$this->update_schema_field( $settings, 'Organization', 'name', $data['website_name'] );
$this->update_schema_field( $settings, 'Organization', '@type', $data['organization_type'] );
$this->update_schema_field( $settings, 'Organization', 'logo', $data['website_logo'] );
$this->update_schema_field( $settings, 'Organization', 'telephone', $data['website_owner_phone'] );
$this->update_schema_field( $settings, 'Organization', 'email', $data['email'] );
$this->update_schema_field( $settings, 'Person', 'name', $data['website_owner_name'] );
$this->update_schema_field( $settings, 'Person', 'image', $data['website_logo'] );
$sanitized_name = sanitize_text_field( $data['website_name'] );
update_option( 'blogname', $sanitized_name );
}
/**
* Update Schema Field
*
* @since 1.0.0
* @param array<string, mixed> $settings Settings.
* @param string $schema_type Schema type.
* @param string $field Field name.
* @param mixed $value Field value.
* @return void
*/
public function update_schema_field( &$settings, $schema_type, $field, $value ) {
$schema_id = $this->find_schema_by_type( $settings, $schema_type );
if ( is_null( $schema_id ) ) {
return; // Bail early if schema is not found.
}
if ( ! isset( $settings['schemas'][ $schema_id ]['fields'] ) ) {
$settings['schemas'][ $schema_id ]['fields'] = [];
}
$settings['schemas'][ $schema_id ]['fields'][ $field ] = $value;
}
/**
* Find Schema by Type
*
* @since 1.0.0
* @param array<string, mixed> $settings Settings array.
* @param string $type Schema type to find.
* @return string|null Schema ID if found, null otherwise.
*/
public function find_schema_by_type( &$settings, $type ) {
if ( isset( $settings['schemas'] ) && is_array( $settings['schemas'] ) ) {
foreach ( $settings['schemas'] as $schema_id => $schema ) {
if ( isset( $schema['type'] ) && $schema['type'] === $type ) {
return $schema_id;
}
}
}
return null;
}
/**
* Person or Organization
*
* @since 1.0.0
* @param string $website_type Website type.
* @return string
*/
public function person_or_organization( $website_type ) {
return in_array( $website_type, [ 'blog', 'personal' ] ) ? 'person' : 'organization';
}
/**
* Get Social Profile Keys
*
* @since 1.0.0
* @return array<string, mixed>|array<int, array<string, mixed>>
*/
public static function get_social_profile_keys() {
return array_column( self::social_profiles(), 'id' );
}
/**
* Set Social Profiles
*
* @since 1.0.0
* @return array<string, mixed>
*/
public static function social_profiles() {
return apply_filters(
'surerank_social_profiles',
[
[
'label' => 'Facebook',
'id' => 'facebook',
'placeholder' => 'https://www.facebook.com/my-page-url',
'show_in_dashboard' => false,
],
[
'label' => 'X',
'id' => 'twitter',
'placeholder' => 'https://x.com/myaccount',
'show_in_dashboard' => false,
],
[
'label' => 'Instagram',
'id' => 'instagram',
'placeholder' => 'https://www.instagram.com/my-page-url',
],
[
'label' => 'YouTube',
'id' => 'youtube',
'placeholder' => 'https://www.youtube.com/my-channel-url',
],
[
'label' => 'LinkedIn',
'id' => 'linkedin',
'placeholder' => 'https://www.linkedin.com/company/my-company',
],
[
'label' => 'TikTok',
'id' => 'tiktok',
'placeholder' => 'https://www.tiktok.com/@username',
],
[
'label' => 'Pinterest',
'id' => 'pinterest',
'placeholder' => 'https://www.pinterest.com/my-page-url',
],
[
'label' => 'WhatsApp',
'id' => 'whatsapp',
'placeholder' => 'https://wa.me/number',
],
[
'label' => 'Telegram',
'id' => 'telegram',
'placeholder' => 'https://t.me/username',
],
[
'label' => 'Yelp',
'id' => 'yelp',
'placeholder' => 'https://www.yelp.com/biz/business-name-location',
],
[
'label' => 'BlueSky',
'id' => 'bluesky',
'placeholder' => 'https://bsky.app/profile/username',
],
]
);
}
/**
* Set Social Schema
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return void
*/
public function set_social_schema( $data, &$settings ) {
$same_as_urls = array_filter(
$data['social_profiles'] ?? [],
static function( $url ) {
return ! empty( $url );
}
);
$this->update_schema_field( $settings, 'Organization', 'sameAs', $same_as_urls );
}
/**
* Retrieves the value of a specific key from the 'surerank_onboarding_user_details' option.
*
* @param string $key The key to retrieve from the settings.
* @param mixed $default The default value to return if the key does not exist.
* @since 1.0.0
* @return mixed The value of the specified key or the default value.
*/
public function get_user_details( ?string $key = null, $default = null ) {
$settings = wp_parse_args( get_option( 'surerank_onboarding_user_details', [] ), DEFAULT_USER_DETAILS );
if ( $key === null ) {
return $settings;
}
if ( is_array( $settings ) && array_key_exists( $key, $settings ) ) {
return $settings[ $key ];
}
return $default;
}
/**
* Sets the value of the 'surerank_onboarding_user_details' option.
*
* @param mixed $details The value to save.
* @since 1.0.0
* @return void
*/
public function set_user_details( $details ) {
update_option( 'surerank_onboarding_user_details', wp_parse_args( $details, DEFAULT_USER_DETAILS ) );
}
/**
* Set Onboarding Data
*
* We need to store the facebook page url and twitter profile username in the settings array as per the new requirement.
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return void
*/
private function set_onboarding_data( $data, &$settings ) {
$settings['facebook_page_url'] = $data['social_profiles']['facebook'] ?? '';
$settings['twitter_profile_username'] = $data['social_profiles']['twitter'] ?? '';
}
/**
* Process Onboarding Data
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return bool
*/
private function process_onboarding_data( $data, &$settings ) {
$this->set_website_details( $data, $settings );
$this->set_social_schema( $data, $settings );
$this->set_social_profiles( $data, $settings );
$lead = [
'email' => $data['email'] ?? '',
'first_name' => $data['first_name'] ?? '',
'last_name' => $data['last_name'] ?? '',
];
$this->generate_lead( $lead );
$this->set_person_or_organization( $data, $settings );
return $this->save_onboarding_data( $data );
}
/**
* Set Person or Organization.
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return void
*/
private function set_person_or_organization( &$data, &$settings ) {
$type = $this->person_or_organization( $data['website_type'] );
$data['person_or_organization'] = $type;
/**
* Depending on the type, we need to set the publisher to the correct schema.
* We need to set the publisher for WebPage and Article.
*/
$schema = $type === 'organization' ? '%schemas.organization%' : '%schemas.person%';
foreach ( [ 'WebPage', 'Article' ] as $context ) {
$this->update_schema_field( $settings, $context, 'publisher', $schema );
}
}
/**
* Set Social Profiles
*
* @since 1.0.0
* @param array<string, mixed> $data Data.
* @param array<string, mixed> $settings Settings.
* @return void
*/
private function set_social_profiles( &$data, &$settings ) {
$settings['social_profiles'] = $data['social_profiles'];
unset( $data['social_profiles'] );
}
/**
* Generate Lead
*
* @since 1.0.0
* @param array<string,string> $lead Website data.
* @return void
*/
private function generate_lead( $lead ) {
$subscription_status = $this->get_user_details( 'lead', false );
if ( $subscription_status ) {
return;
}
if ( empty( $lead['email'] ) || empty( $lead['first_name'] ) ) {
return;
}
$url = 'https://websitedemos.net/wp-json/surerank/v1/subscribe/';
$args = [
'body' => [
'EMAIL' => $lead['email'],
'FIRSTNAME' => $lead['first_name'],
'LASTNAME' => $lead['last_name'] ?? '',
],
];
$response = Requests::post( $url, $args );
if ( ! is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) === 200 ) {
$response = json_decode( wp_remote_retrieve_body( $response ), true );
$lead['lead'] = true;
$this->set_user_details( $lead );
}
}
}