Making WordPress.org

Ticket #3474: 3474.diff

File 3474.diff, 23.4 KB (added by flixos90, 7 years ago)
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/class-api-error-response.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/class-api-error-response.php api.wordpress.org/public_html/core/serve-happy/1.0/class-api-error-response.php
    new file mode 100644
    index 0000000..69e35f3
    - +  
     1<?php
     2
     3namespace Serve_Happy;
     4
     5/**
     6 * Class representing an API error response.
     7 */
     8class API_Error_Response extends API_Response {
     9
     10        /**
     11         * Gets the supported parameters with their default values.
     12         *
     13         * @return array Default parameters as $key => $value pairs.
     14         */
     15        protected function get_defaults() : array {
     16                return array(
     17                        'code'    => '',
     18                        'message' => '',
     19                        'status'  => 500,
     20                );
     21        }
     22}
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/class-api-message.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/class-api-message.php api.wordpress.org/public_html/core/serve-happy/1.0/class-api-message.php
    new file mode 100644
    index 0000000..9eda5eb
    - +  
     1<?php
     2
     3namespace Serve_Happy;
     4
     5/**
     6 * Class representing an API message.
     7 */
     8abstract class API_Message {
     9
     10        /**
     11         * Parameters as $key => $value pairs.
     12         *
     13         * @var array
     14         */
     15        protected $params = array();
     16
     17        /**
     18         * Default parameters as $key => $default pairs.
     19         *
     20         * @var array
     21         */
     22        protected $defaults = array();
     23
     24        /**
     25         * Constructor.
     26         *
     27         * Sets the parameters.
     28         *
     29         * @param array $params Optional. Parameters as $key => $value pairs.
     30         *                      Default empty array.
     31         */
     32        public function __construct( array $params = array() ) {
     33                $this->defaults = $this->get_defaults();
     34
     35                $this->set_params( $params );
     36        }
     37
     38        /**
     39         * Checks whether a given parameter is set.
     40         *
     41         * @param string $key Parameter key.
     42         * @return bool True if the parameter is set, false otherwise.
     43         */
     44        public function has_param( string $key ) : bool {
     45                return isset( $this->params[ $key ] );
     46        }
     47
     48        /**
     49         * Retrieves a given parameter.
     50         *
     51         * @param string $key Parameter key.
     52         * @return mixed Parameter value, or null if parameter is not set.
     53         */
     54        public function get_param( string $key ) {
     55                if ( ! isset( $this->params[ $key ] ) ) {
     56                        return null;
     57                }
     58
     59                return $this->params[ $key ];
     60        }
     61
     62        /**
     63         * Gets all parameters.
     64         *
     65         * @return array Array of all parameters.
     66         */
     67        public function get_params() : array {
     68                return $this->params;
     69        }
     70
     71        /**
     72         * Sets a parameter value.
     73         *
     74         * @param string $key   Parameter key.
     75         * @param mixed  $value Parameter value.
     76         * @return bool True on success, false if the parameter is not supported.
     77         */
     78        public function set_param( string $key, $value ) : bool {
     79                if ( ! array_key_exists( $key, $this->defaults ) ) {
     80                        return false;
     81                }
     82
     83                $this->params[ $key ] = $value;
     84
     85                return true;
     86        }
     87
     88        /**
     89         * Sets all parameters.
     90         *
     91         * This method will override all previously set parameters.
     92         *
     93         * @param array $params Parameters as $key => $value pairs.
     94         * @return bool True on success, false if some parameters are not supported.
     95         */
     96        public function set_params( array $params ) : bool {
     97                $this->params = $this->defaults;
     98
     99                $result = true;
     100
     101                foreach ( $params as $key => $value ) {
     102                        $result = $result && $this->set_param( $key, $value );
     103                }
     104
     105                return $result;
     106        }
     107
     108        /**
     109         * Gets the supported parameters with their default values.
     110         *
     111         * @return array Default parameters as $key => $value pairs.
     112         */
     113        protected abstract function get_defaults() : array;
     114}
     115 No newline at end of file
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/class-api-request.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/class-api-request.php api.wordpress.org/public_html/core/serve-happy/1.0/class-api-request.php
    new file mode 100644
    index 0000000..5e54cac
    - +  
     1<?php
     2
     3namespace Serve_Happy;
     4
     5/**
     6 * Class representing an API request.
     7 */
     8class API_Request extends API_Message {
     9
     10        /**
     11         * Gets the supported parameters with their default values.
     12         *
     13         * @return array Default parameters as $key => $value pairs.
     14         */
     15        protected function get_defaults() : array {
     16                return array(
     17                        'php_version' => null,
     18                );
     19        }
     20}
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/class-api-response.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/class-api-response.php api.wordpress.org/public_html/core/serve-happy/1.0/class-api-response.php
    new file mode 100644
    index 0000000..91d30b5
    - +  
     1<?php
     2
     3namespace Serve_Happy;
     4
     5/**
     6 * Class representing an API response.
     7 */
     8class API_Response extends API_Message {
     9
     10        /**
     11         * Gets the supported parameters with their default values.
     12         *
     13         * @return array Default parameters as $key => $value pairs.
     14         */
     15        protected function get_defaults() : array {
     16                return array(
     17                        'upgrade'         => false,
     18                        'insecure'        => false,
     19                        'info_url'        => '',
     20                        'upgrade_url'     => '',
     21                        'latest_php'      => '',
     22                        'recommended_php' => '',
     23                        'secure_php'      => '',
     24                        'trigger_php'     => '',
     25                        'minimum_php'     => '',
     26                );
     27        }
     28}
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/class-api.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/class-api.php api.wordpress.org/public_html/core/serve-happy/1.0/class-api.php
    new file mode 100644
    index 0000000..f5043ec
    - +  
     1<?php
     2
     3namespace Serve_Happy;
     4
     5/**
     6 * Class handling API requests and serving responses.
     7 */
     8class API {
     9
     10        /**
     11         * Configuration as $key => $value pairs.
     12         *
     13         * @var array
     14         */
     15        protected $config = array();
     16
     17        /**
     18         * JSONP callback, if set.
     19         *
     20         * @var string
     21         */
     22        protected $jsonp = '';
     23
     24        /**
     25         * Constructor.
     26         *
     27         * Sets the configuration data.
     28         *
     29         * @param array $config Configuration as $key => $value pairs.
     30         */
     31        public function __construct( array $config ) {
     32                $this->config = array_merge( array(
     33                        'info_url'        => '',
     34                        'latest_php'      => '',
     35                        'recommended_php' => '',
     36                        'secure_php'      => '',
     37                        'trigger_php'     => '',
     38                        'minimum_php'     => '',
     39                ), $config );
     40        }
     41
     42        /**
     43         * Sets or retrieves the JSONP callback.
     44         *
     45         * @param string $jsonp Optional. JSONP callback, if it should be set.
     46         * @return string JSONP callback set before calling the method.
     47         */
     48        public function jsonp( $jsonp = null ) : string {
     49                if ( null !== $jsonp ) {
     50                        $old         = $this->jsonp;
     51                        $this->jsonp = preg_replace( '/[^a-zA-Z0-9_]/', '', $jsonp );
     52
     53                        return $old;
     54                }
     55
     56                return $this->jsonp;
     57        }
     58
     59        /**
     60         * Handles serving a request.
     61         *
     62         * @param API_Request $request Request object.
     63         */
     64        public function serve_request( API_Request $request ) {
     65                $response = $this->get_response( $request );
     66
     67                $status = 200;
     68                if ( $response instanceof API_Error_Response ) {
     69                        $status = $response->get_param( 'status' );
     70                }
     71
     72                $this->set_status( $status );
     73
     74                $content_type = ! empty( $this->jsonp ) ? 'application/javascript' : 'application/json';
     75               
     76                $this->send_header( 'Content-Type', $content_type . '; charset=utf-8' );
     77                $this->send_header( 'X-Robots-Tag', 'noindex' );
     78
     79                /*
     80                 * Mitigate possible JSONP Flash attacks.
     81                 *
     82                 * https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
     83                 */
     84                $this->send_header( 'X-Content-Type-Options', 'nosniff' );
     85
     86                $result = json_encode( $response->get_params() );
     87
     88                if ( ! empty( $this->jsonp ) ) {
     89                        // Prepend '/**/' to mitigate possible JSONP Flash attacks.
     90                        // https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
     91                        echo '/**/' . $this->jsonp . '(' . $result . ')';
     92                } else {
     93                        echo $result;
     94                }
     95        }
     96
     97        /**
     98         * Gets the response for a given request.
     99         *
     100         * @param API_Request $request Request object.
     101         * @return API_Response Response object.
     102         */
     103        public function get_response( API_Request $request ) : API_Response {
     104                if ( ! $request->has_param( 'php_version' ) ) {
     105                        return $this->create_error_response( 'missing_param', 'Missing parameter: php_version', 400 );
     106                }
     107
     108                $version = $request->get_param( 'php_version' );
     109
     110                if ( empty( $version ) || ! preg_match( '/^[0-9\.]+$/', $version ) ) {
     111                        return $this->create_error_response( 'invalid_param', 'Invalid parameter: php_version', 400 );
     112                }
     113
     114                $data = $this->config;
     115
     116                $data['upgrade']  = version_compare( $version, $this->config['trigger_php'], '<' );
     117                $data['insecure'] = version_compare( $version, $this->config['secure_php'], '<' );
     118       
     119                return $this->create_success_response( $data );
     120        }
     121
     122        /**
     123         * Creates a success response object from given data.
     124         *
     125         * @param array $data Response data.
     126         * @return API_Response Response object.
     127         */
     128        protected function create_success_response( array $data ) : API_Response {
     129                return new API_Response( $data );
     130        }
     131
     132        /**
     133         * Creates an error response object for a given code, message and status.
     134         *
     135         * @param string $code    Error code.
     136         * @param string $message Error message.
     137         * @param int    $status  Optional. HTTP status code to use. Default 500.
     138         * @return API_Error_Response Response object.
     139         */
     140        protected function create_error_response( string $code, string $message, int $status = 500 ) : API_Error_Response {
     141                return new API_Error_Response( array(
     142                        'code'    => $code,
     143                        'message' => $message,
     144                        'status'  => $status,
     145                ) );
     146        }
     147
     148        /**
     149         * Sends an HTTP header.
     150         *
     151         * @param string $key Header key.
     152         * @param string $value Header value.
     153         */
     154        protected function send_header( string $key, string $value ) {
     155                $value  = preg_replace( '/\s+/', ' ', $value );
     156                $this->header( sprintf( '%s: %s', $key, $value ) );
     157        }
     158
     159        /**
     160         * Sends the HTTP status header.
     161         *
     162         * @param int $code HTTP status code.
     163         */
     164        protected function set_status( int $code ) {
     165                $protocol = ! empty( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : '';
     166                if ( ! in_array( $protocol, array( 'HTTP/1.1', 'HTTP/2', 'HTTP/2.0' ) ) ) {
     167                        $protocol = 'HTTP/1.0';
     168                }
     169               
     170                /* Only cover useful status codes here for now. */
     171                switch ( $code ) {
     172                        case 200:
     173                                $description = 'OK';
     174                                break;
     175                        case 400:
     176                                $description = 'Bad Request';
     177                                break;
     178                        case 401:
     179                                $description = 'Unauthorized';
     180                                break;
     181                        case 403:
     182                                $description = 'Forbidden';
     183                                break;
     184                        case 404:
     185                                $description = 'Not Found';
     186                                break;
     187                        case 500:
     188                                $description = 'Internal Server Error';
     189                                break;
     190                        default:
     191                                $description = '';
     192                }
     193
     194                $header = "$protocol $code $description";
     195
     196                $this->header( $header, true, $code );
     197        }
     198
     199        /**
     200         * Low-level method to send an HTTP header.
     201         *
     202         * @param string $header             Header content.
     203         * @param bool   $replace            Optional. Whether to replace a previous header with the same name.
     204         *                                   Default true.
     205         * @param int    $http_response_code Optional. HTTP response code to set with the header. Default none.
     206         */
     207        protected function header( string $header, bool $replace = true, int $http_response_code = 0 ) {
     208                if ( ! empty( $http_response_code ) ) {
     209                        header( $header, $replace, $http_response_code );
     210                } else {
     211                        header( $header, $replace );
     212                }
     213        }
     214}
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/config.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/config.php api.wordpress.org/public_html/core/serve-happy/1.0/config.php
    new file mode 100644
    index 0000000..3598985
    - +  
     1<?php
     2
     3return array(
     4        'info_url'        => 'https://wordpress.org/support/upgrade-php/',
     5        'latest_php'      => '7.2.1',
     6        'recommended_php' => '7.2',
     7        'secure_php'      => '5.6',
     8        'trigger_php'     => '5.3',
     9        'minimum_php'     => '5.2',
     10);
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/index.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/index.php api.wordpress.org/public_html/core/serve-happy/1.0/index.php
    new file mode 100644
    index 0000000..b0ac926
    - +  
     1<?php
     2
     3require_once __DIR__ . '/class-api.php';
     4require_once __DIR__ . '/class-api-message.php';
     5require_once __DIR__ . '/class-api-request.php';
     6require_once __DIR__ . '/class-api-response.php';
     7require_once __DIR__ . '/class-api-error-response.php';
     8
     9$sh_config = require __DIR__ . '/config.php';
     10
     11$sh_api = new Serve_Happy\API( $sh_config );
     12
     13if ( ! empty( $_GET['jsonp'] ) ) {
     14        $sh_api->jsonp( $_GET['jsonp'] );
     15}
     16
     17$sh_api->serve_request( new Serve_Happy\API_Request( $_REQUEST ) );
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/phpunit.xml

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/phpunit.xml api.wordpress.org/public_html/core/serve-happy/1.0/phpunit.xml
    new file mode 100644
    index 0000000..6e130be
    - +  
     1<phpunit
     2        backupGlobals="false"
     3        colors="true"
     4        convertErrorsToExceptions="true"
     5        convertNoticesToExceptions="true"
     6        convertWarningsToExceptions="true"
     7        bootstrap="tests/phpunit/bootstrap.php"
     8        >
     9        <testsuites>
     10                <testsuite>
     11                        <directory suffix=".php">./tests/phpunit/tests/</directory>
     12                </testsuite>
     13        </testsuites>
     14</phpunit>
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/bootstrap.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/bootstrap.php api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/bootstrap.php
    new file mode 100644
    index 0000000..3381c89
    - +  
     1<?php
     2
     3if ( function_exists( 'xdebug_disable' ) ) {
     4        xdebug_disable();
     5}
     6
     7// PHP 6+ Compatibility.
     8if ( class_exists( 'PHPUnit\Runner\Version' ) && version_compare( PHPUnit\Runner\Version::id(), '6.0', '>=' ) ) {
     9        class_alias( 'PHPUnit\Framework\TestCase', 'PHPUnit_Framework_TestCase' );
     10}
     11
     12define( 'SERVEHAPPY_DIR', dirname( dirname( __DIR__ ) ) );
     13
     14require_once SERVEHAPPY_DIR . '/class-api.php';
     15require_once SERVEHAPPY_DIR . '/class-api-message.php';
     16require_once SERVEHAPPY_DIR . '/class-api-request.php';
     17require_once SERVEHAPPY_DIR . '/class-api-response.php';
     18require_once SERVEHAPPY_DIR . '/class-api-error-response.php';
     19
     20require_once __DIR__ . '/class-headerless-api.php';
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/class-headerless-api.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/class-headerless-api.php api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/class-headerless-api.php
    new file mode 100644
    index 0000000..4f492b1
    - +  
     1<?php
     2
     3namespace Serve_Happy\Tests;
     4
     5use Serve_Happy\API;
     6
     7class Headerless_API extends API {
     8
     9        protected $headers_list = array();
     10
     11        public function headers_list() {
     12                return $this->headers_list;
     13        }
     14
     15        protected function header( string $header, bool $replace = true, int $http_response_code = 0 ) {
     16                $this->headers_list[] = $header;
     17        }
     18}
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/tests/api-messages.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/tests/api-messages.php api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/tests/api-messages.php
    new file mode 100644
    index 0000000..08b1251
    - +  
     1<?php
     2
     3namespace Serve_Happy\Tests;
     4
     5use PHPUnit_Framework_TestCase;
     6use Serve_Happy\API_Request;
     7use Serve_Happy\API_Response;
     8use Serve_Happy\API_Error_Response;
     9
     10/**
     11 * @group serve-happy
     12 */
     13class Tests_API_Messages extends PHPUnit_Framework_TestCase {
     14
     15        public function test_has_param_true() {
     16                $request = new API_Request( array(
     17                        'php_version' => '7.0',
     18                ) );
     19
     20                $this->assertTrue( $request->has_param( 'php_version' ) );
     21        }
     22
     23        public function test_has_param_false() {
     24                $request = new API_Request();
     25
     26                $this->assertFalse( $request->has_param( 'php_version' ) );
     27        }
     28
     29        public function test_get_param_existing() {
     30                $request = new API_Request( array(
     31                        'php_version' => '7.0',
     32                ) );
     33
     34                $this->assertSame( '7.0', $request->get_param( 'php_version' ) );
     35        }
     36
     37        public function test_get_param_not_existing() {
     38                $request = new API_Request();
     39
     40                $this->assertNull( $request->get_param( 'php_version' ) );
     41        }
     42
     43        public function test_get_params() {
     44                $data = array(
     45                        'php_version' => '7.0',
     46                );
     47
     48                $request = new API_Request( $data );
     49                $params  = $request->get_params();
     50
     51                ksort( $data );
     52                ksort( $params );
     53                $this->assertSame( $data, $params );
     54        }
     55
     56        public function test_set_param_valid() {
     57                $request = new API_Request();
     58                $this->assertTrue( $request->set_param( 'php_version', '7.0' ) );
     59                $this->assertSame( '7.0', $request->get_param( 'php_version' ) );
     60        }
     61
     62        public function test_set_param_invalid() {
     63                $request = new API_Request();
     64                $this->assertFalse( $request->set_param( 'mysql_version', '5.5' ) );
     65                $this->assertNull( $request->get_param( 'mysql_version' ) );
     66        }
     67
     68        public function test_set_params_valid() {
     69                $request = new API_Request();
     70                $this->assertTrue( $request->set_params( array(
     71                        'php_version' => '7.0',
     72                ) ) );
     73                $this->assertSame( '7.0', $request->get_param( 'php_version' ) );
     74        }
     75
     76        public function test_set_params_invalid() {
     77                $request = new API_Request();
     78                $this->assertFalse( $request->set_params( array(
     79                        'mysql_version' => '5.6',
     80                ) ) );
     81                $this->assertNull( $request->get_param( 'mysql_version' ) );
     82        }
     83
     84        public function test_set_params_partly_valid() {
     85                $request = new API_Request();
     86                $this->assertFalse( $request->set_params( array(
     87                        'php_version'   => '7.0',
     88                        'mysql_version' => '5.6',
     89                ) ) );
     90                $this->assertSame( '7.0', $request->get_param( 'php_version' ) );
     91                $this->assertNull( $request->get_param( 'mysql_version' ) );
     92        }
     93
     94        public function test_request_constructor_get_defaults() {
     95                $expected = array(
     96                        'php_version' => null,
     97                );
     98
     99                $request = new API_Request();
     100                $params  = $request->get_params();
     101
     102                ksort( $expected );
     103                ksort( $params );
     104                $this->assertSame( $expected, $params );
     105        }
     106
     107        public function test_response_constructor_get_defaults() {
     108                $expected = array(
     109                        'upgrade'         => false,
     110                        'insecure'        => false,
     111                        'info_url'        => '',
     112                        'upgrade_url'     => '',
     113                        'latest_php'      => '',
     114                        'recommended_php' => '',
     115                        'secure_php'      => '',
     116                        'trigger_php'     => '',
     117                        'minimum_php'     => '',
     118                );
     119
     120                $response = new API_Response();
     121                $params  = $response->get_params();
     122
     123                ksort( $expected );
     124                ksort( $params );
     125                $this->assertSame( $expected, $params );
     126        }
     127
     128        public function test_error_response_constructor_get_defaults() {
     129                $expected = array(
     130                        'code'    => '',
     131                        'message' => '',
     132                        'status'  => 500,
     133                );
     134
     135                $response = new API_Error_Response();
     136                $params  = $response->get_params();
     137
     138                ksort( $expected );
     139                ksort( $params );
     140                $this->assertSame( $expected, $params );
     141        }
     142}
  • new file api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/tests/api.php

    diff --git api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/tests/api.php api.wordpress.org/public_html/core/serve-happy/1.0/tests/phpunit/tests/api.php
    new file mode 100644
    index 0000000..a5bbeb8
    - +  
     1<?php
     2
     3namespace Serve_Happy\Tests;
     4
     5use PHPUnit_Framework_TestCase;
     6use Serve_Happy\API;
     7use Serve_Happy\API_Request;
     8use Serve_Happy\API_Response;
     9use Serve_Happy\API_Error_Response;
     10
     11/**
     12 * @group serve-happy
     13 */
     14class Tests_API extends PHPUnit_Framework_TestCase {
     15
     16        private static $config;
     17
     18        public static function setUpBeforeClass() {
     19                self::$config = array(
     20                        'info_url'        => 'https://wordpress.org/support/upgrade-php/',
     21                        'latest_php'      => '7.2.1',
     22                        'recommended_php' => '7.2',
     23                        'secure_php'      => '5.6',
     24                        'trigger_php'     => '5.3',
     25                        'minimum_php'     => '5.2',
     26                );
     27        }
     28
     29        public static function tearDownAfterClass() {
     30                self::$config = null;
     31        }
     32
     33        public function test_jsonp_get() {
     34                $api = new API( self::$config );
     35                $this->assertSame( '', $api->jsonp() );
     36        }
     37
     38        public function test_jsonp_set() {
     39                $api = new API( self::$config );
     40                $this->assertSame( '', $api->jsonp( 'callbackFunc' ) );
     41                $this->assertSame( 'callbackFunc', $api->jsonp() );
     42        }
     43
     44        public function test_serve_request_success() {
     45                $api = new Headerless_API( self::$config );
     46
     47                ob_start();
     48                $api->serve_request( new API_Request( array(
     49                        'php_version' => '7.0',
     50                ) ) );
     51                $result = ob_get_clean();
     52
     53                $headers = $api->headers_list();
     54
     55                $this->assertTrue( in_array( 'HTTP/1.0 200 OK', $headers, true ) );
     56                $this->assertTrue( in_array( 'Content-Type: application/json; charset=utf-8', $headers, true ) );
     57                $this->assertInstanceOf( 'stdClass', json_decode( $result ) );
     58        }
     59
     60        public function test_serve_request_error() {
     61                $api = new Headerless_API( self::$config );
     62
     63                ob_start();
     64                $api->serve_request( new API_Request() );
     65                $result = ob_get_clean();
     66
     67                $headers = $api->headers_list();
     68
     69                $this->assertTrue( in_array( 'HTTP/1.0 400 Bad Request', $headers, true ) );
     70                $this->assertTrue( in_array( 'Content-Type: application/json; charset=utf-8', $headers, true ) );
     71                $this->assertInstanceOf( 'stdClass', json_decode( $result ) );
     72        }
     73
     74        public function test_serve_request_jsonp() {
     75                $api = new Headerless_API( self::$config );
     76                $api->jsonp( 'callbackFunc' );
     77
     78                ob_start();
     79                $api->serve_request( new API_Request( array(
     80                        'php_version' => '7.0',
     81                ) ) );
     82                $result = ob_get_clean();
     83
     84                $headers = $api->headers_list();
     85
     86                $this->assertTrue( in_array( 'HTTP/1.0 200 OK', $headers, true ) );
     87                $this->assertTrue( in_array( 'Content-Type: application/javascript; charset=utf-8', $headers, true ) );
     88                $this->assertSame( 0, strpos( $result, '/**/callbackFunc(' ) );
     89        }
     90
     91        /**
     92         * @dataProvider data_get_response
     93         */
     94        public function test_get_response( $php_version, $expected_data, $is_error ) {
     95                $api = new API( self::$config );
     96
     97                $response = $api->get_response( new API_Request( array(
     98                        'php_version' => $php_version,
     99                ) ) );
     100                $response_data = array_intersect_key( $response->get_params(), $expected_data );
     101
     102                ksort( $expected_data );
     103                ksort( $response_data );
     104
     105                $this->assertInstanceOf( $is_error ? API_Error_Response::class : API_Response::class, $response );
     106                $this->assertSame( $expected_data, $response_data );
     107        }
     108
     109        public function data_get_response() {
     110                return array(
     111                        array(
     112                                '5.2',
     113                                array(
     114                                        'upgrade'  => true,
     115                                        'insecure' => true,
     116                                ),
     117                                false,
     118                        ),
     119                        array(
     120                                '5.3',
     121                                array(
     122                                        'upgrade'  => false,
     123                                        'insecure' => true,
     124                                ),
     125                                false,
     126                        ),
     127                        array(
     128                                '5.4',
     129                                array(
     130                                        'upgrade'  => false,
     131                                        'insecure' => true,
     132                                ),
     133                                false,
     134                        ),
     135                        array(
     136                                '5.5',
     137                                array(
     138                                        'upgrade'  => false,
     139                                        'insecure' => true,
     140                                ),
     141                                false,
     142                        ),
     143                        array(
     144                                '5.6',
     145                                array(
     146                                        'upgrade'  => false,
     147                                        'insecure' => false,
     148                                ),
     149                                false,
     150                        ),
     151                        array(
     152                                '7.0',
     153                                array(
     154                                        'upgrade'  => false,
     155                                        'insecure' => false,
     156                                ),
     157                                false,
     158                        ),
     159                        array(
     160                                '7.1',
     161                                array(
     162                                        'upgrade'  => false,
     163                                        'insecure' => false,
     164                                ),
     165                                false,
     166                        ),
     167                        array(
     168                                '7.2',
     169                                array(
     170                                        'upgrade'  => false,
     171                                        'insecure' => false,
     172                                ),
     173                                false,
     174                        ),
     175                        array(
     176                                null,
     177                                array(
     178                                        'code'    => 'missing_param',
     179                                        'message' => 'Missing parameter: php_version',
     180                                        'status'  => 400,
     181                                ),
     182                                true,
     183                        ),
     184                        array(
     185                                '',
     186                                array(
     187                                        'code'    => 'invalid_param',
     188                                        'message' => 'Invalid parameter: php_version',
     189                                        'status'  => 400,
     190                                ),
     191                                true,
     192                        ),
     193                        array(
     194                                'this.is.not.a.version.number',
     195                                array(
     196                                        'code'    => 'invalid_param',
     197                                        'message' => 'Invalid parameter: php_version',
     198                                        'status'  => 400,
     199                                ),
     200                                true,
     201                        ),
     202                );
     203        }
     204}