<?php
/**
 * Genesis Framework.
 *
 * WARNING: This file is part of the core Genesis Framework. DO NOT edit this file under any circumstances.
 * Please do all modifications in the form of a child theme.
 *
 * @package StudioPress\Genesis
 * @author  StudioPress
 * @license GPL-2.0-or-later
 * @link    https://my.studiopress.com/themes/genesis/
 */

/**
 * Check and updates server for update information.
 *
 * Uses the WordPress HTTP API to check an external url for update information.
 * Data returned can be saved to a transient to avoid http calls on every page load.
 *
 * @since 2.7.0
 */
class Genesis_Update_Check {

	/**
	 * POST URL key.
	 *
	 * @var string
	 *
	 * @since 2.7.0
	 */
	const POST_URL_KEY = 'post_url';

	/**
	 * POST args key.
	 *
	 * @var string
	 *
	 * @since 2.7.0
	 */
	const POST_ARGS_KEY = 'post_args';

	/**
	 * Required data key
	 *
	 * @var string
	 *
	 * @since 2.7.0
	 */
	const REQ_DATA_KEY = 'req_data_keys';

	/**
	 * URL to POST to.
	 *
	 * @var string
	 *
	 * @since 2.7.0
	 */
	protected $post_url;

	/**
	 * Args used to build the POST request.
	 *
	 * @var array
	 *
	 * @since 2.7.0
	 */
	protected $post_args;

	/**
	 * Required data keys.
	 *
	 * @var array
	 *
	 * @since 2.7.0
	 */
	protected $req_data_keys;

	/**
	 * The results of an update check.
	 *
	 * @var array
	 *
	 * @since 2.7.0
	 */
	protected $update = [];

	/**
	 * Constructor.
	 *
	 * @since 2.7.0
	 *
	 * @param array $config The configuration array used to build the server request and process the response.
	 */
	public function __construct( array $config ) {

		$this->post_url      = $config[ self::POST_URL_KEY ];
		$this->post_args     = $config[ self::POST_ARGS_KEY ];
		$this->req_data_keys = isset( $config[ self::REQ_DATA_KEY ] ) ? $config[ self::REQ_DATA_KEY ] : [];

	}

	/**
	 * Retrieve and assemble update information and return the array.
	 *
	 * @since 2.7.0
	 *
	 * @return array Array of update information.
	 */
	public function get_update() {

		// If we've already done the work, return.
		if ( $this->update ) {
			return $this->update;
		}

		$this->update = $this->validate_response( maybe_unserialize( $this->get_response_body() ) );

		return $this->update;

	}

	/**
	 * Validate the format and data of the update response.
	 *
	 * @param array $response The response to validate.
	 * @return array Empty array if invalid, otherwise unaltered response.
	 */
	protected function validate_response( $response ) {

		if ( ! is_array( $response ) ) {
			return [];
		}

		foreach ( $this->req_data_keys as $req ) {
			if ( ! array_key_exists( $req, $response ) ) {
				return [];
			}
		}

		return $response;

	}

	/**
	 * Get the POST response.
	 *
	 * @since 2.7.0
	 *
	 * @return WP_Error|array The response or WP_Error on failure.
	 */
	protected function get_response() {
		return wp_remote_post( $this->post_url, $this->post_args );
	}

	/**
	 * Get the body of the response.
	 *
	 * @since 2.7.0
	 *
	 * @return string The body of the response. Empty string if no body or incorrect parameter given.
	 */
	protected function get_response_body() {
		return wp_remote_retrieve_body( $this->get_response() );
	}

}
