HEX
Server: nginx
System: Linux pool195-106-36.bur.atomicsites.net 6.12.57+deb12-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.57-1~bpo12+1 (2025-11-17) x86_64
User: (0)
PHP: 8.3.32
Disabled: pcntl_fork
Upload Files
File: //wordpress/plugins/wp-cloud-client/1.1.9/src/Settings/SettingsRepository.php
<?php

declare(strict_types=1);

namespace VPlugins\WPCloudClient\Settings;

class SettingsRepository {

	private const OPTION_KEY = 'wpcc_settings';

	/**
	 * Retrieve the configured site ID (9-char WP Cloud / Atomic site ID).
	 *
	 * Resolution order:
	 *  1. Atomic_Persistent_Data::ATOMIC_SITE_ID — platform-managed.
	 *  2. ATOMIC_SITE_ID constant                — direct platform constant.
	 *  3. wpcc_site_id filter                    — last-resort hook.
	 *
	 * @return string|null Site ID or null if not resolvable.
	 */
	public function getSiteId(): ?string {
		if ( class_exists( 'Atomic_Persistent_Data' ) ) {
			$persistent = new \Atomic_Persistent_Data();
			$v          = trim( (string) ( $persistent->ATOMIC_SITE_ID ?? '' ) );
			if ( '' !== $v ) {
				return $v;
			}
		}

		if ( \defined( 'ATOMIC_SITE_ID' ) && is_scalar( \ATOMIC_SITE_ID ) ) {
			$v = (string) \ATOMIC_SITE_ID;
			return '' !== $v ? $v : null;
		}

		try {
			$value = (string) apply_filters( 'wpcc_site_id', '' );
		} catch ( \Throwable $e ) {
			error_log( '[WP Cloud Client] wpcc_site_id filter threw: ' . $e->getMessage() );
			return null;
		}
		return '' !== $value ? $value : null;
	}

	/**
	 * Retrieve the Vendasta site ID (64-char VStore PK) for GA4 tracking.
	 *
	 * @return string|null Vendasta site ID or null if not set.
	 */
	public function getVendastaSiteId(): ?string {
		if ( class_exists( 'Atomic_Persistent_Data' ) ) {
			$persistent = new \Atomic_Persistent_Data();
			$v          = trim( (string) ( $persistent->WSP_SITE_ID ?? '' ) );
			if ( '' !== $v ) {
				return $v;
			}
		}
		return null;
	}

	/**
	 * Retrieve the configured API key.
	 *
	 * Resolution order:
	 *  1. WSP_API_KEY constant       — explicit override (wp-config.php or mu-plugin).
	 *  2. Atomic_Persistent_Data    — platform-managed, not in DB; survives staging→prod pushes.
	 *  3. wpcc_api_key filter       — last-resort hook.
	 *
	 * @return string|null API key or null if not set.
	 */
	public function getApiKey(): ?string {
		if ( \defined( 'WSP_API_KEY' ) && is_scalar( \WSP_API_KEY ) ) {
			$v = (string) \WSP_API_KEY;
			return '' !== $v ? $v : null;
		}

		if ( class_exists( 'Atomic_Persistent_Data' ) ) {
			$persistent = new \Atomic_Persistent_Data();
			$v          = trim( (string) ( $persistent->WSP_API_KEY ?? '' ) );
			if ( '' !== $v ) {
				return $v;
			}
		}

		try {
			$value = (string) apply_filters( 'wpcc_api_key', '' );
		} catch ( \Throwable $e ) {
			error_log( '[WP Cloud Client] wpcc_api_key filter threw: ' . $e->getMessage() );
			return null;
		}
		return '' !== $value ? $value : null;
	}

	/**
	 * Retrieve the configured environment.
	 *
	 * Reads WSP_SITE_ENVIRONMENT from Atomic_Persistent_Data (PROD or DEMO).
	 * Defaults to 'PROD' if the value is absent.
	 *
	 * @return string Environment value ('PROD' or 'DEMO').
	 */
	public function getEnvironment(): string {
		if ( class_exists( 'Atomic_Persistent_Data' ) ) {
			$persistent = new \Atomic_Persistent_Data();
			$value      = trim( (string) ( $persistent->WSP_SITE_ENVIRONMENT ?? '' ) );
			if ( '' !== $value ) {
				return $value;
			}
		}

		return 'PROD';
	}

	/**
	 * Check whether this site is a multisite installation.
	 *
	 * Reads WSP_SITE_TYPE from Atomic_Persistent_Data (SINGLE or MULTISITE).
	 * Defaults to false (single site) if not set.
	 *
	 * @return bool True if the site type is MULTISITE.
	 */
	public function isMultisite(): bool {
		if ( class_exists( 'Atomic_Persistent_Data' ) ) {
			$persistent = new \Atomic_Persistent_Data();
			$value      = strtoupper( trim( (string) ( $persistent->WSP_SITE_TYPE ?? '' ) ) );
			return 'MULTISITE' === $value;
		}

		return false;
	}

	/**
	 * Check whether this site is a staging site.
	 *
	 * Reads WSP_STAGING from Atomic_Persistent_Data (TRUE or FALSE).
	 * Defaults to false if not set.
	 *
	 * @return bool True if staging is enabled.
	 */
	public function isStaging(): bool {
		if ( class_exists( 'Atomic_Persistent_Data' ) ) {
			$persistent = new \Atomic_Persistent_Data();
			$value      = strtoupper( trim( (string) ( $persistent->WSP_STAGING ?? '' ) ) );
			return 'TRUE' === $value;
		}

		return false;
	}

	/**
	 * Retrieve the custom GA4 tracking ID.
	 *
	 * @return string|null Tracking ID or null if not set.
	 */
	public function getGa4TrackingId(): ?string {
		return $this->get( 'ga4_tracking_id' );
	}

	/**
	 * Check whether debug mode is enabled.
	 *
	 * @return bool True if debug mode is on.
	 */
	public function isDebugMode(): bool {
		return (bool) $this->get( 'debug_mode' );
	}

	/**
	 * Check whether the wp-login.php page is exposed.
	 *
	 * Mirrors the bootstrapper's WSP_EXPOSE_WP_LOGIN behaviour: defaults to
	 * false (login hidden) so direct access is redirected away unless the
	 * manager has explicitly exposed it.
	 *
	 * @return bool True if the login page is exposed, false if hidden.
	 */
	public function isLoginExposed(): bool {
		return (bool) $this->get( 'expose_login' );
	}

	/**
	 * Set whether the wp-login.php page is exposed.
	 *
	 * @param bool $exposed True to expose the login page, false to hide it.
	 * @return bool True if the option was updated, false on failure.
	 */
	public function setLoginExposed( bool $exposed ): bool {
		return $this->update( [ 'expose_login' => $exposed ? '1' : '' ] );
	}

	/**
	 * Retrieve the redirect URL for hidden login page access attempts.
	 *
	 * @return string Redirect URL, or empty string if not set.
	 */
	public function getLoginRedirectUrl(): string {
		return (string) $this->get( 'login_redirect_url' );
	}

	/**
	 * Set the redirect URL for hidden login page access attempts.
	 *
	 * @param string $url URL to redirect unauthenticated visitors to.
	 * @return bool True if the option was updated, false on failure.
	 */
	public function setLoginRedirectUrl( string $url ): bool {
		return $this->update( [ 'login_redirect_url' => $url ] );
	}

	/**
	 * Retrieve the WP Cloud Manager base URL.
	 *
	 * Checks the WPCC_MANAGER_URL constant first, then falls back to the
	 * wpcc_manager_url filter so the value can be supplied by the hosting
	 * environment without touching the database.
	 *
	 * @return string Manager base URL, or empty string if not configured.
	 */
	public function getManagerUrl(): string {
		if ( \defined( 'WPCC_MANAGER_URL' ) ) {
			return (string) \WPCC_MANAGER_URL;
		}

		return (string) apply_filters( 'wpcc_manager_url', '' );
	}

	/**
	 * Check whether all required credentials are configured.
	 *
	 * @return bool True if site ID and API key are set.
	 */
	public function isConfigured(): bool {
		return $this->getSiteId() !== null
			&& $this->getApiKey() !== null;
	}

	/**
	 * Update settings by merging with existing values.
	 *
	 * @param array $values Key-value pairs to update.
	 * @return bool True if the option was updated, false on failure.
	 */
	public function update( array $values ): bool {
		$current = $this->all();
		return (bool) update_option( self::OPTION_KEY, array_merge( $current, $values ) );
	}

	/**
	 * Remove specific keys from stored settings.
	 *
	 * Used for migrations to clean up stale keys from previous versions.
	 *
	 * @param array $keys Keys to remove.
	 */
	public function purge( array $keys ): void {
		$current = $this->all();
		foreach ( $keys as $key ) {
			unset( $current[ $key ] );
		}
		update_option( self::OPTION_KEY, $current );
	}

	/**
	 * Retrieve all settings as an array.
	 *
	 * @return array All stored settings.
	 */
	public function all(): array {
		return (array) get_option( self::OPTION_KEY, [] );
	}

	/**
	 * Retrieve a single setting value by key.
	 *
	 * @param string $key Setting key to retrieve.
	 * @return string|null Setting value or null if empty.
	 */
	private function get( string $key ): ?string {
		$settings = $this->all();
		$value    = isset( $settings[ $key ] ) ? trim( (string) $settings[ $key ] ) : null;
		return null !== $value && '' !== $value ? $value : null;
	}
}