<?php

/**
 * Utility handling HTTP(s) automation issues
 *
 * @author     Timely Network Inc
 * @since      2.0
 *
 * @package    AI1EC
 * @subpackage AI1EC.Http
 */
class Ai1ec_Http_Request {

    /**
     * Public constructor
     *
     * @param Ai1ec_Registry_Object $registry
     *
     * @return void
     */
    public function __construct( Ai1ec_Registry_Object $registry ) {
        $this->_registry = $registry;
    }

    /**
     * Callback for debug-checking filters. Changes debug to false for AJAX req.
     *
     * @wp_hook ai1ec_dbi_debug
     *
     * @param bool $do_debug Current debug value.
     *
     * @return bool Optionally modified `$do_debug`.
     */
    public function debug_filter( $do_debug ) {
        if ( $this->is_ajax() ) {
            $do_debug = false;
        }
        return $do_debug;
    }

    /**
     * Check if we are processing AJAX request.
     *
     * @return bool True if it's an AJAX request.
     */
    public function is_ajax() {
        if ( defined( 'DOING_AJAX' ) ) {
            return true;
        }
        if (
            isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) &&
            'XMLHttpRequest' === $_SERVER['HTTP_X_REQUESTED_WITH']
        ) {
            return true;
        }
        if (
            isset( $_GET['ai1ec_doing_ajax'] ) &&
            'true' === $_GET['ai1ec_doing_ajax']
        ) {
            return true;
        }
        if ( isset( $_GET['ai1ec_js_widget'] ) ) {
            return true;
        }
        // Legacy support.
        if ( isset( $_GET['ai1ec_super_widget'] ) ) {
            return true;
        }
        if (
            isset( $_GET['ai1ec_render_js'] ) ||
            isset( $_GET['ai1ec_render_css'] )
        ) {
            return true;
        }
        return apply_filters( 'ai1ec_is_ajax', false );
    }

    /**
     * Check if client accepts gzip and we should compress content
     *
     * Plugin settings, client preferences and server capabilities are
     * checked to make sure we should use gzip for output compression.
     *
     * @return bool True when gzip should be used
     */
    public function client_use_gzip() {
        $settings = $this->_registry->get( 'model.settings' );

        if (
            $settings->get( 'disable_gzip_compression' ) ||
            (
                isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) &&
                'identity' === $_SERVER['HTTP_ACCEPT_ENCODING'] ||
                ! extension_loaded( 'zlib' )
            )
        ) {
            return false;
        }
        $zlib_output_handler = ini_get( 'zlib.output_handler' );
        if (
            in_array( 'ob_gzhandler', ob_list_handlers() ) ||
            in_array(
                strtolower( ini_get( 'zlib.output_compression' ) ),
                array( '1', 'on' )
            ) ||
            ! empty( $zlib_output_handler )
        ) {
            return false;
        }
        return true;
    }

    /**
     * Disable `streams` transport support as necessary
     *
     * Following (`streams`) transport is disabled only when request to cron
     * dispatcher are made to make sure that requests does have no impact on
     * browsing experience - site is not slowed down, when crons are spawned
     * from within current screen session.
     *
     * @param mixed  $output  HTTP output
     * @param string $url     Original request URL
     *
     * @return mixed Original or modified $output
     */
    public function pre_http_request( $status, $output, $url ) {
        $cron_url = site_url( 'wp-cron.php' );
        remove_filter( 'use_streams_transport', 'ai1ec_return_false' );
        if (
            0 === strncmp( $url, $cron_url, strlen( $cron_url ) ) &&
            ! function_exists( 'curl_init' )
        ) {
            add_filter( 'use_streams_transport', 'ai1ec_return_false' );
        }
        return $status;
    }

    /**
     * Inject time.ly certificate to cURL resource handle
     *
     * @param resource $curl Instance of cURL resource
     *
     * @return void Method does not return value
     */
    public function curl_inject_certificate( $curl ) {
        // verify that the passed argument
        // is resource of type 'curl'
        if (
            is_resource( $curl ) &&
            'curl' === get_resource_type( $curl )
        ) {
            // set CURLOPT_CAINFO to AI1EC_CA_ROOT_PEM
            curl_setopt( $curl, CURLOPT_CAINFO, AI1EC_CA_ROOT_PEM );
        }
    }

    /**
     * Initialize time.ly certificate only for time.ly domain
     *
     * @param array  $args Http arguments.
     * @param string $url Current URL address.
     *
     * @return void Method does not return value
     */
    public function init_certificate( $args, $url ) {
        remove_action( 'http_api_curl', array( $this, 'curl_inject_certificate' ) );
        if ( false !== stripos( $url, '//time.ly' ) ) {
            add_action( 'http_api_curl', array( $this, 'curl_inject_certificate' ) );
        }
        return $args;
    }

    /**
     * Checks if is json required for frontend rendering.
     *
     * @param string $request_format Format.
     *
     * @return bool True or false.
     */
    public function is_json_required( $request_format, $type ) {
        $fer_list = explode( ',', AI1EC_FER_ENABLED_TEMPLATES_LIST );
        return
            'json' === $request_format &&
            in_array( strtolower( $type ), $fer_list ) &&
            $this->_registry->get(
                'model.settings'
            )->get( 'ai1ec_use_frontend_rendering' ) &&
            $this->is_ajax();
    }

    /**
     * Returns current action for bulk operations.
     *
     * @return string|null Action or null when empty.
     */
    public function get_current_action() {
        if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) {
            return $_REQUEST['action'];
        }
        if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) {
            return $_REQUEST['action2'];
        }
        return null;
    }
}
