123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- <?php
- const CURL_DOC_FILE = 'https://curl.haxx.se/libcurl/c/symbols-in-versions.html';
- const SOURCE_FILE = __DIR__ . '/interface.c';
- const MIN_SUPPORTED_CURL_VERSION = '7.29.0';
- const IGNORED_CONSTANTS = [
- 'CURLOPT_PROGRESSDATA'
- ];
- const CONSTANTS_REGEX_PATTERN = '~^CURL(?:OPT|_VERSION)_[A-Z0-9_]+$~';
- $curlConstants = getCurlConstants();
- $sourceConstants = getSourceConstants();
- $notInPHP = [];
- $notInCurl = [];
- $outdated = [];
- foreach ($curlConstants as $name => [$introduced, $deprecated, $removed]) {
- $inPHP = in_array($name, $sourceConstants);
- if ($removed !== null) {
- if (version_compare($removed, MIN_SUPPORTED_CURL_VERSION) <= 0) {
-
- continue;
- }
- }
- if (! $inPHP) {
- $notInPHP[$name] = [$introduced, $removed];
- }
- }
- foreach ($sourceConstants as $name) {
- if (! isset($curlConstants[$name])) {
- $notInCurl[] = $name;
- continue;
- }
- $removed = $curlConstants[$name][2];
- if ($removed === null) {
- continue;
- }
- if (version_compare($removed, MIN_SUPPORTED_CURL_VERSION) <= 0) {
-
- $outdated[$name] = $removed;
- }
- }
- $allGood = true;
- if ($notInPHP) {
- uasort($notInPHP, function($a, $b) {
- return version_compare($a[0], $b[0]);
- });
- $table = new AsciiTable();
- $table->add('Constant', 'Introduced', '', 'Removed', '');
- foreach ($notInPHP as $name => [$introduced, $removed]) {
- if ($removed === null) {
- $removed = '';
- $removedHex = '';
- } else {
- $removedHex = getHexVersion($removed);
- }
- $table->add($name, $introduced, getHexVersion($introduced), $removed, $removedHex);
- }
- echo "Constants missing from the PHP source:\n\n";
- echo $table, "\n";
- $allGood = false;
- }
- if ($notInCurl) {
- $table = new AsciiTable();
- foreach ($notInCurl as $name) {
- $table->add($name);
- }
- echo "Constants defined in the PHP source, but absent from the cURL documentation:\n\n";
- echo $table, "\n";
- $allGood = false;
- }
- if ($outdated) {
- uasort($outdated, function($a, $b) {
- return version_compare($a, $b);
- });
- $table = new AsciiTable();
- $table->add('Constant', 'Removed');
- foreach ($outdated as $name => $version) {
- $table->add($name, $version);
- }
- echo "Constants defined in the PHP source, but removed before the minimum supported cURL version:\n\n";
- echo $table, "\n";
- $allGood = false;
- }
- if ($allGood) {
- echo "All good! Source code and cURL documentation are in sync.\n";
- }
- function getCurlConstants() : array
- {
- $html = file_get_contents(CURL_DOC_FILE);
-
- preg_match('~<pre>([^<]+)</pre>~', $html, $matches);
- $constantList = $matches[1];
-
- $regexp = '/^([A-Za-z0-9_]+) +([0-9\.]+)(?: +([0-9\.\-]+))?(?: +([0-9\.]+))?/m';
- preg_match_all($regexp, $constantList, $matches, PREG_SET_ORDER);
- $constants = [];
- foreach ($matches as $match) {
- $name = $match[1];
- $introduced = $match[2];
- $deprecated = $match[3] ?? null;
- $removed = $match[4] ?? null;
- if (in_array($name, IGNORED_CONSTANTS, true) || !preg_match(CONSTANTS_REGEX_PATTERN, $name)) {
-
- continue;
- }
- if ($deprecated === '-') {
- $deprecated = null;
- }
- $constants[$name] = [$introduced, $deprecated, $removed];
- }
- return $constants;
- }
- function getSourceConstants() : array
- {
- $source = file_get_contents(SOURCE_FILE);
- preg_match_all('/REGISTER_CURL_CONSTANT\(([A-Za-z0-9_]+)\)/', $source, $matches);
- $constants = [];
- foreach ($matches[1] as $name) {
- if ($name === '__c') {
- continue;
- }
- if (!preg_match(CONSTANTS_REGEX_PATTERN, $name)) {
-
- continue;
- }
- $constants[] = $name;
- }
- return $constants;
- }
- function getHexVersion(string $version) : string
- {
- $parts = explode('.', $version);
- if (count($parts) === 2) {
- $parts[] = '0';
- }
- if (count($parts) !== 3) {
- throw new \RuntimeException('Invalid version number: ' . $version);
- }
- $hex = '0x';
- foreach ($parts as $value) {
- if (! ctype_digit($value) || strlen($value) > 3) {
- throw new \RuntimeException('Invalid version number: ' . $version);
- }
- $value = (int) $value;
- if ($value > 255) {
- throw new \RuntimeException('Invalid version number: ' . $version);
- }
- $value = dechex($value);
- if (strlen($value) === 1) {
- $value = '0' . $value;
- }
- $hex .= $value;
- }
- return $hex;
- }
- class AsciiTable
- {
-
- private $values = [];
-
- private $length = [];
-
- private $padding = 4;
-
- public function add(string ...$values) : void
- {
- $this->values[] = $values;
- foreach ($values as $key => $value) {
- $length = strlen($value);
- if (isset($this->length[$key])) {
- $this->length[$key] = max($this->length[$key], $length);
- } else {
- $this->length[$key] = $length;
- }
- }
- }
-
- public function __toString() : string
- {
- $result = '';
- foreach ($this->values as $values) {
- foreach ($values as $key => $value) {
- if ($key !== 0) {
- $result .= str_repeat(' ', $this->padding);
- }
- $result .= str_pad($value, $this->length[$key]);
- }
- $result .= "\n";
- }
- return $result;
- }
- }
|