Source of file Client.php
Size: 8,405 Bytes - Last Modified: 2020-03-05T10:42:44+00:00
/mnt/sshfs/cdn-01/home/users/stable/server.stable.cz/cdn/web/lib/stable-cz/cdn-client/src/Client/Client.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 | <?php namespace Stable\Cdn; /** * Stable.cz CDN client * * Basic usage examples: * * // construct * $client = new \Stable\Cdn\Client(YOUR_API_KEY); * * // create some local file * file_put_contents('localfile', date('Y-m-d')); * * // upload file * $client->upload('localfile', 'path/to/remotefile'); * * // verify file exists * $client->ls('path/to/remotefile'); * * // list files in directory * $client->ls('path/to'); * * // delete remote file * $client->delete('path/to/remotefile'); * * @author Evzen Eiba <evzen.eiba@stable.cz> * @copyright Stable.cz * */ class Client { /** * @var string URL given to contructor */ protected $url = 'https://cdn.stable.cz/'; /** * @var string API key given to constructor */ protected $apikey; /** * @var string Last curlcall curlinfo */ public $curlLastInfo = null; /** * @var string Last curlcall result */ public $curlLastResult = null; /** * @var int Maximum size of a upload batch */ public $chunkFileSize = 5 * 1024 * 1024; /** * @var array Request/response storage */ public $calls = []; /** * Constructor * @param $apikey Your CDN service api key acquired from Stable.cz * @param $url Endpoint url (http://domain/, rest is concatenated automatically * @return null */ public function __construct($apikey) { $this->apikey = $apikey; // $this->url = $url; } /** * API request call (via cURL) * @param (string) $namespace - API namespace, currently "files" namespace only * @param (string|null) $path - PATH for request, eg. path for a existing file) * @param (array) $params - call params, eg. metadata for uploaded file * @param (string) $method - HTTP method (GET|POST|DELETE) * @throws Exception - in case of wrong method * @return (stdClass) - decoded JSON according to API definition or null in case of system fault */ protected function call(string $namespace, string $path = null, string $method, array $params = []):? \stdClass { $url = rtrim($this->url, '/') . '/api/' . trim($namespace, '/') . '/' . ltrim($path, '/'); $params['auth'] = $this->apikey; $options = [ CURLOPT_URL => $url , CURLOPT_RETURNTRANSFER => true , CURLINFO_HEADER_OUT => true ]; $options[CURLOPT_CUSTOMREQUEST] = strtoupper($method); switch (strtoupper($method)) { case 'DELETE' : case 'GET' : $options[CURLOPT_URL] .= '?' . http_build_query($params); break; case 'POST' : $options[CURLOPT_POST] = true; $options[CURLOPT_POSTFIELDS] = json_encode($params); // $options[CURLOPT_HTTPHEADER] = [ 'Content-Type: application/json' ]; break; default: throw new \Exception(sprintf('Unknown method %s', $method)); break; } $ch = curl_init(); curl_setopt_array($ch, $options); $res = curl_exec($ch); $this->curlLastInfo = curl_getinfo($ch); $this->curlLastResult = $res; // var_dump($this->curlLastResult); $ret = null; if ($res) { $ret = json_decode($res); } $this->calls[] = [ 'url' => str_replace($this->apikey ,'YOUR_API_KEY', $options[CURLOPT_URL]) , 'method' => $options[CURLOPT_CUSTOMREQUEST] , 'data' => !empty($options[CURLOPT_POSTFIELDS]) ? str_replace($this->apikey ,'YOUR_API_KEY', json_encode($params, JSON_PRETTY_PRINT)) : null , 'response' => $ret ? str_replace($this->apikey ,'YOUR_API_KEY', json_encode($ret, JSON_PRETTY_PRINT)) : false ]; return $ret; } /** * Uploads a file to target * @param (string) $file - source file path * @param (string) $target - target file path * @param (callable) $callback - callback for upload progress * @return (stdClass) - decoded JSON according to API definition or null in case of system fault */ public function upload(string $file, string $target, callable $callback = null):? \stdClass { $filesize = filesize($file); if ($filesize > $this->chunkFileSize) { $i = 0; $progress = 0; $start = microtime(true); $parts = $filesize / $this->chunkFileSize; $f = fOpen($file, 'r'); if ($callback) { $callback((object) [ 'chunk' => -1 , 'progress' => $progress , 'total_filesize' => $filesize , 'chunkresult' => null]); } while ($chunk = fread($f, $this->chunkFileSize)) { $res = $this->call('files', null, 'POST', [ 'data' => [ 'filename' => $target , 'chunk' => $i , 'content' => base64_encode($chunk) ] ] ); $progress += strlen($chunk); $eta = ( (microtime(true) - $start) / ($i+1) * $parts ) - (microtime(true) - $start); $d1 = new \DateTime; $d1->setTimestamp(0); $d2 = new \DateTime; $d2->setTimestamp((int) $eta); $eta_formatted = $d2->diff($d1)->format('%H:%I:%S'); if ($callback) { $callback((object) [ 'chunk' => $i , 'progress' => $progress , 'total_filesize' => $filesize , 'eta' => $eta , 'eta_formatted' => $eta_formatted , 'chunkresult' => $res]); } $i++; } fClose($f); return $res; // return last result; } else { $res = $this->call('files', null, 'POST', [ 'data' => [ 'filename' => $target, 'content' => base64_encode(file_get_contents($file)) ] ] ); if ($callback) { $callback((object) [ 'chunk' => 0 , 'progress' => $filesize , 'total_filesize' => $filesize , 'eta' => 0 , 'eta_formatted' => 0 , 'chunkresult' => $res]); } return $res; } } /** * Delete an existing file * @param (string) $file - path to existing file * @return (stdClass) - decoded JSON according to API definition or null in case of system fault */ public function delete(string $file):? \stdClass { $res = $this->call('files', $file, 'DELETE'); return $res; } /** * List an existing file or directory - get a file info or a directory and its files * @param (string) $path - path to a file or directory * @return (stdClass) - decoded JSON according to API definition or null in case of system fault */ public function ls(string $path):? \stdClass { $res = $this->call('files', $path, 'GET'); return $res; } /** * Configure CDN (currently resizer sizes only) * @param (string) $what - configuration part ('sizes'); * @param (string) $action - one of get|add|delete action * @param $value - optional value * @return (stdClass) - decoded JSON according to API definition or null in case of system fault */ public function configure(string $what, string $action, $value = null):? \stdClass { switch(strtolower($action)) { case 'get' : return $this->call($what, $value, 'GET'); case 'add' : return $this->call($what, null, 'POST', [ 'data' => $value ]); case 'delete' : return $this->call($what, $value, 'DELETE'); } } } |