I am using the Wikimedia api and php. I need to get first main image from article and all text in article. I have got code for it, but it takes only short info and very little picture. I tried to change many parameters, but it is not working.
Code is here:
function get_wiki_url($title) {
$context = stream_context_create(array(
'http' => array(
'method'=>"POST",
'content' => $reqdata = http_build_query(array(
'action' => 'opensearch',
'search' => $title,
'prop' => 'info',
'format' => 'xml',
'inprop' => 'url'
)),
'header' => implode("\r\n", array(
"Content-Length: " . strlen($reqdata),
"User-Agent: MyCuteBot/0.1",
"Connection: Close",
""
))
)));
if (false === $response = file_get_contents("http://ru.wikipedia.org/w/api.php", false, $context)) {
return false;
}
//парсим строку
$xml = simplexml_load_string($response);
return $xml->Section->Item;
}
var_dump ($pages_data = get_wiki_url("article header"));
Your query appears to be running a search for $title (parameter action=opensearch); if you want the article and main image (I presume you want HTML, not wikitext), you need to use action=parse -- see the Mediawiki parse documentation.
Example URL for getting the Hyperloop page:
http://ru.wikipedia.org/w/api.php?action=parse&format=xml&page=Hyperloop
The documentation has details on all the options available.
Related
I have a php script to update my subscribers from my wordpress userlist to Mailchimp using batch-subscribe. (https://apidocs.mailchimp.com/api/2.0/lists/batch-subscribe.php)
Everything works fine when I submit about 400 records. All records are added, and I get a return from the API with the number of added records, etc.
If I submit about 600 or more (I have about 730 subscribers), all records are added to Mailchimp, but the API returns FALSE. I double checked it with === false, and it is false. I get no errors -- it just returns false (but all records are added to Mailchimp).
Mailchimp says "Maximum batch sizes vary based on the amount of data in each record, though you should cap them at 5k - 10k records, depending on your experience." (https://apidocs.mailchimp.com/api/2.0/lists/batch-subscribe.php).
I'm nowhere close to that, and every record is being added to the mailchimp list just fine. I just don't get the return from the API.
I've increased my timeout value to 5 minutes. I also switched to using different records, suspecting I might have had a record with something that was causing it to mess up, but it had the same behavior with different records.
I'm using the DrewM library to interface with Mailchimp API version 2.0. I double checked to make sure DrewM is using post for the request, and it does. (https://github.com/drewm/mailchimp-api/)
Any ideas what is causing this?
Here is the code:
function mailchimpdailyupdate () {
set_time_limit(300);
$api = get_mc_api();
$mcListId = get_mc_mailing_list();
$MailChimp = new \Drewm\MailChimp($api);
...
foreach ( $blogusers as $user ) {
$userinfo = get_userdata( $user->ID );
$location = ...//code to get location
$merge_vars = array(
'FNAME'=> $userinfo->first_name,
'LNAME'=> $userinfo->last_name,
'MMERGE3'=> $userinfo->user_login, //username
'MMERGE6'=> $location //location
);
$batch[] = array(
'email' => array('email' => $user->user_email),
'merge_vars' => $merge_vars
);
} //end foreach
//mailchimp call
$retval = $MailChimp->call('lists/batch-subscribe', array(
'id' => $mcListId, // your mailchimp list id here
'batch' => $batch,
'update_existing' => true
)
);
if ($retval === false) {
echo "Mailchimp API returned false";
}
echo 'Added: ' . $retval['add_count'] . "<br/>";
echo 'Updated: ' . $retval['update_count'] . "<br/>";
echo 'Errors: ' . $retval['error_count'] . "<br/>";
}
With help from Mailchimp support, I was able to locate and solve the problem.
The issue was actually in the DrewM wrapper.
The content-length section of the header was apparently not working correctly on long calls. I removed it, and everything began working fine.
Original section of DrewM code (not working):
$result = file_get_contents($url, null, stream_context_create(array(
'http' => array(
'protocol_version' => 1.1,
'user_agent' => 'PHP-MCAPI/2.0',
'method' => 'POST',
'header' => "Content-type: application/json\r\n".
"Connection: close\r\n" .
"Content-length: " . strlen($json_data) . "\r\n",
'content' => $json_data,
),
)));
Updated section of code (working):
$result = file_get_contents($url, null, stream_context_create(array(
'http' => array(
'protocol_version' => 1.1,
'user_agent' => 'PHP-MCAPI/2.0',
'method' => 'POST',
'header' => "Content-type: application/json\r\n".
"Connection: close\r\n",
'content' => $json_data,
),
)));
I want to update a video using google api v3 and i get the error 400 Bad Request.
This is my code.
$url = 'https://www.googleapis.com/youtube/v3/videos?part=snippet&videoId='.$_GET['videoId'].'&access_token='.Session::get('access_token');
$params = array(
"id"=> $_GET['videoId'],
"kind"=> "youtube#video",
'snippet' => array(
"title"=> "I'm being changed.",
"categoryId"=> "10",
"tags"=> array(
"humanities",
"Harpham",
"BYU"
),
'description' => 'test!'
)
);
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'PUT',
'content' => http_build_query($params),
),
);
$context = stream_context_create($options);
$result = json_decode(file_get_contents($url, false, $context));
I think since you don't set all parameters inside snippet, that's giving an error. What you can do is, first getting that video with videos->list, then updating the field you are interested in and sending back the update request with the whole object back.
Here's an example also utilizing php client library: https://github.com/youtube/api-samples/blob/master/php/update_video.php
I'm getting this error:
`file_get_contents(): stream does not support seeking
I have no clue to fix it. There is no Resource Id or whatsoever.
This is my code:
$postData = array('name' => $name, 'description' => $description, 'date_begin' => $start, 'date_end' => $end);
$stream = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n"
. "Authorization: Basic Y3Nub2VrOnNuMDNr\r\n",
'method' => 'POST',
'content' => http_build_query($postData)
)
);
return stream_context_create($stream);
And in the file where the stream returns to. Its the function getApiContext.
$responseJson = json_decode(file_get_contents('http://10.0.0.89/api/v1/projects', false, BaseController::getApiContext(), true));
And then I get this annoying error. I know about cUrl, but I must use streams.
why have you got true on your file_get_contents offset param? perhaps you meant to put this in the json_decode if so, try this:
$responseJson = json_decode(file_get_contents('http://10.0.0.89/api/v1/projects', false, BaseController::getApiContext()),true);
It seems you are passing the fourth parameter to file_get_contents, this is not supported for remote streams (as per the documentation: http://no1.php.net/manual/en/function.file-get-contents.php)
Change your call to file_get_contents to exclude it (or pass it to json_decode if that was your intent).
$responseJson = json_decode(file_get_contents('http://10.0.0.89/api/v1/projects', false, BaseController::getApiContext()));
I am troubleshooting some problems with POSTing to a remote site, specifically the remote host never returns any data (empty string).
Before I try to troubleshoot anything else, I want to make sure the calling code is actually correct. The code is:
$context = stream_context_create(array('http' => array(
'method' => "POST",
'header' => "Content-Type: application/xml",
'timeout' => 60.0,
'ignore_errors' => true, # return body even if HTTP status != 200
'content' => $send_xml
)));
$response = trim(file_get_contents($this->bulk_service_url, false, $context));
All my questions belong to the "header" option and it's values, and how to correctly format it and write it. The PHP documentation, discussion below it and even stackoverflow research yield very inconsistent results.
1) do I have to include the Content-Length header, and if not, will PHP calculate it correctly? The documentation does not include it, but I've seen many people include it manually, is it then respected or overwritten by PHP?
2) do I have to pass the header option as a string, or an associative array? Manual says string, majority pass it as a string, but this comment says that if PHP was compiled with --with-curlwrappers option, you have to pass it as an array. This is very inconsistent behavior.
3) when passing as a string, do I have to include terminating \r\n characters? Especially when specifying just one header. Manual does not provide such an example, first comment on manual page does include it, second one does not, again, no clear rule on how to specify this. Does PHP automatically handle both cases?
The server is using PHP 5.3.
You should really store your headers within code as an array and finalize the preparation just prior to sending the request...
function prepareHeaders($headers) {
$flattened = array();
foreach ($headers as $key => $header) {
if (is_int($key)) {
$flattened[] = $header;
} else {
$flattened[] = $key.': '.$header;
}
}
return implode("\r\n", $flattened);
}
$headers = array(
'Content-Type' => 'application/xml',
'ContentLength' => $dl,
);
$context = stream_context_create(array('http' => array(
'method' => "POST",
'header' => prepareHeaders($headers),
'timeout' => 60.0,
'ignore_errors' => true,
'content' => $send_xml
)));
$response = trim(file_get_contents($url, FALSE, $context));
Preparing context try to add:
ContentLength: {here_calculated_length} in 'header' key preceded with \r\n
"\r\n" at the end of 'header' key.
So it should look like:
$dl = strlen($send_xml);//YOUR_DATA_LENGTH
$context = stream_context_create(array('http' => array(
'method' => "POST",
'header' => "Content-Type: application/xml\r\nContentLength: $dl\r\n",
'timeout' => 60.0,
'ignore_errors' => true, # return body even if HTTP status != 200
'content' => $send_xml
)));
Just a little improvement of the suggestion by #doublejosh, in case it helps someone:
(use of array notation and one-liner lambda function)
$headers = [
'Content-Type' => 'application/xml',
'Content-Length' => strlen($send_xml)
];
$context = stream_context_create(['http' => [
'method' => "POST",
'header' => array_map(function ($h, $v) {return "$h: $v";}, array_keys($headers), $headers),
'timeout' => 60.0,
'ignore_errors'=> true,
'content' => $send_xml
]
]);
Sorry, I can only post 2 hyperlinks so I'm going to have to remove the http : //
Background
I'm, trying to convert the code here: https://github.com/RusticiSoftware/TinCan_Prototypes/blob/92969623efebe2588fdbf723dd9f33165694970c/ClientPrototypes/StatementIssuer/StatementIssuer.java
into PHP, specifically the makeRequest function. This code posts data to a Tin Can Compliant Learner Record Store.
The current version of my PHP code is here:
tincanapi.co.uk/wiki/tincanapi.co.uk:MediaWikiTinCan
The specification for the Tin Can API which everything should conform to is here:
scorm.com/wp-content/assets/tincandocs/TinCanAPI.pdf
There is also a working java script function that Posts data in the right format here (see the XHR_request function I think):
https://github.com/RusticiSoftware/TinCan_Prototypes/blob/92969623efebe2588fdbf723dd9f33165694970c/ClientPrototypes/GolfExample_TCAPI/scripts/TCDriver.js
I don't have access to the code or server that I'm posting to, but the end result should be an output here: beta.projecttincan.com/ClientPrototypes/ReportSample/index.html
Problem
I'm trying to use Curl to POST the data as JSON in PHP. Curl is returning 'false' but no error and is not posting the data.
On the recommendation of other questions on this site, I've tried adding 'json=' to the start of the POSTFIELDS, but since the Java and JavaScript versions does have this, I'm not sure this is right.
Can anybody suggest either how I might fix this or how I might get useful errors out of curl? My backup is to output the relevant JavaScript to the user's browser, but surely PHP should be able to do this server side?
Very grateful for any help.
Andrew
At least one thing is wrong: you should not be using rawurlencode on your Authorization header value.
Consider using php streams and json_encode() and json_decode() instead. The following code works.
function fopen_request_json($data, $url)
{
$streamopt = array(
'ssl' => array(
'verify-peer' => false,
),
'http' => array(
'method' => 'POST',
'ignore_errors' => true,
'header' => array(
'Authorization: Basic VGVzdFVzZXI6cGFzc3dvcmQ=',
'Content-Type: application/json',
'Accept: application/json, */*; q=0.01',
),
'content' => json_encode($data),
),
);
$context = stream_context_create($streamopt);
$stream = fopen($url, 'rb', false, $context);
$ret = stream_get_contents($stream);
$meta = stream_get_meta_data($stream);
if ($ret) {
$ret = json_decode($ret);
}
return array($ret, $meta);
}
function make_request()
{
$url = 'https://cloud.scorm.com/ScormEngineInterface/TCAPI/public/statements';
$statements = array(
array(
'actor' => array(
'name' => array('Example Name'),
'mbox' => array('mailto:example#example.com'),
'objectType' => 'Person',
),
'verb' => 'experienced',
'object' => array(
'objectType' => 'Activity',
'id'=> 'http://www.thincanapi.co.uk/wiki/index.php?Main_Page',
'definition' => array(
'name' => array('en-US'=>'TinCanAPI.co.uk-tincanapi.co.uk'),
'description' => array('en-US'=> 'TinCanAPI.co.uk-tincanapi.co.uk'),
),
),
),
);
return fopen_request_json($statements, $url);
}
list($resp, $meta) = make_request();
var_export($resp); // Returned headers, including errors, are in $meta
We've now released an open source library specifically for PHP, it uses a similar method as the accepted answer but rounds out the rest of the library as well. See:
http://rusticisoftware.github.io/TinCanPHP/
https://github.com/RusticiSoftware/TinCanPHP