The Content Management System Hooks (CMS Hooks) API is for users wishing to display various output from a WIKINDX database into a CMS (Content Management System). It requires some minimal configuration in the Admin > Configure panel.
The following assumes the path to the WIKINDX is https://wikindx.test/ – if not, adjust the path accordingly.
With a browser go to the page https://wikindx.test/cmsprint.php. If you get the message “CMS feature disabled”, you still have to unlock the CMS feature. If you get the message “Unknown action” you are ready use it.
In the examples below, we assume you use a CMS written in PHP, as most are, but the approach remains valid for any program capable of using the HTTP protocol.
In the appendix you will find two basic functions to help you write your first queries. This code uses the cUrl extension (to be activated in the php.ini
configuration file if it is not done).
It is strongly advised not to use file_get_contents()
or fopen()
to make your requests (allow_url_fopen
option need to be activated for that). These functions do not provide a means of debugging the code and are susceptible to attacks allowing the execution of arbitrary code. That’s why we provide the curl_get()
function as an appendix.
During development you can check that a response is correct by checking cUrl and HTTP error codes. When all goes well cUrl returns code 0 and HTTP 200. It is rare that cUrl returns an error unless its configuration is not adapted to your network (e.g. mandatory proxy). However, you may frequently encounter the following HTTP errors:
curl_get()
and curl_post()
).The CMS Hooks API has two family of queries:
The API only uses two HTTP verbs GET and POST.
Sending a GET or POST request consists of calling a URL with parameters called queryString. The queryString first parameter (case sensitive) is always preceded by a question mark, the following by an ampersand. The name of a parameter is separated from its value by an equal sign. When special characters appear they must be escaped (this should not be the case because the expected values are numeric in our case).
Examples:
https://wikindx.test/cmsprint.php?param1=value1
https://wikindx.test/cmsprint.php?param1=value1¶m2=value2
https://wikindx.test/cmsprint.php?param1=value1¶m2=value2¶m3=it%27s+value+3
When the request uses the POST verb, we also add a body encoded with the method application/x-www-form-urlencoded
(RFC1738). This is information that we want the server to process in addition to parameters. The curl_post()
function is written to support this encoding transparently.
The rest of the document describes the verb, the combinations of parameters and the body to send, to obtain the desired result.
The following parameters are valid in all queries.
action is required and must have valid values (case sensitive) ; This parameter indicates what type of response you expect. The values are described later.
mimetype is optional and can take values (case sensitive) php (default) or json. This parameter conditions the format of the data returned. To read serialized PHP, use the unserialize() function, for json use json_decode().
bibStyle is optional and selects the bibliographic style used for formatting resources. If this parameter is omitted or its value is wrong the style configured in admin panel will be used. Accepted values are the identifier of a style in uppercase. The APA style is always available, the other styles delivered with WIKINDX may not be installed (ABNT, BRITISHMEDICALJOURNAL, CFB, CHICAGO-AD, CHICAGO-FT, HARVARD, IEEE, MLA, TURABIAN, WIKINDX).
language is optional and select your preferred locale used for formatting resources. If this parameter is omitted or its value is wrong the locale configured in the style will be used. Example of accepted locale: en, fr, de_AT, etc.
In all cases, the return from WIKINDX comprises zero, one or more resources matching the queryString parameters inside an array.
We describe here the operation of the parameters common to these actions, then the actions and the exceptions if necessary with examples.
action is required and must have valid values among : getAll, getResource, getCategory, getSubCategory, getKeyword, getCreator, getPublisher, getCollection, getAbstract, getNotes, getQuote, getParaphrase, getMusing, getRecent.
id is required, excepting getAll and getRecent actions, and must have valid values. The id you wish to use may be found directly in WIKINDX (if you’ve set your WIKINDX Preferences to view the CMS pop-up window). You can specify multiple ids separated by commas.
limit is optional. e.g. &limit=10 in the queryString will limit
the results of any list to 10. limit will be
ignored if action=getResource
or action=getAll
. The default is unlimited, which is not really unlimited because requests have a maximum size and execution time that depends on the server configuration of requested WIKINDX.
start is optional but if used depends on the presence of limit (otherwise, start will be ignored). e.g. &start=5 in the queryString will return a list beginning after the 5th element. start will be
ignored if action=getResource
or action=getAll
or action=getRecent
. The default is 0, the beginning of the list.
order is optional. e.g. order=year
in the queryString will
display a list ordered by publication year. Possible values are
creator, year, title, and timestamp. The default is creator. getAll action always use timestamp order.
When using getKeyword, getCategory or getCreator, you may have
a further parameter of sqlMethod=and
which allows you to return
results, for example, where each resource belongs to all requested
categories. By default, the resources in the result match any one of the
requested categories. Ditto for keywords and creators.
When getting notes, quotes, paraphrases or musings, only public ones are returned.
The output is a string representing a JSON array or a serialized PHP array.
Example of JSON response:
{"95":"de Sainte-Marie, A., & du Fourny, H. (1733). <em>Histoire g\u00e9n\u00e9alogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume<\/em>. Vol. 7. 75 - Paris: Compagnie des Libraires."}
To access the JSON array, you will need to use the following code:
$array = json_decode($response, TRUE);
Example of PHP response:
a:1:{i:95;s:263:"de Sainte-Marie, A., & du Fourny, H. (1733). <em>Histoire généalogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume</em>. Vol. 7. 75 - Paris: Compagnie des Libraires.";}
To access the PHP array, you will need to use the following code:
$array = unserialize($response);
The contents of $array
may be like the following example:
[13] => Back, M., & Des, D. (1996). Micro-narratives in sound design: Context and caricature in waveform manipulation. Retrieved March 12, 2004, from <a href="http://www2.hku.nl/~audiogam/ag/articles/micronaratives.htm" target="_blank">http://www2.hku.nl/~aud ... cles/micronaratives.htm</a>.
[54] => Carr, D. (2003). Play dead: Genre and affect in silent hill and planescape torment. <em>Game Studies</em><em>, 3</em>(1). Retrieved September 16, 2003, from <a href="http://www.gamestudies.org/0301/carr/" target="_blank">http://www.gamestudies.org/0301/carr/</a>.
[2] => Chion, M. (1992). Wasted words. In R. Altman (Ed.), <em>Sound Theory Sound Practice</em> (pp. 104–110). New York: Routledge.
[103] => Chion, M. (1994). <em>Audio-vision: Sound on screen</em> (C. Gorbman, Trans.) New York: Columbia University Press.
[4] => Truppin, A. (1992). And then there was sound: The films of Andrei Tarkovsky. In R. Altman (Ed.), <em>Sound Theory Sound Practice</em> (pp. 235–248). New York: Routledge.
Note that, depending upon the bibliographic style chosen, the results may contain HTML tags and entities (as in the above example). The key of each array member is the resource ID.
You can then loop through this array in order to format and print the individual items as you wish. An example might be:
foreach($array as $resourceId => $item)
{
print $item . "<br>";
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getAll
Example of JSON response:
{
"12": "Saffroy, G. (1970). <em>Bibliographie généalogique, héraldique et nobiliaire de la France des origines à nos jours, imprimés et manuscrits</em>. 75 - Paris: Saffroy.",
"39": "Barré de Saint-Venant, R. (1969). <em>Dictionnaire topographique, historique, biographique, généalogique et héraldique du vendômois et de l'arrondissement de vendôme</em>. Vendôme, 41: Société archéologique, scientifique et littéraire du Vendômois. (Original work published 1912-1917).",
"73": "Votre Généalogie. (2008). Votre généalogie n° 27. <em>Votre Généalogie</em>, <em>27</em>.",
"92": "de Sainte-Marie, A., & du Fourny, H. (1727). <em>Histoire généalogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume</em>. Vol. 3. 75 - Paris: Compagnie des Libraires.",
"94": "de Sainte-Marie, A., & du Fourny, H. (1730). <em>Histoire généalogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume</em>. Vol. 6. 75 - Paris: Compagnie des Libraires.",
"95": "de Sainte-Marie, A., & du Fourny, H. (1733). <em>Histoire généalogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume</em>. Vol. 7. 75 - Paris: Compagnie des Libraires."
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getResource&id=95
Example of JSON response:
{
"95": "de Sainte-Marie, A., & du Fourny, H. (1733). <em>Histoire généalogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume</em>. Vol. 7. 75 - Paris: Compagnie des Libraires."
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getCategory&id=4
Example of JSON response:
{
"92": "de Sainte-Marie, A., & du Fourny, H. (1727). <em>Histoire généalogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume</em>. Vol. 3. 75 - Paris: Compagnie des Libraires."
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getSubcategory&id=2
Example of JSON response:
{
"94": "de Sainte-Marie, A., & du Fourny, H. (1730). <em>Histoire généalogique et chronologique de la maison royale de france et des grands officiers de la couronne, de la maison du roy et des anciens barons du royaume</em>. Vol. 6. 75 - Paris: Compagnie des Libraires."
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getKeyword&id=12
Example of JSON response:
{
"73": "Votre Généalogie. (2008). Votre généalogie n° 27. <em>Votre Généalogie</em>, <em>27</em>."
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getCreator&id=143
Example of JSON response:
{
"12": "Barré de Saint-Venant, R. (1970). <em>Bibliographie généalogique, héraldique et nobiliaire de la France des origines à nos jours, imprimés et manuscrits</em>. 75 - Paris: Saffroy.",
"39": "Barré de Saint-Venant, R. (1969). <em>Dictionnaire topographique, historique, biographique, généalogique et héraldique du vendômois et de l'arrondissement de vendôme</em>. Vendôme, 41: Société archéologique, scientifique et littéraire du Vendômois. (Original work published 1912-1917)."
}
To display up to 5 resources by two particular creators (where they are co-authors), ordered by publication year:
HTTP verb: GET
Example of JSON response:
{
"5": "Bernard, G., Escalle, E., Maurin, I. (1976). <em>Maurs au fil des siècles: Des origines à 1789</em>.",
"6": "Bernard, G., Escalle, E., Maurin, I. (1988). <em>Guide des recherches sur l'histoire des familles</em>.",
"9714": "Bernard, G., Escalle, E., Maurin, I. (1987). <em>Les familles protestantes en france : xvie siècle - 1792 : guide des recherches biographiques et généalogiques</em>. 75 - Paris: Archives de France.",
"15149": "Bernard, G., Escalle, E., Maurin, I., G. (1990). <em>Les familles juives en france : xvie siècle-1815 : guide des recherches biographiques et généalogiques</em>. 75 - Paris: Archives Nationales.",
"19999": "Bernard, G., Escalle, E., Maurin, I., Pariset, J.-D., & Zuber, H. (1987). <em>Les familles protestantes en france : xvie siècle-1792 : guide des recherches biographiques et généalogiques</em>. 75 - Paris: Archives Nationales."
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getPublisher&id=42
Example of JSON response:
{
"75": "Tanguay, C. (1871). <em>Dictionnaire généalogique des familles canadiennes depuis la fondation de la colonie jusqu'à nos jours</em>. Vol. 1. Québec: Senécal.",
"76": "Tanguay, C. (1886). <em>Dictionnaire généalogique des familles canadiennes depuis la fondation de la colonie jusqu'à nos jours</em>. Vol. 2. Québec: Senécal.",
"77": "Tanguay, C. (1886). <em>Dictionnaire généalogique des familles canadiennes depuis la fondation de la colonie jusqu'à nos jours</em>. Vol. 3. Québec: Senécal.",
"78": "Tanguay, C. (1888). <em>Dictionnaire généalogique des familles canadiennes depuis la fondation de la colonie jusqu'à nos jours</em>. Vol. 5. Québec: Senécal.",
"79": "Tanguay, C. (1889). <em>Dictionnaire généalogique des familles canadiennes depuis la fondation de la colonie jusqu'à nos jours</em>. Vol. 6. Québec: Senécal.",
"80": "Tanguay, C. (1890). <em>Dictionnaire généalogique des familles canadiennes depuis la fondation de la colonie jusqu'à nos jours</em>. Vol. 7. Québec: Senécal."
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getCollection&id=13
Example of JSON response:
{"125":"Collectif. <em>Les monographies des instituteurs de seine-et-oise<\/em>. Unpublished manuscript."}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getAbstract&id=242
Example of JSON response:
{
"10": "Louis-Etienne SAINT-DENIS (alias le mameluck ALI). Entré en 1806 au service de Napoléon, Louis-Etienne Saint-Denis (né à Versailles en 1788) passe en décembre 1811 au service intérieur comme second \"mameluck\". C'est par la volonté de l'Empereur qu'il s'appellera désormais Ali. Faux \"mameluck\" mais vrai témoin, Ali note tout par le menu, depuis la campagne de Russie jusqu'à la mort de l'Empereur - en passant par le premier exil à l'île d'Elbe, la défaite des armées françaises à Waterloo et l'embarquement pour Sainte-Hélène. Comme l'a écrit Jean-Paul Kauffmann : \"Ali est la mémoire visuelle de la captivité.\" Publiés pour la première fois en 1926 et jamais réédités depuis, les Souvenirs du Mameluck Ali sur l'Empereur Napoléon constituent un témoignage unique sur l'homme qui a marqué l'Histoire à tout jamais. Ouvrage sincère et captivant !"
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getNotes&id=74,75,76
Example of JSON response:
{"74":"17 fascicules","75":"Québec","76":"Québec"}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getQuote&id=755,22830
Example of JSON response:
{
"755": {
"1": "Depuis que le Reich hitlérien a disparu, avec les camps de concentration qui en étaient une caractéristique essentielle, la littérature sur ce sujet n'a pas cessé d'être importante, en Allemagne même, et dans les autres pays concernés, pays européens, États-Unis ou Israël."
},
"22830": {
"10": "Martin est le nom le plus répandu en France",
"12": "Petit est un patronyme très courant en France."
}
}
The response is an array of arrays. Keys of the main array are resource ids and subarrays are quotes where the key is a quote id and the value is the quote.
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getParaphrase&id=915
Example of JSON response:
{
"915": {
"8": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut leo nibh, iaculis quis nunc scelerisque, pellentesque volutpat arcu. Phasellus tellus leo, accumsan eget dolor lacinia, maximus facilisis ex. Donec sodales vel ipsum sed fringilla. Pellentesque quis suscipit dolor. Fusce eleifend congue eros elementum commodo. Curabitur placerat quam at eros facilisis, eu volutpat nunc dignissim. Praesent aliquet lectus mauris, ut feugiat dolor sagittis vitae."
}
}
HTTP verb: GET
Request: https://wikindx.test/cmsprint.php?mimetype=json&action=getMusing&id=11520
Example of JSON response:
{
"22830": {
"6": "Cras non sodales ex. Curabitur pellentesque metus facilisis consequat efficitur. Sed vitae turpis non velit maximus cursus eu blandit nunc. Fusce vehicula risus rutrum posuere molestie.",
"7": "Vestibulum in laoreet leo, vitae dictum sapien. Fusce mollis augue mauris, eget sodales metus ullamcorper at."
}
}
The response is an array of arrays. Keys of the main array are resource ids and subarrays are musings where the key is a quote id and the value is the musing.
To display the 10 most recently added resources:
HTTP verb: GET
Request: http://wikindx.test/cmsprint.php?mimetype=json&action=getRecent&limit=3
Example of JSON response:
{
"21602": "Anonyme. (2008). <em>Saint vincent des landes (44) - décès de 1670 à 1802</em>. 35 - Grand Fougeray: Histoire et Généalogie.",
"22830": "<em>Les vieux noms de la france de l’ouest et les familles d’origine française au delà des mers</em>. (1954). Vol. 868. Beauchênes.",
"22832": "<em>Bretet 12: Uie</em>. January 24 2020. Edison."
}
To display at most 15 resources added within the last 5 days:
HTTP verb: GET
Request: http://wikindx.test/cmsprint.php?mimetype=json&action=getRecent&limit=7&days=5
Example of JSON response:
{
"21602": "Anonyme. (2008). <em>Saint vincent des landes (44) - décès de 1670 à 1802</em>. 35 - Grand Fougeray: Histoire et Généalogie.",
"22827": "France, M. D. (1958). <em>Histoire de la famille de france : venue d’artois en champagne, 1415-1957. [avant-propos de michel de france.]</em>. Vol. 865. 42 -\tSaint-Just-la-Pendue: Imprimerie Chirat.",
"22828": "Le Blant, R. (1955). <em>Robert le blant. nobiliaire de béarn : tome 2</em>. Vol. 866. 40 -\tDax: Impr. de Dumolia.",
"22829": "<em>Recueil généalogique de la bourgeoisie ancienne. deuxième série</em>. (1955). Vol. 867. 75 -\tParis: Editions S.G.A.F.",
"22830": "<em>Les vieux noms de la france de l’ouest et les familles d’origine française au delà des mers</em>. (1954). Vol. 868. Beauchênes.",
"22831": "Vrignault, H.-Y.-F. (1954). <em>Les enfants de louis xv, descendance illégitime</em>. Vol. 869. 75 - Paris: Perrin.",
"22832": "<em>Bretet 12: Uie</em>. January 24 2020. Edison."
}
WIKINDX may be used to format a series of citations within a block of CMS text that uses the CMS replacement tags. The CMS replacement tag may be automatically generated for pasting into the CMS text by using the WIKINDX CMS pop-up window if you have set the CMS hyperlink to display in your WIKINDX preferences. The citation style, by default, uses the style set in the WIKINDX admin panel.
If your CMS text block containing the replacement tags is:
Chion states that: "Blah, blah, blah" {ADD_BIB_ITEM:3:314} but in a later article corrects this by saying: "Bleah, bleah, bleah" {ADD_BIB_ITEM:89:22-23}.
the output from WIKINDX (assuming the current style is APA) may be:
Chion states that: "Blah, blah, blah" (1999, 314) but in a later article corrects this by saying: "Bleah, bleah, bleah" (2001, 22–23).
The replacement tag may have further parameters: it is recommended to use the CMS replacement tag generator in WIKINDX for greatest accuracy.
There are several steps in creating the replacement tag code in your CMS, sending the text block to WIKINDX and receiving it back:
if (strpos($text, "{ADD_BIB_ITEM:") === FALSE)
{
return;
}
preg_replace()
to reformat your particular CMS replacement
tags to a format WIKINDX will recognize (using [cite]...[/cite]
).
For example, with the CMS replacement tags in the example above,
you should use:$text = preg_replace("/\{ADD_BIB_ITEM:(.*)\}/Ui", "[cite]$1[/cite]", $text);
Using the example above, this code will produce:
Chion states that: "Blah, blah, blah" [cite]3:314[/cite] but in a later article corrects this by saying: "Bleah, bleah, bleah" [cite]89:22-23[/cite].
Write the new $text
to a temporary file on your web server.
Send a POST to WIKINDX where you give the text to parse as a value of text body parameter.
$response_array = curl_post("https://wikindx.test/cmsprint.php?action=parseText", ["text" => "Belle journée [cite]22827[/cite] [cite]22828[/cite] pour une promenade [footnote]J'aime particuliérement le bord du lac[/footnote]"]);
$string
back to your CMS.echo $response_array["response"];
Note the following:
The response will contain not only the formatted text block but will
also contain an appended bibliography of the citations in the text.
Where the current style is an in-text citation style such as APA,
this bibliography is separated by <br><br>
– if your CMS uses
similar HTML code for line breaks and you wish to be able to split this
bibliography from the text for some reason, you should replace all
occurrences of <br>
with a unique string prior to sending
it to the WIKINDX and then split the result on <br><br>
before
reverting that unique string back to <br>
and finally printing
the result back to the CMS. If the current style is a style using
footnotes such as Chicago, the WIKINDX result contains the formatted
text, the required footnote citations and the appended bibliography.
Splitting the WIKINDX result on <br><br>
will produce an array
of three members, the first being the text block, the second being the
footnotes and the third being the bibliography. For example, you might
use the following code:
$text = preg_replace("/\{ADD_BIB_ITEM:(.*)\}/Ui", "[cite]$1[/cite]", $text);
$text = str_replace('<br>', 'IAMAUNIQUESTRING', $text);
$response_array = curl_post("https://wikindx.test/cmsprint.php?action=parseText", ["text" => $text]);
$split = preg_split("/(<br \/>){2,2}/i", $response_array["response"]);
$text = str_replace('IAMAUNIQUESTRING', '<br>', $split[0]);
$footnotes = $split[1];
$bibliography = $split[2];
<?php
$cms_url = "http://wikindx.test/cmsprint.php?action=parseText";
$response_array = curl_get($cms_url);
// Print the whole array
//echo print_r($response_array);
// Print only the response
echo $response_array["response"];
/**
* Send a GET HTTP request
*
* @param string $url - the url
* @param bool $verbose_mode Set to TRUE to get raw traces
*
* @return array
*/
function curl_get($url, $verbose_mode = FALSE)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url ?? "");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
// Disables certificate verification and proxy usage
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_PROXY, NULL);
// Timeout de la connexion en secondes
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
// Timeout de l'exécution en secondes
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_VERBOSE, $verbose_mode);
$response = curl_exec($ch);
if ($response === FALSE)
{
$response = "";
}
$errno_http = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$errmsg_http = http_strerror($errno_http);
$errno_curl = curl_errno($ch);
$errmsg_curl = curl_strerror($errno_curl);
// Since PHP 8.0 the curl_close() function no longer has an effect
if (version_compare(PHP_VERSION, '8.0.0', '<'))
{
curl_close($ch);
}
return [
"errno_curl" => $errno_curl,
"errmsg_curl" => $errmsg_curl,
"errno_http" => $errno_http,
"errmsg_http" => $errmsg_http,
"response" => $response,
];
}
/**
* Send a POST HTTP request
*
* @param string $url - the url
* @param bool $verbose_mode Set to TRUE to get raw traces
*
* @return array
*/
function curl_post($url, $data = NULL, $verbose_mode = FALSE)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url ?? "");
curl_setopt($ch, CURLOPT_POST, TRUE);
if (!is_null($data))
{
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
}
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
// Disables certificate verification and proxy usage
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_PROXY, NULL);
// Connection timeout in seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
// Execution timeout in seconds
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_VERBOSE, $verbose_mode);
$response = curl_exec($ch);
if ($response === FALSE)
{
$response = "";
}
$errno_http = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$errmsg_http = http_strerror($errno_http);
$errno_curl = curl_errno($ch);
$errmsg_curl = curl_strerror($errno_curl);
// Since PHP 8.0 the curl_close() function no longer has an effect
if (version_compare(PHP_VERSION, '8.0.0', '<'))
{
curl_close($ch);
}
return [
"errno_curl" => $errno_curl,
"errmsg_curl" => $errmsg_curl,
"errno_http" => $errno_http,
"errmsg_http" => $errmsg_http,
"response" => $response,
];
}
/**
* Return the english name associated with an HTTP error code
*
* @param int|string $errno - HTTP error code
*
* @return string
*/
function http_strerror($errno)
{
if (is_string($errno) && is_numeric)
{
if (is_numeric($errno))
{
$errno = intval($errno);
}
else
{
$errno = 0;
}
}
$http_status_codes = [
// 1xx informational response
100 => "Continue",
101 => "Switching Protocols",
102 => "Processing",
103 => "Early Hints",
// 2xx success
200 => "OK",
201 => "Created",
202 => "Accepted",
203 => "Non-Authoritative Information",
204 => "No Content",
205 => "Reset Content",
206 => "Partial Content",
207 => "Multi-Status",
208 => "Already Reported",
226 => "IM Used",
// 3xx redirection
300 => "Multiple Choices",
301 => "Moved Permanently",
302 => "Found",
303 => "See Other",
304 => "Not Modified",
305 => "Use Proxy",
306 => "Switch Proxy",
307 => "Temporary Redirect",
308 => "Permanent Redirect",
// 4xx client errors
400 => "Bad Request",
401 => "Unauthorized",
402 => "Payment Required",
403 => "Forbidden",
404 => "Not Found",
405 => "Method Not Allowed",
406 => "Not Acceptable",
407 => "Proxy Authentication Required",
408 => "Request Timeout",
409 => "Conflict",
410 => "Gone",
411 => "Length Required",
412 => "Precondition Failed",
413 => "Payload Too Large",
414 => "URI Too Long",
415 => "Unsupported Media Type",
416 => "Range Not Satisfiable",
417 => "Expectation Failed",
418 => "I'm a teapot",
421 => "Misdirected Request",
422 => "Unprocessable Entity",
423 => "Locked",
424 => "Failed Dependency",
425 => "Too Early",
426 => "Upgrade Required",
428 => "Precondition Required",
429 => "Too Many Requests",
431 => "Request Header Fields Too Large",
451 => "Unavailable For Legal Reasons",
// 5xx server errors
500 => "Internal Server Error",
501 => "Not Implemented",
502 => "Bad Gateway",
503 => "Service Unavailable",
504 => "Gateway Timeout",
505 => "HTTP Version Not Supported",
506 => "Variant Also Negotiates",
507 => "Insufficient Storage",
508 => "Loop Detected",
510 => "Not Extended",
511 => "Network Authentication Required",
// DeepL specific code
456 => "Quota exceeded",
529 => "Too many requests",
];
return $http_status_codes[$errno] ?? "";
}