2018-08-19 11:39:14 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
|
|
use Exception;
|
2019-08-13 22:44:32 +08:00
|
|
|
use App\Services\Plugin;
|
2019-02-27 23:44:50 +08:00
|
|
|
use Illuminate\Support\Arr;
|
2018-08-19 11:39:14 +08:00
|
|
|
use Illuminate\Http\Request;
|
|
|
|
use App\Services\PluginManager;
|
2019-03-02 22:58:37 +08:00
|
|
|
use Composer\Semver\Comparator;
|
2019-04-05 17:23:27 +08:00
|
|
|
use App\Services\PackageManager;
|
2018-08-19 11:39:14 +08:00
|
|
|
|
|
|
|
class MarketController extends Controller
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Guzzle HTTP client.
|
|
|
|
*
|
|
|
|
* @var \GuzzleHttp\Client
|
|
|
|
*/
|
|
|
|
protected $guzzle;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cache for plugins registry.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $registryCache;
|
|
|
|
|
|
|
|
public function __construct(\GuzzleHttp\Client $guzzle)
|
|
|
|
{
|
|
|
|
$this->guzzle = $guzzle;
|
|
|
|
}
|
|
|
|
|
2019-08-13 22:44:32 +08:00
|
|
|
public function marketData(PluginManager $manager)
|
2018-08-19 11:39:14 +08:00
|
|
|
{
|
2019-08-13 22:44:32 +08:00
|
|
|
$plugins = collect($this->getAllAvailablePlugins())->map(function ($item) use ($manager) {
|
|
|
|
$plugin = $manager->get($item['name']);
|
2018-08-19 11:39:14 +08:00
|
|
|
|
|
|
|
if ($plugin) {
|
|
|
|
$item['enabled'] = $plugin->isEnabled();
|
|
|
|
$item['installed'] = $plugin->version;
|
|
|
|
$item['update_available'] = Comparator::greaterThan($item['version'], $item['installed']);
|
|
|
|
} else {
|
|
|
|
$item['installed'] = false;
|
|
|
|
}
|
|
|
|
|
2019-02-27 23:44:50 +08:00
|
|
|
$requirements = Arr::get($item, 'require', []);
|
2018-08-19 11:39:14 +08:00
|
|
|
unset($item['require']);
|
|
|
|
|
|
|
|
$item['dependencies'] = [
|
2019-08-13 22:44:32 +08:00
|
|
|
'all' => $requirements,
|
|
|
|
'unsatisfied' => $manager->getUnsatisfied(new Plugin('', $item)),
|
2018-08-19 11:39:14 +08:00
|
|
|
];
|
|
|
|
|
|
|
|
return $item;
|
|
|
|
});
|
|
|
|
|
|
|
|
return $plugins;
|
|
|
|
}
|
|
|
|
|
2019-08-13 22:44:32 +08:00
|
|
|
public function checkUpdates(PluginManager $manager)
|
2018-08-19 11:39:14 +08:00
|
|
|
{
|
2019-08-13 22:44:32 +08:00
|
|
|
$pluginsHaveUpdate = collect($this->getAllAvailablePlugins())
|
|
|
|
->filter(function ($item) use ($manager) {
|
|
|
|
$plugin = $manager->get($item['name']);
|
2019-08-15 23:27:29 +08:00
|
|
|
|
2019-08-13 22:44:32 +08:00
|
|
|
return $plugin && Comparator::greaterThan($item['version'], $plugin->version);
|
|
|
|
});
|
2018-08-19 11:39:14 +08:00
|
|
|
|
|
|
|
return json([
|
|
|
|
'available' => $pluginsHaveUpdate->isNotEmpty(),
|
2019-03-02 22:58:37 +08:00
|
|
|
'plugins' => $pluginsHaveUpdate->values()->all(),
|
2018-08-19 11:39:14 +08:00
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2019-04-05 17:23:27 +08:00
|
|
|
public function download(Request $request, PluginManager $manager, PackageManager $package)
|
2018-08-19 11:39:14 +08:00
|
|
|
{
|
|
|
|
$name = $request->get('name');
|
|
|
|
$metadata = $this->getPluginMetadata($name);
|
|
|
|
|
|
|
|
if (! $metadata) {
|
|
|
|
return json(trans('admin.plugins.market.non-existent', ['plugin' => $name]), 1);
|
|
|
|
}
|
|
|
|
|
2019-12-09 23:30:49 +08:00
|
|
|
$fakePlugin = new Plugin('', $metadata);
|
|
|
|
$unsatisfied = $manager->getUnsatisfied($fakePlugin);
|
|
|
|
$conflicts = $manager->getConflicts($fakePlugin);
|
|
|
|
if ($unsatisfied->isNotEmpty() || $conflicts->isNotEmpty()) {
|
|
|
|
$reason = $manager->formatUnresolved($unsatisfied, $conflicts);
|
|
|
|
|
|
|
|
return json(trans('admin.plugins.market.unresolved'), 1, compact('reason'));
|
|
|
|
}
|
|
|
|
|
2018-08-19 11:39:14 +08:00
|
|
|
$url = $metadata['dist']['url'];
|
2019-02-27 23:44:50 +08:00
|
|
|
$filename = Arr::last(explode('/', $url));
|
2019-08-19 23:06:17 +08:00
|
|
|
$pluginsDir = $manager->getPluginsDirs()->first();
|
2019-04-20 15:17:42 +08:00
|
|
|
$path = storage_path("packages/$name".'_'.$metadata['version'].'.zip');
|
2018-08-19 11:39:14 +08:00
|
|
|
|
|
|
|
try {
|
2019-04-05 17:23:27 +08:00
|
|
|
$package->download($url, $path, $metadata['dist']['shasum'])->extract($pluginsDir);
|
2018-08-19 11:39:14 +08:00
|
|
|
} catch (Exception $e) {
|
2019-04-05 17:23:27 +08:00
|
|
|
return json($e->getMessage(), 1);
|
2018-08-19 11:39:14 +08:00
|
|
|
}
|
2019-04-19 19:36:36 +08:00
|
|
|
|
2018-08-19 11:39:14 +08:00
|
|
|
return json(trans('admin.plugins.market.install-success'), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getPluginMetadata($name)
|
|
|
|
{
|
2019-08-13 22:44:32 +08:00
|
|
|
return collect($this->getAllAvailablePlugins())->firstWhere('name', $name);
|
2018-08-19 11:39:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function getAllAvailablePlugins()
|
|
|
|
{
|
2019-04-05 17:48:36 +08:00
|
|
|
$registryVersion = 1;
|
2019-07-05 14:48:12 +08:00
|
|
|
if (app()->runningUnitTests() || ! $this->registryCache) {
|
2019-04-22 19:26:17 +08:00
|
|
|
$registries = collect(explode(',', config('plugins.registry')));
|
|
|
|
$this->registryCache = $registries->map(function ($registry) use ($registryVersion) {
|
|
|
|
try {
|
|
|
|
$pluginsJson = $this->guzzle->request(
|
|
|
|
'GET',
|
|
|
|
trim($registry),
|
2019-08-04 18:19:53 +08:00
|
|
|
['verify' => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()]
|
2019-04-22 19:26:17 +08:00
|
|
|
)->getBody();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
throw new Exception(trans('admin.plugins.market.connection-error', [
|
|
|
|
'error' => htmlentities($e->getMessage()),
|
|
|
|
]));
|
|
|
|
}
|
|
|
|
|
|
|
|
$registryData = json_decode($pluginsJson, true);
|
|
|
|
$received = Arr::get($registryData, 'version');
|
2019-05-03 10:34:50 +08:00
|
|
|
abort_if(
|
|
|
|
is_int($received) && $received != $registryVersion,
|
|
|
|
500,
|
|
|
|
"Only version $registryVersion of market registry is accepted."
|
|
|
|
);
|
2019-04-22 19:26:17 +08:00
|
|
|
|
|
|
|
return Arr::get($registryData, 'packages', []);
|
|
|
|
})->flatten(1);
|
2018-08-19 11:39:14 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:26:17 +08:00
|
|
|
return $this->registryCache;
|
2018-08-19 11:39:14 +08:00
|
|
|
}
|
|
|
|
}
|