Skip to content

Instantly share code, notes, and snippets.

@jrobinsonc
Last active January 12, 2019 23:16
Show Gist options
  • Save jrobinsonc/cc700d08f90e7261db9c63f50cb87f3a to your computer and use it in GitHub Desktop.
Save jrobinsonc/cc700d08f90e7261db9c63f50cb87f3a to your computer and use it in GitHub Desktop.
Class to download packages from a SatisPress installation.

SatisPress Downloader

Usage

$downloader = new \Jrdev\SatisPressDownloader('https://domain.tld/satispress/packages.json', [
    // 'auth' => ['user', 'pass'], // Basic auth, if required.
    // 'baseDir' => __DIR__, // Base directory to create the sub-directories `cache` and `packages`.
    // 'versions' => 1, // How many versions of each package should be downloaded: 1 = the latest, 2 = the two latest versions, etc.
]);

$downloader->run();
<?php
namespace Jrdev;
use ErrorException;
use stdClass;
class SatisPressDownloader
{
protected $config;
public function __construct(string $satisJson, array $extraConf = [])
{
$this->config = new stdClass;
$this->config->satisJson = $satisJson;
$this->config->baseDir = $extraConf['baseDir'] ?? (sys_get_temp_dir() . '/'
. substr(strrchr(static::class, '\\'), 1));
$this->config->cacheDir = $this->config->baseDir . '/cache';
$this->config->packagesDir = $this->config->baseDir . '/packages';
// Create required directories if they don't exist.
foreach ([
$this->config->cacheDir,
$this->config->packagesDir
] as $dirPath) {
if (!is_dir($dirPath) && !mkdir($dirPath, 0755, true)) {
throw new ErrorException('Directory cannot be created: '. basename($dirPath));
}
}
// How many versions of each package should be stored.
$this->config->versions = $extraConf['versions'] ?? 1;
// If authentication is needed to download the packages.
$this->config->auth = null;
if (isset($extraConf['auth']) && !empty($extraConf['auth'])) {
$this->config->auth = new stdClass;
$this->config->auth->type = 'basic';
$this->config->auth->creds = $extraConf['auth'];
}
}
protected function copyFile(string $src, string $dest)
{
$srcHandle = fopen($src, 'r');
if (false === $srcHandle) {
throw new ErrorException('File cannot be downloaded: ' . $src);
}
$destDir = dirname($dest);
if (!is_dir($destDir) && !mkdir($destDir, 0755, true)) {
throw new ErrorException('Directory cannot be created: '. basename($destDir));
}
$destHandle = fopen($dest, 'w');
if (false === $destHandle) {
fclose($srcHandle);
throw new ErrorException('File cannot be created: ' . $dest);
}
while (!feof($srcHandle)) {
$chunk = fread($srcHandle, 4096);
fwrite($destHandle, $chunk);
}
fclose($destHandle);
fclose($srcHandle);
}
protected function fetchPackages(): string
{
$cacheFile = $this->config->cacheDir . '/packages.json';
if (!file_exists($cacheFile)) {
$this->copyFile($this->config->satisJson, $cacheFile);
}
return file_get_contents($cacheFile);
}
protected function parsePackage(stdClass $packageData): array
{
$output = [];
$versionCount = 0;
foreach ($packageData as $packageVersion) {
// For now, we only accept ZIPs.
if ($packageVersion->dist->type !== 'zip') {
throw new ErrorException('Unknown file type: '. $packageVersion->dist->type
. ' for package ' . $packageVersion->name);
}
$package = new stdClass;
$package->name = str_replace('satispress/', '', $packageVersion->name);
$package->name .= "-{$packageVersion->version}";
$package->name .= ".{$packageVersion->dist->type}";
$package->downloadUrl = $packageVersion->dist->url;
if (!is_null($this->config->auth)) {
$authStr = implode(':', $this->config->auth->creds);
$package->downloadUrl = str_replace('://', '://' . $authStr . '@', $package->downloadUrl);
}
$package->type = $packageVersion->type;
$output[] = $package;
$versionCount++;
if ($this->config->versions === $versionCount) {
break;
}
}
return $output;
}
protected function downloadPackage(array $package)
{
foreach ($package as $packageVersion) {
$filePath = "{$this->config->packagesDir}/{$packageVersion->type}/{$packageVersion->name}";
if (file_exists($filePath)) {
return;
}
$this->copyFile($packageVersion->downloadUrl, $filePath);
}
}
protected function parseJson(string $jsonData): \Generator
{
$parsedJson = json_decode($jsonData);
if (null === $parsedJson) {
throw new ErrorException('JSON data cannot be parsed.');
}
foreach ($parsedJson->packages as $package) {
yield $this->parsePackage($package);
}
}
public function run()
{
// Run.
$jsonData = $this->fetchPackages();
foreach ($this->parseJson($jsonData) as $package) {
$this->downloadPackage($package);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment