Last active
October 8, 2022 15:58
-
-
Save alexandreelise/f03db3117dd47d865f66c34dc6b6adcd to your computer and use it in GitHub Desktop.
Create an article in Joomla from streamed csv with raw php using Joomla! 4.x Web Services Api
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
/* | |
YOUR ATTENTION PLEASE. THE NEW PLACE FOR THIS CODE IS : https://github.com/alexandreelise/j4x-api-examples | |
*/ | |
/** | |
* | |
* @author Alexandre ELISÉ <[email protected]> | |
* @copyright (c) 2009 - present. Alexandre ELISÉ. All rights reserved. | |
* @license GPL-2.0-and-later GNU General Public License v2.0 or later | |
* @link https://alexandree.io | |
*/ | |
// Public url of the sample csv used in this example (CHANGE WITH YOUR OWN CSV URL IF YOU WISH) | |
$csvUrl = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vTO8DC8xzEEyP754B0kBu1sa2P9Rn3I8OLmq_RJYHwOwTlY8OGvpjp1yvaE84Imj0HYQeJcNKT2TOFR/pub?gid=168068017&single=true&output=csv'; | |
// Your Joomla! 4.x website base url | |
$baseUrl = 'https://example.org'; | |
$basePath = 'api/index.php/v1'; | |
$endpoint = sprintf('%s/%s/%s', $baseUrl, $basePath, 'content/articles'); | |
$timeout = 10; | |
// Your Joomla! 4.x Api Token (DO NOT STORE IT IN YOUR REPO USE A VAULT OR A PASSWORD MANAGER) | |
$token = ''; | |
// PHP Generator to efficiently read the csv file | |
$generator = function (string $url, array $keys = []): Generator { | |
if (empty($url)) | |
{ | |
yield new RuntimeException('Url MUST NOT be empty', 422); | |
} | |
$defaultKeys = [ | |
'title', | |
'alias', | |
'catid', | |
'articletext', | |
'language', | |
'metadesc', | |
'metakey', | |
'state', | |
'featured', | |
]; | |
$mergedKeys = array_unique(array_merge($defaultKeys, $keys)); | |
$resource = fopen($url, 'r'); | |
if ($resource === false) | |
{ | |
yield new RuntimeException('Could not read csv file', 500); | |
} | |
try | |
{ | |
//NON-BLOCKING I/O (Does not wait before processing next line.) | |
stream_set_blocking($resource, false); | |
do | |
{ | |
$currentLine = stream_get_line( | |
$resource, | |
0, | |
"\r\n" | |
); | |
if (empty($currentLine)) | |
{ | |
yield new RuntimeException('Current line MUST NOT be empty', 422); | |
} | |
$extractedContent = str_getcsv($currentLine); | |
array_shift($extractedContent); | |
if ($mergedKeys != $extractedContent) | |
{ | |
$encodedContent = json_encode(array_combine($mergedKeys, $extractedContent)); | |
yield $encodedContent; | |
} | |
yield new RuntimeException('Current line seem to be invalid', 422); | |
} while (!feof($resource)); | |
} finally | |
{ | |
fclose($resource); | |
} | |
}; | |
// Read CSV in a PHP Generator using streams in non-blocking I/O mode | |
$streamCsv = $generator($csvUrl); | |
// Process data returned by the PHP Generator | |
$process = function ($endpoint, $dataString, $headers, $timeout, $transport) { | |
curl_setopt_array($transport, [ | |
CURLOPT_URL => $endpoint, | |
CURLOPT_RETURNTRANSFER => true, | |
CURLOPT_ENCODING => 'utf-8', | |
CURLOPT_MAXREDIRS => 10, | |
CURLOPT_TIMEOUT => $timeout, | |
CURLOPT_FOLLOWLOCATION => true, | |
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2TLS, | |
CURLOPT_CUSTOMREQUEST => 'POST', | |
CURLOPT_POSTFIELDS => $dataString, | |
CURLOPT_HTTPHEADER => $headers, | |
] | |
); | |
return curl_exec($transport); | |
}; | |
foreach ($streamCsv as $dataString) | |
{ | |
if (!is_string($dataString)) | |
{ | |
continue; | |
} | |
$curl = curl_init(); | |
try | |
{ | |
// HTTP request headers | |
$headers = [ | |
'Accept: application/vnd.api+json', | |
'Content-Type: application/json', | |
'Content-Length: ' . mb_strlen($dataString), | |
sprintf('X-Joomla-Token: %s', trim($token)), | |
]; | |
$output = $process($endpoint, $dataString, $headers, $timeout, $curl); | |
// Continue even on partial failure | |
if ($output === false || array_key_exists('errors', json_decode($output, true))) | |
{ | |
continue; | |
} | |
} | |
catch (Throwable $e) | |
{ | |
echo $e->getMessage() . PHP_EOL; | |
continue; | |
} finally | |
{ | |
curl_close($curl); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment