<?php
/**
 * Locator: where the Gravity Forms upload base lives, what serves it, and
 * whether Gravity Forms itself is present.
 *
 * The upload directory outlives the form plugin — files stay (and stay
 * reachable) even when Gravity Forms is deactivated or deleted. Everything
 * here therefore works from the directory itself; Gravity Forms only makes
 * the answers richer (form titles, entry links).
 *
 * @package Upload_Vault
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Uvgf_Locator
 */
class Uvgf_Locator {

	/**
	 * Is Gravity Forms active?
	 *
	 * @return bool
	 */
	public static function gf_active() {
		return class_exists( 'GFForms' );
	}

	/**
	 * Absolute path of the Gravity Forms upload base (no trailing slash).
	 *
	 * Prefers Gravity Forms' own answer (it honours the gform_upload_path
	 * filter); falls back to the documented default location.
	 *
	 * @return string
	 */
	public static function base_dir() {
		$dir = '';

		if ( class_exists( 'GFFormsModel' ) && is_callable( array( 'GFFormsModel', 'get_upload_root' ) ) ) {
			$dir = (string) GFFormsModel::get_upload_root();
		}

		if ( '' === $dir ) {
			$uploads = wp_upload_dir( null, false );
			$dir     = trailingslashit( (string) $uploads['basedir'] ) . 'gravity_forms';
		}

		$dir = untrailingslashit( wp_normalize_path( $dir ) );

		/**
		 * Filter the resolved Gravity Forms upload base directory.
		 *
		 * @param string $dir Absolute path, no trailing slash.
		 */
		return apply_filters( 'uvgf_base_dir', $dir );
	}

	/**
	 * Public URL of the upload base (no trailing slash).
	 *
	 * @return string
	 */
	public static function base_url() {
		$url = '';

		if ( class_exists( 'GFFormsModel' ) && is_callable( array( 'GFFormsModel', 'get_upload_url_root' ) ) ) {
			$url = untrailingslashit( (string) GFFormsModel::get_upload_url_root() );
		}

		if ( '' === $url ) {
			$uploads = wp_upload_dir( null, false );
			$url     = untrailingslashit( (string) $uploads['baseurl'] ) . '/gravity_forms';
		}

		/**
		 * Filter the resolved Gravity Forms upload base URL.
		 *
		 * @param string $url URL, no trailing slash.
		 */
		return apply_filters( 'uvgf_base_url', $url );
	}

	/**
	 * Does the base directory exist (i.e. has anything ever been uploaded)?
	 *
	 * @return bool
	 */
	public static function base_exists() {
		return is_dir( self::base_dir() );
	}

	/**
	 * Web server family, for tailoring protection guidance.
	 *
	 * @return string apache|litespeed|nginx|iis|unknown
	 */
	public static function server_type() {
		global $is_apache, $is_nginx, $is_IIS, $is_iis7;

		$software = isset( $_SERVER['SERVER_SOFTWARE'] ) ? strtolower( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) ) : '';

		if ( false !== strpos( $software, 'litespeed' ) ) {
			return 'litespeed';
		}
		if ( ! empty( $is_apache ) || false !== strpos( $software, 'apache' ) ) {
			return 'apache';
		}
		if ( ! empty( $is_nginx ) || false !== strpos( $software, 'nginx' ) ) {
			return 'nginx';
		}
		if ( ! empty( $is_IIS ) || ! empty( $is_iis7 ) || false !== strpos( $software, 'microsoft-iis' ) ) {
			return 'iis';
		}
		return 'unknown';
	}

	/**
	 * Does .htaccess apply on this server?
	 *
	 * @return bool
	 */
	public static function htaccess_applies() {
		return in_array( self::server_type(), array( 'apache', 'litespeed' ), true );
	}

	/**
	 * Form titles (id => title) when Gravity Forms is available.
	 *
	 * @return array
	 */
	public static function form_titles() {
		$titles = array();
		if ( class_exists( 'GFAPI' ) && is_callable( array( 'GFAPI', 'get_forms' ) ) ) {
			$forms = GFAPI::get_forms( null ); // Active + inactive; uploads outlive form state.
			if ( is_array( $forms ) ) {
				foreach ( $forms as $form ) {
					if ( isset( $form['id'] ) ) {
						$titles[ (int) $form['id'] ] = isset( $form['title'] ) ? (string) $form['title'] : '';
					}
				}
			}
		}
		return $titles;
	}

	/**
	 * The nginx server-block snippet for this site's upload base.
	 *
	 * @return string
	 */
	public static function nginx_snippet() {
		$path = wp_parse_url( self::base_url(), PHP_URL_PATH );
		$path = $path ? $path : '/wp-content/uploads/gravity_forms';
		return "location ^~ {$path}/ {\n    deny all;\n    return 403;\n}";
	}

	/**
	 * The IIS web.config snippet for this site's upload base.
	 *
	 * @return string
	 */
	public static function iis_snippet() {
		return "<configuration>\n  <system.webServer>\n    <security>\n      <authorization>\n        <remove users=\"*\" roles=\"\" verbs=\"\" />\n      </authorization>\n    </security>\n  </system.webServer>\n</configuration>";
	}
}
