PNG %k25u25%fgd5n! PNG %k25u25%fgd5n!automattic/woocommerce/LICENSE000066400000002120151501170470012240 0ustar00The MIT License (MIT) Copyright (c) 2016, Automattic (https://automattic.com/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. automattic/woocommerce/README.md000066400000021322151501170470012517 0ustar00# WooCommerce API - PHP Client A PHP wrapper for the WooCommerce REST API. Easily interact with the WooCommerce REST API securely using this library. If using a HTTPS connection this library uses BasicAuth, else it uses Oauth to provide a secure connection to WooCommerce. [![CI status](https://github.com/woocommerce/wc-api-php/actions/workflows/ci.yml/badge.svg?branch=trunk)](https://github.com/woocommerce/wc-api-php/actions/workflows/ci.yml) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/woocommerce/wc-api-php/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/woocommerce/wc-api-php/?branch=master) [![PHP version](https://badge.fury.io/ph/automattic%2Fwoocommerce.svg)](https://packagist.org/packages/automattic/woocommerce) ## Installation ``` composer require automattic/woocommerce ``` ## Getting started Generate API credentials (Consumer Key & Consumer Secret) following this instructions . Check out the WooCommerce API endpoints and data that can be manipulated in . ## Setup Setup for the new WP REST API integration (WooCommerce 2.6 or later): ```php require __DIR__ . '/vendor/autoload.php'; use Automattic\WooCommerce\Client; $woocommerce = new Client( 'http://example.com', 'ck_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 'cs_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', [ 'version' => 'wc/v3', ] ); ``` ## Client class ```php $woocommerce = new Client($url, $consumer_key, $consumer_secret, $options); ``` ### Options | Option | Type | Required | Description | | ----------------- | -------- | -------- | ------------------------------------------ | | `url` | `string` | yes | Your Store URL, example: http://woo.dev/ | | `consumer_key` | `string` | yes | Your API consumer key | | `consumer_secret` | `string` | yes | Your API consumer secret | | `options` | `array` | no | Extra arguments (see client options table) | #### Client options | Option | Type | Required | Description | | ------------------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `version` | `string` | no | API version, default is `wc/v3` | | `timeout` | `int` | no | Request timeout, default is `15` | | `verify_ssl` | `bool` | no | Verify SSL when connect, use this option as `false` when need to test with self-signed certificates, default is `true` | | `follow_redirects` | `bool` | no | Allow the API call to follow redirects | | `query_string_auth` | `bool` | no | Force Basic Authentication as query string when `true` and using under HTTPS, default is `false` | | `oauth_timestamp` | `string` | no | Custom oAuth timestamp, default is `time()` | | `oauth_only` | `bool` | no | Only use oauth for requests, it will disable Basic Auth, default is `false` | | `user_agent` | `string` | no | Custom user-agent, default is `WooCommerce API Client-PHP` | | `wp_api_prefix` | `string` | no | Custom WP REST API URL prefix, used to support custom prefixes created with the `rest_url_prefix` filter | | `wp_api` | `bool` | no | Set to `false` in order to use the legacy WooCommerce REST API (deprecated and not recommended) | | `method_override_query` | `bool` | no | If true will mask all non-GET/POST methods by using POST method with added query parameter `?_method=METHOD` into URL | | `method_override_header` | `bool` | no | If true will mask all non-GET/POST methods (PUT/DELETE/etc.) by using POST method with added `X-HTTP-Method-Override: METHOD` HTTP header into request | ## Client methods ### GET ```php $woocommerce->get($endpoint, $parameters = []); ``` ### POST ```php $woocommerce->post($endpoint, $data); ``` ### PUT ```php $woocommerce->put($endpoint, $data); ``` ### DELETE ```php $woocommerce->delete($endpoint, $parameters = []); ``` ### OPTIONS ```php $woocommerce->options($endpoint); ``` #### Arguments | Params | Type | Description | | ------------ | -------- | ------------------------------------------------------------ | | `endpoint` | `string` | WooCommerce API endpoint, example: `customers` or `order/12` | | `data` | `array` | Only for POST and PUT, data that will be converted to JSON | | `parameters` | `array` | Only for GET and DELETE, request query string | #### Response All methods will return arrays on success or throwing `HttpClientException` errors on failure. ```php use Automattic\WooCommerce\HttpClient\HttpClientException; try { // Array of response results. $results = $woocommerce->get('customers'); // Example: ['customers' => [[ 'id' => 8, 'created_at' => '2015-05-06T17:43:51Z', 'email' => ... echo '
' . print_r($results, true) . '
'; // JSON output.

  // Last request data.
  $lastRequest = $woocommerce->http->getRequest();
  echo '
' . print_r($lastRequest->getUrl(), true) . '
'; // Requested URL (string).
  echo '
' .
    print_r($lastRequest->getMethod(), true) .
    '
'; // Request method (string).
  echo '
' .
    print_r($lastRequest->getParameters(), true) .
    '
'; // Request parameters (array).
  echo '
' .
    print_r($lastRequest->getHeaders(), true) .
    '
'; // Request headers (array).
  echo '
' . print_r($lastRequest->getBody(), true) . '
'; // Request body (JSON).

  // Last response data.
  $lastResponse = $woocommerce->http->getResponse();
  echo '
' . print_r($lastResponse->getCode(), true) . '
'; // Response code (int).
  echo '
' .
    print_r($lastResponse->getHeaders(), true) .
    '
'; // Response headers (array).
  echo '
' . print_r($lastResponse->getBody(), true) . '
'; // Response body (JSON).
} catch (HttpClientException $e) {
  echo '
' . print_r($e->getMessage(), true) . '
'; // Error message.
  echo '
' . print_r($e->getRequest(), true) . '
'; // Last request data.
  echo '
' . print_r($e->getResponse(), true) . '
'; // Last response data.
}
```

## Release History

- 2022-03-18 - 3.1.0 - Added new options to support `_method` and `X-HTTP-Method-Override` from WP, supports 7+, dropped support to PHP 5.
- 2019-01-16 - 3.0.0 - Legacy API turned off by default, and improved JSON error handler.
- 2018-03-29 - 2.0.1 - Fixed fatal errors on `lookForErrors`.
- 2018-01-12 - 2.0.0 - Responses changes from arrays to `stdClass` objects. Added `follow_redirects` option.
- 2017-06-06 - 1.3.0 - Remove BOM before decoding and added support for multi-dimensional arrays for oAuth1.0a.
- 2017-03-15 - 1.2.0 - Added `user_agent` option.
- 2016-12-14 - 1.1.4 - Fixed WordPress 4.7 compatibility.
- 2016-10-26 - 1.1.3 - Allow set `oauth_timestamp` and improved how is handled the response headers.
- 2016-09-30 - 1.1.2 - Added `wp_api_prefix` option to allow custom WP REST API URL prefix.
- 2016-05-10 - 1.1.1 - Fixed oAuth and error handler for WP REST API.
- 2016-05-09 - 1.1.0 - Added support for WP REST API, added method `Automattic\WooCommerce\Client::options` and fixed multiple headers responses.
- 2016-01-25 - 1.0.2 - Fixed an error when getting data containing non-latin characters.
- 2016-01-21 - 1.0.1 - Sort all oAuth parameters before build request URLs.
- 2016-01-11 - 1.0.0 - Stable release.
automattic/woocommerce/composer.json000066400000001523151501170470013763 0ustar00{
  "name": "automattic/woocommerce",
  "description": "A PHP wrapper for the WooCommerce REST API",
  "type": "library",
  "license": "MIT",
  "authors": [
    {
      "name": "Claudio Sanches",
      "email": "claudio.sanches@automattic.com"
    }
  ],
  "minimum-stability": "dev",
  "keywords": [
    "API",
    "WooCommerce"
  ],
  "require": {
    "php": ">= 7.1.0",
    "ext-curl": "*",
    "ext-json": "*"
  },
  "require-dev": {
    "phpunit/phpunit": "^8",
    "squizlabs/php_codesniffer": "3.*",
    "overtrue/phplint": "7.4.x-dev"
  },
  "autoload": {
    "psr-4": {
      "Automattic\\WooCommerce\\": ["src/WooCommerce"]
    }
  },
  "autoload-dev": {
    "psr-4": { 
      "Automattic\\WooCommerce\\LegacyTests\\": "tests/legacy-php/WooCommerce/Tests",
      "Automattic\\WooCommerce\\Tests\\": "tests/php/WooCommerce/Tests"
    }
  }
}
automattic/woocommerce/src/WooCommerce/HttpClient/BasicAuth.php000066400000003724151501170470020706 0ustar00ch             = $ch;
        $this->consumerKey    = $consumerKey;
        $this->consumerSecret = $consumerSecret;
        $this->doQueryString  = $doQueryString;
        $this->parameters     = $parameters;

        $this->processAuth();
    }

    /**
     * Process auth.
     */
    protected function processAuth()
    {
        if ($this->doQueryString) {
            $this->parameters['consumer_key']    = $this->consumerKey;
            $this->parameters['consumer_secret'] = $this->consumerSecret;
        } else {
            \curl_setopt($this->ch, CURLOPT_USERPWD, $this->consumerKey . ':' . $this->consumerSecret);
        }
    }

    /**
     * Get parameters.
     *
     * @return array
     */
    public function getParameters()
    {
        return $this->parameters;
    }
}
automattic/woocommerce/src/WooCommerce/HttpClient/Response.php000066400000004107151501170470020635 0ustar00code    = $code;
        $this->headers = $headers;
        $this->body    = $body;
    }

    /**
     * To string.
     *
     * @return string
     */
    public function __toString()
    {
        return \json_encode([
            'code'    => $this->code,
            'headers' => $this->headers,
            'body'    => $this->body,
        ]);
    }

    /**
     * Set code.
     *
     * @param int $code Response code.
     */
    public function setCode($code)
    {
        $this->code = (int) $code;
    }

    /**
     * Set headers.
     *
     * @param array $headers Response headers.
     */
    public function setHeaders($headers)
    {
        $this->headers = $headers;
    }

    /**
     * Set body.
     *
     * @param string $body Response body.
     */
    public function setBody($body)
    {
        $this->body = $body;
    }

    /**
     * Get code.
     *
     * @return int
     */
    public function getCode()
    {
        return $this->code;
    }

    /**
     * Get headers.
     *
     * @return array $headers Response headers.
     */
    public function getHeaders()
    {
        return $this->headers;
    }

    /**
     * Get body.
     *
     * @return string $body Response body.
     */
    public function getBody()
    {
        return $this->body;
    }
}
automattic/woocommerce/src/WooCommerce/HttpClient/Options.php000066400000007724151501170470020502 0ustar00options = $options;
    }

    /**
     * Get API version.
     *
     * @return string
     */
    public function getVersion()
    {
        return isset($this->options['version']) ? $this->options['version'] : self::VERSION;
    }

    /**
     * Check if need to verify SSL.
     *
     * @return bool
     */
    public function verifySsl()
    {
        return isset($this->options['verify_ssl']) ? (bool) $this->options['verify_ssl'] : true;
    }

    /**
     * Only use OAuth.
     *
     * @return bool
     */
    public function isOAuthOnly()
    {
        return isset($this->options['oauth_only']) ? (bool) $this->options['oauth_only'] : false;
    }

    /**
     * Get timeout.
     *
     * @return int
     */
    public function getTimeout()
    {
        return isset($this->options['timeout']) ? (int) $this->options['timeout'] : self::TIMEOUT;
    }

    /**
     * Basic Authentication as query string.
     * Some old servers are not able to use CURLOPT_USERPWD.
     *
     * @return bool
     */
    public function isQueryStringAuth()
    {
        return isset($this->options['query_string_auth']) ? (bool) $this->options['query_string_auth'] : false;
    }

    /**
     * Check if is WP REST API.
     *
     * @return bool
     */
    public function isWPAPI()
    {
        return isset($this->options['wp_api']) ? (bool) $this->options['wp_api'] : true;
    }

    /**
     * Custom API Prefix for WP API.
     *
     * @return string
     */
    public function apiPrefix()
    {
        return isset($this->options['wp_api_prefix']) ? $this->options['wp_api_prefix'] : self::WP_API_PREFIX;
    }

    /**
     * oAuth timestamp.
     *
     * @return string
     */
    public function oauthTimestamp()
    {
        return isset($this->options['oauth_timestamp']) ? $this->options['oauth_timestamp'] : \time();
    }

    /**
     * Custom user agent.
     *
     * @return string
     */
    public function userAgent()
    {
        return isset($this->options['user_agent']) ? $this->options['user_agent'] : self::USER_AGENT;
    }

    /**
     * Get follow redirects.
     *
     * @return bool
     */
    public function getFollowRedirects()
    {
        return isset($this->options['follow_redirects']) ? (bool) $this->options['follow_redirects'] : false;
    }

    /**
     * Check is it needed to mask all non-GET/POST methods (PUT/DELETE/etc.) by using POST method with added
     * query parameter ?_method=METHOD into URL.
     *
     * @return bool
     */
    public function isMethodOverrideQuery()
    {
        return isset($this->options['method_override_query']) && $this->options['method_override_query'];
    }

    /**
     * Check is it needed to mask all non-GET/POST methods (PUT/DELETE/etc.) by using POST method with added
     * "X-HTTP-Method-Override: METHOD" HTTP header into request.
     *
     * @return bool
     */
    public function isMethodOverrideHeader()
    {
        return isset($this->options['method_override_header']) && $this->options['method_override_header'];
    }
}
automattic/woocommerce/src/WooCommerce/HttpClient/Request.php000066400000006076151501170470020476 0ustar00url        = $url;
        $this->method     = $method;
        $this->parameters = $parameters;
        $this->headers    = $headers;
        $this->body       = $body;
    }

    /**
     * Set url.
     *
     * @param string $url Request url.
     */
    public function setUrl($url)
    {
        $this->url = $url;
    }

    /**
     * Set method.
     *
     * @param string $method Request method.
     */
    public function setMethod($method)
    {
        $this->method = $method;
    }

    /**
     * Set parameters.
     *
     * @param array $parameters Request paramenters.
     */
    public function setParameters($parameters)
    {
        $this->parameters = $parameters;
    }

    /**
     * Set headers.
     *
     * @param array $headers Request headers.
     */
    public function setHeaders($headers)
    {
        $this->headers = $headers;
    }

    /**
     * Set body.
     *
     * @param string $body Request body.
     */
    public function setBody($body)
    {
        $this->body = $body;
    }

    /**
     * Get url.
     *
     * @return string
     */
    public function getUrl()
    {
        return $this->url;
    }

    /**
     * Get method.
     *
     * @return string
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * Get parameters.
     *
     * @return array
     */
    public function getParameters()
    {
        return $this->parameters;
    }

    /**
     * Get headers.
     *
     * @return array
     */
    public function getHeaders()
    {
        return $this->headers;
    }

    /**
     * Get raw headers.
     *
     * @return array
     */
    public function getRawHeaders()
    {
        $headers = [];

        foreach ($this->headers as $key => $value) {
            $headers[] = $key . ': ' . $value;
        }

        return $headers;
    }

    /**
     * Get body.
     *
     * @return string
     */
    public function getBody()
    {
        return $this->body;
    }
}
automattic/woocommerce/src/WooCommerce/HttpClient/HttpClientException.php000066400000002461151501170470022775 0ustar00request  = $request;
        $this->response = $response;
    }

    /**
     * Get request data.
     *
     * @return Request
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Get response data.
     *
     * @return Response
     */
    public function getResponse()
    {
        return $this->response;
    }
}
automattic/woocommerce/src/WooCommerce/HttpClient/HttpClient.php000066400000031126151501170470021116 0ustar00options        = new Options($options);
        $this->url            = $this->buildApiUrl($url);
        $this->consumerKey    = $consumerKey;
        $this->consumerSecret = $consumerSecret;
    }

    /**
     * Check if is under SSL.
     *
     * @return bool
     */
    protected function isSsl()
    {
        return 'https://' === \substr($this->url, 0, 8);
    }

    /**
     * Build API URL.
     *
     * @param string $url Store URL.
     *
     * @return string
     */
    protected function buildApiUrl($url)
    {
        $api = $this->options->isWPAPI() ? $this->options->apiPrefix() : '/wc-api/';

        return \rtrim($url, '/') . $api . $this->options->getVersion() . '/';
    }

    /**
     * Build URL.
     *
     * @param string $url        URL.
     * @param array  $parameters Query string parameters.
     *
     * @return string
     */
    protected function buildUrlQuery($url, $parameters = [])
    {
        if (!empty($parameters)) {
            if (false !== strpos($url, '?')) {
                $url .= '&' . \http_build_query($parameters);
            } else {
                $url .= '?' . \http_build_query($parameters);
            }
        }

        return $url;
    }

    /**
     * Authenticate.
     *
     * @param string $url        Request URL.
     * @param string $method     Request method.
     * @param array  $parameters Request parameters.
     *
     * @return array
     */
    protected function authenticate($url, $method, $parameters = [])
    {
        // Setup authentication.
        if (!$this->options->isOAuthOnly() && $this->isSsl()) {
            $basicAuth = new BasicAuth(
                $this->ch,
                $this->consumerKey,
                $this->consumerSecret,
                $this->options->isQueryStringAuth(),
                $parameters
            );
            $parameters = $basicAuth->getParameters();
        } else {
            $oAuth = new OAuth(
                $url,
                $this->consumerKey,
                $this->consumerSecret,
                $this->options->getVersion(),
                $method,
                $parameters,
                $this->options->oauthTimestamp()
            );
            $parameters = $oAuth->getParameters();
        }

        return $parameters;
    }

    /**
     * Setup method.
     *
     * @param string $method Request method.
     */
    protected function setupMethod($method)
    {
        if ('POST' == $method) {
            \curl_setopt($this->ch, CURLOPT_POST, true);
        } elseif (\in_array($method, ['PUT', 'DELETE', 'OPTIONS'])) {
            \curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $method);
        }
    }

    /**
     * Get request headers.
     *
     * @param  bool $sendData If request send data or not.
     *
     * @return array
     */
    protected function getRequestHeaders($sendData = false)
    {
        $headers = [
            'Accept'     => 'application/json',
            'User-Agent' => $this->options->userAgent() . '/' . Client::VERSION,
        ];

        if ($sendData) {
            $headers['Content-Type'] = 'application/json;charset=utf-8';
        }

        return $headers;
    }

    /**
     * Create request.
     *
     * @param string $endpoint   Request endpoint.
     * @param string $method     Request method.
     * @param array  $data       Request data.
     * @param array  $parameters Request parameters.
     *
     * @return Request
     */
    protected function createRequest($endpoint, $method, $data = [], $parameters = [])
    {
        $body    = '';
        $url     = $this->url . $endpoint;
        $hasData = !empty($data);
        $headers = $this->getRequestHeaders($hasData);

        // HTTP method override feature which masks PUT and DELETE HTTP methods as POST method with added
        // ?_method=PUT query parameter and/or X-HTTP-Method-Override HTTP header.
        if (!in_array($method, ['GET', 'POST'])) {
            $usePostMethod = false;
            if ($this->options->isMethodOverrideQuery()) {
                $parameters = array_merge(['_method' => $method], $parameters);
                $usePostMethod = true;
            }
            if ($this->options->isMethodOverrideHeader()) {
                $headers['X-HTTP-Method-Override'] = $method;
                $usePostMethod = true;
            }
            if ($usePostMethod) {
                $method = 'POST';
            }
        }

        // Setup authentication.
        $parameters = $this->authenticate($url, $method, $parameters);

        // Setup method.
        $this->setupMethod($method);

        // Include post fields.
        if ($hasData) {
            $body = \json_encode($data);
            \curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
        }

        $this->request = new Request(
            $this->buildUrlQuery($url, $parameters),
            $method,
            $parameters,
            $headers,
            $body
        );

        return $this->getRequest();
    }

    /**
     * Get response headers.
     *
     * @return array
     */
    protected function getResponseHeaders()
    {
        $headers = [];
        $lines   = \explode("\n", $this->responseHeaders);
        $lines   = \array_filter($lines, 'trim');

        foreach ($lines as $index => $line) {
            // Remove HTTP/xxx params.
            if (strpos($line, ': ') === false) {
                continue;
            }

            list($key, $value) = \explode(': ', $line);

            $headers[$key] = isset($headers[$key]) ? $headers[$key] . ', ' . trim($value) : trim($value);
        }

        return $headers;
    }

    /**
     * Create response.
     *
     * @return Response
     */
    protected function createResponse()
    {

        // Set response headers.
        $this->responseHeaders = '';
        \curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, function ($_, $headers) {
            $this->responseHeaders .= $headers;
            return \strlen($headers);
        });

        // Get response data.
        $body    = \curl_exec($this->ch);
        $code    = \curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
        $headers = $this->getResponseHeaders();

        // Register response.
        $this->response = new Response($code, $headers, $body);

        return $this->getResponse();
    }

    /**
     * Set default cURL settings.
     */
    protected function setDefaultCurlSettings()
    {
        $verifySsl       = $this->options->verifySsl();
        $timeout         = $this->options->getTimeout();
        $followRedirects = $this->options->getFollowRedirects();

        \curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $verifySsl);
        if (!$verifySsl) {
            \curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $verifySsl);
        }
        if ($followRedirects) {
            \curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
        }
        \curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        \curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        \curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->request->getRawHeaders());
        \curl_setopt($this->ch, CURLOPT_URL, $this->request->getUrl());

        foreach ($this->customCurlOptions as $customCurlOptionKey => $customCurlOptionValue) {
            \curl_setopt($this->ch, $customCurlOptionKey, $customCurlOptionValue);
        }
    }

    /**
     * Look for errors in the request.
     *
     * @param array $parsedResponse Parsed body response.
     */
    protected function lookForErrors($parsedResponse)
    {
        // Any non-200/201/202 response code indicates an error.
        if (!\in_array($this->response->getCode(), ['200', '201', '202'])) {
            $errors = isset($parsedResponse->errors) ? $parsedResponse->errors : $parsedResponse;
            $errorMessage = '';
            $errorCode = '';

            if (is_array($errors)) {
                $errorMessage = $errors[0]->message;
                $errorCode    = $errors[0]->code;
            } elseif (isset($errors->message, $errors->code)) {
                $errorMessage = $errors->message;
                $errorCode    = $errors->code;
            }

            throw new HttpClientException(
                \sprintf('Error: %s [%s]', $errorMessage, $errorCode),
                $this->response->getCode(),
                $this->request,
                $this->response
            );
        }
    }

    /**
     * Process response.
     *
     * @return \stdClass
     */
    protected function processResponse()
    {
        $body = $this->response->getBody();

        // Look for UTF-8 BOM and remove.
        if (0 === strpos(bin2hex(substr($body, 0, 4)), 'efbbbf')) {
            $body = substr($body, 3);
        }

        $parsedResponse = \json_decode($body);

        // Test if return a valid JSON.
        if (JSON_ERROR_NONE !== json_last_error()) {
            $message = function_exists('json_last_error_msg') ? json_last_error_msg() : 'Invalid JSON returned';
            throw new HttpClientException(
                sprintf('JSON ERROR: %s', $message),
                $this->response->getCode(),
                $this->request,
                $this->response
            );
        }

        $this->lookForErrors($parsedResponse);

        return $parsedResponse;
    }

    /**
     * Make requests.
     *
     * @param string $endpoint   Request endpoint.
     * @param string $method     Request method.
     * @param array  $data       Request data.
     * @param array  $parameters Request parameters.
     *
     * @return \stdClass
     */
    public function request($endpoint, $method, $data = [], $parameters = [])
    {
        // Initialize cURL.
        $this->ch = \curl_init();

        // Set request args.
        $request = $this->createRequest($endpoint, $method, $data, $parameters);

        // Default cURL settings.
        $this->setDefaultCurlSettings();

        // Get response.
        $response = $this->createResponse();

        // Check for cURL errors.
        if (\curl_errno($this->ch)) {
            throw new HttpClientException('cURL Error: ' . \curl_error($this->ch), 0, $request, $response);
        }

        \curl_close($this->ch);

        return $this->processResponse();
    }

    /**
     * Get request data.
     *
     * @return Request
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Get response data.
     *
     * @return Response
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * Set custom cURL options to use in requests.
     *
     * @param array $curlOptions
     */
    public function setCustomCurlOptions(array $curlOptions)
    {
        $this->customCurlOptions = $curlOptions;
    }
}
automattic/woocommerce/src/WooCommerce/HttpClient/OAuth.php000066400000014725151501170470020066 0ustar00url            = $url;
        $this->consumerKey    = $consumerKey;
        $this->consumerSecret = $consumerSecret;
        $this->apiVersion     = $apiVersion;
        $this->method         = $method;
        $this->parameters     = $parameters;
        $this->timestamp      = $timestamp;
    }

    /**
     * Encode according to RFC 3986.
     *
     * @param string|array $value Value to be normalized.
     *
     * @return string
     */
    protected function encode($value)
    {
        if (is_array($value)) {
            return array_map([$this, 'encode'], $value);
        } else {
            return str_replace(['+', '%7E'], [' ', '~'], rawurlencode($value));
        }
    }

    /**
     * Normalize parameters.
     *
     * @param array $parameters Parameters to normalize.
     *
     * @return array
     */
    protected function normalizeParameters($parameters)
    {
        $normalized = [];

        foreach ($parameters as $key => $value) {
            // Percent symbols (%) must be double-encoded.
            $key   = $this->encode($key);
            $value = $this->encode($value);

            $normalized[$key] = $value;
        }

        return $normalized;
    }

    /**
     * Process filters.
     *
     * @param array $parameters Request parameters.
     *
     * @return array
     */
    protected function processFilters($parameters)
    {
        if (isset($parameters['filter'])) {
            $filters = $parameters['filter'];
            unset($parameters['filter']);
            foreach ($filters as $filter => $value) {
                $parameters['filter[' . $filter . ']'] = $value;
            }
        }

        return $parameters;
    }

    /**
     * Get secret.
     *
     * @return string
     */
    protected function getSecret()
    {
        $secret = $this->consumerSecret;

        // Fix secret for v3 or later.
        if (!\in_array($this->apiVersion, ['v1', 'v2'])) {
            $secret .= '&';
        }

        return $secret;
    }

    /**
     * Generate oAuth1.0 signature.
     *
     * @param array $parameters Request parameters including oauth.
     *
     * @return string
     */
    protected function generateOauthSignature($parameters)
    {
        $baseRequestUri = \rawurlencode($this->url);

        // Extract filters.
        $parameters = $this->processFilters($parameters);

        // Normalize parameter key/values and sort them.
        $parameters = $this->normalizeParameters($parameters);
        $parameters = $this->getSortedParameters($parameters);

        // Set query string.
        $queryString  = \implode('%26', $this->joinWithEqualsSign($parameters)); // Join with ampersand.
        $stringToSign = $this->method . '&' . $baseRequestUri . '&' . $queryString;
        $secret       = $this->getSecret();

        return \base64_encode(\hash_hmac(self::HASH_ALGORITHM, $stringToSign, $secret, true));
    }

    /**
     * Creates an array of urlencoded strings out of each array key/value pairs.
     *
     * @param  array  $params      Array of parameters to convert.
     * @param  array  $queryParams Array to extend.
     * @param  string $key         Optional Array key to append
     * @return string              Array of urlencoded strings
     */
    protected function joinWithEqualsSign($params, $queryParams = [], $key = '')
    {
        foreach ($params as $paramKey => $paramValue) {
            if ($key) {
                $paramKey = $key . '%5B' . $paramKey . '%5D'; // Handle multi-dimensional array.
            }

            if (is_array($paramValue)) {
                $queryParams = $this->joinWithEqualsSign($paramValue, $queryParams, $paramKey);
            } else {
                $string = $paramKey . '=' . $paramValue; // Join with equals sign.
                $queryParams[] = $this->encode($string);
            }
        }

        return $queryParams;
    }

    /**
     * Sort parameters.
     *
     * @param array $parameters Parameters to sort in byte-order.
     *
     * @return array
     */
    protected function getSortedParameters($parameters)
    {
        \uksort($parameters, 'strcmp');

        foreach ($parameters as $key => $value) {
            if (\is_array($value)) {
                \uksort($parameters[$key], 'strcmp');
            }
        }

        return $parameters;
    }

    /**
     * Get oAuth1.0 parameters.
     *
     * @return string
     */
    public function getParameters()
    {
        $parameters = \array_merge($this->parameters, [
            'oauth_consumer_key'     => $this->consumerKey,
            'oauth_timestamp'        => $this->timestamp,
            'oauth_nonce'            => \sha1(\microtime()),
            'oauth_signature_method' => 'HMAC-' . self::HASH_ALGORITHM,
        ]);

        // The parameters above must be included in the signature generation.
        $parameters['oauth_signature'] = $this->generateOauthSignature($parameters);

        return $this->getSortedParameters($parameters);
    }
}
automattic/woocommerce/src/WooCommerce/Client.php000066400000004517151501170470016204 0ustar00http = new HttpClient($url, $consumerKey, $consumerSecret, $options);
    }

    /**
     * POST method.
     *
     * @param string $endpoint API endpoint.
     * @param array  $data     Request data.
     *
     * @return \stdClass
     */
    public function post($endpoint, $data)
    {
        return $this->http->request($endpoint, 'POST', $data);
    }

    /**
     * PUT method.
     *
     * @param string $endpoint API endpoint.
     * @param array  $data     Request data.
     *
     * @return \stdClass
     */
    public function put($endpoint, $data)
    {
        return $this->http->request($endpoint, 'PUT', $data);
    }

    /**
     * GET method.
     *
     * @param string $endpoint   API endpoint.
     * @param array  $parameters Request parameters.
     *
     * @return \stdClass
     */
    public function get($endpoint, $parameters = [])
    {
        return $this->http->request($endpoint, 'GET', [], $parameters);
    }

    /**
     * DELETE method.
     *
     * @param string $endpoint   API endpoint.
     * @param array  $parameters Request parameters.
     *
     * @return \stdClass
     */
    public function delete($endpoint, $parameters = [])
    {
        return $this->http->request($endpoint, 'DELETE', [], $parameters);
    }

    /**
     * OPTIONS method.
     *
     * @param string $endpoint API endpoint.
     *
     * @return \stdClass
     */
    public function options($endpoint)
    {
        return $this->http->request($endpoint, 'OPTIONS', [], []);
    }
}
autoload.php000066400000000262151501170470007070 0ustar00
 *     Jordi Boggiano 
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier 
 * @author Jordi Boggiano 
 * @see    https://www.php-fig.org/psr/psr-0/
 * @see    https://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    /** @var ?string */
    private $vendorDir;

    // PSR-4
    /**
     * @var array[]
     * @psalm-var array>
     */
    private $prefixLengthsPsr4 = array();
    /**
     * @var array[]
     * @psalm-var array>
     */
    private $prefixDirsPsr4 = array();
    /**
     * @var array[]
     * @psalm-var array
     */
    private $fallbackDirsPsr4 = array();

    // PSR-0
    /**
     * @var array[]
     * @psalm-var array>
     */
    private $prefixesPsr0 = array();
    /**
     * @var array[]
     * @psalm-var array
     */
    private $fallbackDirsPsr0 = array();

    /** @var bool */
    private $useIncludePath = false;

    /**
     * @var string[]
     * @psalm-var array
     */
    private $classMap = array();

    /** @var bool */
    private $classMapAuthoritative = false;

    /**
     * @var bool[]
     * @psalm-var array
     */
    private $missingClasses = array();

    /** @var ?string */
    private $apcuPrefix;

    /**
     * @var self[]
     */
    private static $registeredLoaders = array();

    /**
     * @param ?string $vendorDir
     */
    public function __construct($vendorDir = null)
    {
        $this->vendorDir = $vendorDir;
    }

    /**
     * @return string[]
     */
    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
        }

        return array();
    }

    /**
     * @return array[]
     * @psalm-return array>
     */
    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    /**
     * @return array[]
     * @psalm-return array
     */
    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    /**
     * @return array[]
     * @psalm-return array
     */
    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    /**
     * @return string[] Array of classname => path
     * @psalm-return array
     */
    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param string[] $classMap Class to filename map
     * @psalm-param array $classMap
     *
     * @return void
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string          $prefix  The prefix
     * @param string[]|string $paths   The PSR-0 root directories
     * @param bool            $prepend Whether to prepend the directories
     *
     * @return void
     */
    public function add($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    (array) $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = (array) $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                (array) $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string          $prefix  The prefix/namespace, with trailing '\\'
     * @param string[]|string $paths   The PSR-4 base directories
     * @param bool            $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    (array) $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                (array) $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string          $prefix The prefix
     * @param string[]|string $paths  The PSR-0 base directories
     *
     * @return void
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string          $prefix The prefix/namespace, with trailing '\\'
     * @param string[]|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     *
     * @return void
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     *
     * @return void
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     *
     * @return void
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     *
     * @return void
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);

        if (null === $this->vendorDir) {
            return;
        }

        if ($prepend) {
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
        } else {
            unset(self::$registeredLoaders[$this->vendorDir]);
            self::$registeredLoaders[$this->vendorDir] = $this;
        }
    }

    /**
     * Unregisters this instance as an autoloader.
     *
     * @return void
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));

        if (null !== $this->vendorDir) {
            unset(self::$registeredLoaders[$this->vendorDir]);
        }
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return true|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }

        return null;
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    /**
     * Returns the currently registered loaders indexed by their corresponding vendor directories.
     *
     * @return self[]
     */
    public static function getRegisteredLoaders()
    {
        return self::$registeredLoaders;
    }

    /**
     * @param  string       $class
     * @param  string       $ext
     * @return string|false
     */
    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }
}

/**
 * Scope isolated include.
 *
 * Prevents access to $this/self from included files.
 *
 * @param  string $file
 * @return void
 * @private
 */
function includeFile($file)
{
    include $file;
}
composer/installed.php000066400000002041151501170470011063 0ustar00 array(
        'pretty_version' => '1.0.0+no-version-set',
        'version' => '1.0.0.0',
        'type' => 'library',
        'install_path' => __DIR__ . '/../../',
        'aliases' => array(),
        'reference' => NULL,
        'name' => '__root__',
        'dev' => true,
    ),
    'versions' => array(
        '__root__' => array(
            'pretty_version' => '1.0.0+no-version-set',
            'version' => '1.0.0.0',
            'type' => 'library',
            'install_path' => __DIR__ . '/../../',
            'aliases' => array(),
            'reference' => NULL,
            'dev_requirement' => false,
        ),
        'automattic/woocommerce' => array(
            'pretty_version' => '3.1.0',
            'version' => '3.1.0.0',
            'type' => 'library',
            'install_path' => __DIR__ . '/../automattic/woocommerce',
            'aliases' => array(),
            'reference' => 'd3b292f04c0b3b21dced691ebad8be073a83b4ad',
            'dev_requirement' => false,
        ),
    ),
);
composer/installed.json000066400000004102151501170470011245 0ustar00{
    "packages": [
        {
            "name": "automattic/woocommerce",
            "version": "3.1.0",
            "version_normalized": "3.1.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/woocommerce/wc-api-php.git",
                "reference": "d3b292f04c0b3b21dced691ebad8be073a83b4ad"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/woocommerce/wc-api-php/zipball/d3b292f04c0b3b21dced691ebad8be073a83b4ad",
                "reference": "d3b292f04c0b3b21dced691ebad8be073a83b4ad",
                "shasum": ""
            },
            "require": {
                "ext-curl": "*",
                "ext-json": "*",
                "php": ">= 7.1.0"
            },
            "require-dev": {
                "overtrue/phplint": "7.4.x-dev",
                "phpunit/phpunit": "^8",
                "squizlabs/php_codesniffer": "3.*"
            },
            "time": "2022-03-18T21:46:17+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Automattic\\WooCommerce\\": [
                        "src/WooCommerce"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Claudio Sanches",
                    "email": "claudio.sanches@automattic.com"
                }
            ],
            "description": "A PHP wrapper for the WooCommerce REST API",
            "keywords": [
                "api",
                "woocommerce"
            ],
            "support": {
                "issues": "https://github.com/woocommerce/wc-api-php/issues",
                "source": "https://github.com/woocommerce/wc-api-php/tree/3.1.0"
            },
            "install-path": "../automattic/woocommerce"
        }
    ],
    "dev": true,
    "dev-package-names": []
}
composer/LICENSE000066400000002056151501170470007406 0ustar00
Copyright (c) Nils Adermann, Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

composer/InstalledVersions.php000066400000035217151501170470012567 0ustar00
 *     Jordi Boggiano 
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer;

use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;

/**
 * This class is copied in every Composer installed project and available to all
 *
 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
 *
 * To require its presence, you can require `composer-runtime-api ^2.0`
 */
class InstalledVersions
{
    /**
     * @var mixed[]|null
     * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null
     */
    private static $installed;

    /**
     * @var bool|null
     */
    private static $canGetVendors;

    /**
     * @var array[]
     * @psalm-var array}>
     */
    private static $installedByVendor = array();

    /**
     * Returns a list of all package names which are present, either by being installed, replaced or provided
     *
     * @return string[]
     * @psalm-return list
     */
    public static function getInstalledPackages()
    {
        $packages = array();
        foreach (self::getInstalled() as $installed) {
            $packages[] = array_keys($installed['versions']);
        }

        if (1 === \count($packages)) {
            return $packages[0];
        }

        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    }

    /**
     * Returns a list of all package names with a specific type e.g. 'library'
     *
     * @param  string   $type
     * @return string[]
     * @psalm-return list
     */
    public static function getInstalledPackagesByType($type)
    {
        $packagesByType = array();

        foreach (self::getInstalled() as $installed) {
            foreach ($installed['versions'] as $name => $package) {
                if (isset($package['type']) && $package['type'] === $type) {
                    $packagesByType[] = $name;
                }
            }
        }

        return $packagesByType;
    }

    /**
     * Checks whether the given package is installed
     *
     * This also returns true if the package name is provided or replaced by another package
     *
     * @param  string $packageName
     * @param  bool   $includeDevRequirements
     * @return bool
     */
    public static function isInstalled($packageName, $includeDevRequirements = true)
    {
        foreach (self::getInstalled() as $installed) {
            if (isset($installed['versions'][$packageName])) {
                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
            }
        }

        return false;
    }

    /**
     * Checks whether the given package satisfies a version constraint
     *
     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
     *
     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
     *
     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
     * @param  string        $packageName
     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
     * @return bool
     */
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    {
        $constraint = $parser->parseConstraints($constraint);
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));

        return $provided->matches($constraint);
    }

    /**
     * Returns a version constraint representing all the range(s) which are installed for a given package
     *
     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
     * whether a given version of a package is installed, and not just whether it exists
     *
     * @param  string $packageName
     * @return string Version constraint usable with composer/semver
     */
    public static function getVersionRanges($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            $ranges = array();
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
            }
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
            }
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
            }
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
            }

            return implode(' || ', $ranges);
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['version'])) {
                return null;
            }

            return $installed['versions'][$packageName]['version'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getPrettyVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
                return null;
            }

            return $installed['versions'][$packageName]['pretty_version'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
     */
    public static function getReference($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['reference'])) {
                return null;
            }

            return $installed['versions'][$packageName]['reference'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
     */
    public static function getInstallPath($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @return array
     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
     */
    public static function getRootPackage()
    {
        $installed = self::getInstalled();

        return $installed[0]['root'];
    }

    /**
     * Returns the raw installed.php data for custom implementations
     *
     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
     * @return array[]
     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}
     */
    public static function getRawData()
    {
        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);

        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                self::$installed = include __DIR__ . '/installed.php';
            } else {
                self::$installed = array();
            }
        }

        return self::$installed;
    }

    /**
     * Returns the raw data of all installed.php which are currently loaded for custom implementations
     *
     * @return array[]
     * @psalm-return list}>
     */
    public static function getAllRawData()
    {
        return self::getInstalled();
    }

    /**
     * Lets you reload the static array from another file
     *
     * This is only useful for complex integrations in which a project needs to use
     * this class but then also needs to execute another project's autoloader in process,
     * and wants to ensure both projects have access to their version of installed.php.
     *
     * A typical case would be PHPUnit, where it would need to make sure it reads all
     * the data it needs from this class, then call reload() with
     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
     * the project in which it runs can then also use this class safely, without
     * interference between PHPUnit's dependencies and the project's dependencies.
     *
     * @param  array[] $data A vendor/composer/installed.php data set
     * @return void
     *
     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data
     */
    public static function reload($data)
    {
        self::$installed = $data;
        self::$installedByVendor = array();
    }

    /**
     * @return array[]
     * @psalm-return list}>
     */
    private static function getInstalled()
    {
        if (null === self::$canGetVendors) {
            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
        }

        $installed = array();

        if (self::$canGetVendors) {
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
                if (isset(self::$installedByVendor[$vendorDir])) {
                    $installed[] = self::$installedByVendor[$vendorDir];
                } elseif (is_file($vendorDir.'/composer/installed.php')) {
                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
                        self::$installed = $installed[count($installed) - 1];
                    }
                }
            }
        }

        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                self::$installed = require __DIR__ . '/installed.php';
            } else {
                self::$installed = array();
            }
        }
        $installed[] = self::$installed;

        return $installed;
    }
}
composer/platform_check.php000066400000001635151501170470012075 0ustar00= 70100)) {
    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.0". You are running ' . PHP_VERSION . '.';
}

if ($issues) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
        } elseif (!headers_sent()) {
            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
        }
    }
    trigger_error(
        'Composer detected issues in your platform: ' . implode(' ', $issues),
        E_USER_ERROR
    );
}
composer/autoload_static.php000066400000002132151501170470012264 0ustar00 
        array (
            'Automattic\\WooCommerce\\' => 23,
        ),
    );

    public static $prefixDirsPsr4 = array (
        'Automattic\\WooCommerce\\' => 
        array (
            0 => __DIR__ . '/..' . '/automattic/woocommerce/src/WooCommerce',
        ),
    );

    public static $classMap = array (
        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInit401867c5932e744c5dfedd62b35b2206::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInit401867c5932e744c5dfedd62b35b2206::$prefixDirsPsr4;
            $loader->classMap = ComposerStaticInit401867c5932e744c5dfedd62b35b2206::$classMap;

        }, null, ClassLoader::class);
    }
}
composer/autoload_namespaces.php000066400000000225151501170470013115 0ustar00 array($vendorDir . '/automattic/woocommerce/src/WooCommerce'),
);
composer/autoload_real.php000066400000003551151501170470011726 0ustar00= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
        if ($useStaticLoader) {
            require __DIR__ . '/autoload_static.php';

            call_user_func(\Composer\Autoload\ComposerStaticInit401867c5932e744c5dfedd62b35b2206::getInitializer($loader));
        } else {
            $map = require __DIR__ . '/autoload_namespaces.php';
            foreach ($map as $namespace => $path) {
                $loader->set($namespace, $path);
            }

            $map = require __DIR__ . '/autoload_psr4.php';
            foreach ($map as $namespace => $path) {
                $loader->setPsr4($namespace, $path);
            }

            $classMap = require __DIR__ . '/autoload_classmap.php';
            if ($classMap) {
                $loader->addClassMap($classMap);
            }
        }

        $loader->register(true);

        return $loader;
    }
}
composer/autoload_classmap.php000066400000000350151501170470012600 0ustar00 $vendorDir . '/composer/InstalledVersions.php',
);