Skip to content

Commit

Permalink
Wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jaxwilko committed Jan 6, 2025
1 parent 09a7a88 commit d328417
Show file tree
Hide file tree
Showing 18 changed files with 21,625 additions and 213 deletions.
19 changes: 9 additions & 10 deletions modules/system/classes/UpdateManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,34 +56,33 @@ public function getMigrationTableName(): string
*/
public function check(bool $force = false): int
{
// Already know about updates, never retry.
if (($oldCount = Parameter::get('system::update.count')) > 0) {
return $oldCount;
}
$updateCount = Parameter::get('system::update.count');

// Retry period not passed, skipping.
if (
!$force
&& ($retryTimestamp = Parameter::get('system::update.retry'))
&& Carbon::createFromTimeStamp($retryTimestamp)->isFuture()
&& $updateCount > 0
) {
return $oldCount;
return $updateCount;
}

try {
$result = $this->requestUpdateList();
$newCount = array_get($result, 'update', 0);
$updateCount = array_reduce(array_values($this->availableUpdates()), function (int $carry, array $updates) {
return $carry + count($updates);
}, 0);
} catch (Exception $ex) {
$newCount = 0;
$updateCount = 0;
}

/*
* Remember update count, set retry date
*/
Parameter::set('system::update.count', $newCount);
Parameter::set('system::update.count', $updateCount);
Parameter::set('system::update.retry', Carbon::now()->addHours(24)->timestamp);

return $newCount;
return $updateCount;
}

public function availableUpdates(): array
Expand Down
58 changes: 58 additions & 0 deletions modules/system/classes/core/MarketPlaceApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use System\Traits\InteractsWithZip;
use Winter\Storm\Exception\ApplicationException;
use Winter\Storm\Network\Http as NetworkHttp;
use Winter\Storm\Packager\Composer;
use Winter\Storm\Support\Facades\Config;
use Winter\Storm\Support\Facades\File;
use Winter\Storm\Support\Facades\Http;
Expand All @@ -26,6 +27,7 @@ class MarketPlaceApi
use InteractsWithZip;

public const PRODUCT_CACHE_KEY = 'system-updates-product-details';
public const PRODUCT_FETCH_CACHE_KEY = 'marketplace.api.products';

public const REQUEST_PLUGIN_DETAIL = 'plugin/detail';
public const REQUEST_PLUGIN_CONTENT = 'plugin/content';
Expand Down Expand Up @@ -487,4 +489,60 @@ public function extractPlugin(string $name, string $hash): void

$this->extractArchive($filePath, plugins_path());
}


////////////////////////////////////////////////
/// @TODO: Move this to the marketplace api
////////////////////////////////////////////////

public function getProducts(): array
{
return Cache::remember(static::PRODUCT_FETCH_CACHE_KEY, Carbon::now()->addMinutes(5), function () {
return [
'plugins' => $this->getPackageType('winter-plugin'),
'themes' => $this->getPackageType('winter-theme'),
];
});
}

protected function getPackageType(string $type): array
{
$installed = Composer::getWinterPackageNames();

$packages = array_map(function (array $package) use ($installed) {
// This is scuffed, store the composer name as "package"
$package['package'] = $package['name'];
// Then guess a winter name from the package name (this will need to be handled by the market)
$package['name'] = implode('.', array_map(function (string $str) {
return str_replace(' ', '', ucwords(str_replace(['wn-', '-plugin', '-'], ['', '', ' '], $str)));
}, explode('/', $package['name'])));
// Check if the package is installed, should probably happen somewhere else
$package['installed'] = in_array($package['package'], $installed);
// Grab the package image, for now this will do
$package['icon'] = 'https://picsum.photos/200?a=' . md5($package['name']);
return $package;
}, Composer::listPackages($type));

usort($packages, function ($a, $b) {
return $b['favers'] <=> $a['favers'];
});

$popular = array_slice($packages, 0, 9);

usort($packages, function ($a, $b) {
return str_starts_with($b['package'], 'winter/');
});

$featured = array_slice($packages, 0, 9);

usort($packages, function ($a, $b) {
return $b['downloads'] <=> $a['downloads'];
});

return [
'popular' => $popular,
'featured' => $featured,
'all' => $packages
];
}
}
12 changes: 12 additions & 0 deletions modules/system/classes/extensions/PluginVersionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -661,4 +661,16 @@ public function getCurrentVersionNote($plugin): string
}));
return $lastHistory ? $lastHistory->detail : '';
}

/**
* Flushes local cache
*
* @return $this
*/
public function forgetCache(): static
{
// unset($this->databaseHistory, $this->databaseVersions, $this->fileVersions);

return $this;
}
}
5 changes: 3 additions & 2 deletions modules/system/classes/extensions/source/ExtensionSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class ExtensionSource

protected string $status = 'uninstalled';

/**
* @throws ApplicationException
*/
public function __construct(
public string $source,
public string $type,
Expand Down Expand Up @@ -266,7 +269,6 @@ protected function guessPathFromCode(string $code): ?string
}

/**
* @throws \ReflectionException
* @throws ApplicationException
*/
protected function guessCodeFromPath(string $path): ?string
Expand All @@ -284,7 +286,6 @@ protected function guessCodeFromPath(string $path): ?string
}

/**
* @throws \ReflectionException
* @throws ApplicationException
*/
protected function guessCodeFromPlugin(string $path): string
Expand Down
2 changes: 1 addition & 1 deletion modules/system/console/create/scaffold/plugin/plugin.stub
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace {{ plugin_namespace }};

use Backend;
use Backend\Models\UserRole;
use System\Classes\PluginBase;
use System\Classes\Extensions\PluginBase;

/**
* {{ name }} Plugin Information File
Expand Down
5 changes: 2 additions & 3 deletions modules/system/controllers/Updates.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function __construct()
{
parent::__construct();

$this->addJs('/modules/system/assets/js/updates/updates.js', 'core');
$this->addJs('/modules/system/controllers/updates/assets/dist/updates.js', 'core');
$this->addCss('/modules/system/assets/css/updates/updates.css', 'core');

BackendMenu::setContext('Winter.System', 'system', 'updates');
Expand Down Expand Up @@ -101,8 +101,7 @@ public function install($tab = null): ?HttpResponse
$this->addCss('/modules/system/assets/css/updates/install.css', 'core');

$this->vars['activeTab'] = $tab ?: 'plugins';
$this->vars['installedPlugins'] = $this->getInstalledPlugins();
$this->vars['installedThemes'] = $this->getInstalledThemes();

$this->vars['packageUploadWidget'] = $this->getPackageUploadWidget($tab === 'themes' ? 'theme' : 'plugin');
} catch (Exception $ex) {
$this->handleError($ex);
Expand Down
123 changes: 6 additions & 117 deletions modules/system/controllers/updates/_install_plugins.php
Original file line number Diff line number Diff line change
@@ -1,119 +1,8 @@
<div>

<!-- Search -->
<div class="row">
<div class="col-md-9">
<form
role="form"
id="installPluginsForm"
data-handler="onInstallPlugin"
onsubmit="$.wn.installProcess.searchSubmit(this); return false">
<div class="product-search">
<input
name="code"
id="pluginSearchInput"
class="product-search-input search-input-lg typeahead"
placeholder="<?= e(trans('system::lang.plugins.search')) ?>"
data-search-type="plugins"
/>
<i class="icon icon-search"></i>
<i class="icon loading" style="display: none"></i>
</div>
</form>
</div>
<div class="col-md-3">
<button
type="button"
data-control="popup"
data-handler="onLoadPluginUploader"
tabindex="-1"
class="btn btn-success wn-icon-file-arrow-up"
>
<?= e(trans('system::lang.plugins.upload')) ?>
</a>
</div>
</div>

<div class="row">

<div class="col-md-7">

<!-- Installed plugins -->
<div id="pluginList"
class="product-list-manager">

<h4 class="section-header">
<a href="<?= Backend::url('system/updates') ?>"><?= e(trans('system::lang.plugins.installed')) ?></a>
<small>(<span class="product-counter"><?= count($installedPlugins) ?></span>)</small>
</h4>

<?php if (!count($installedPlugins)): ?>
<div class="product-list-empty">
<p><?= e(trans('system::lang.plugins.no_plugins')) ?></p>
</div>
<?php else: ?>
<ul class="product-list plugin-list">
<?php foreach ($installedPlugins as $plugin): ?>

<li data-code="<?= $plugin['code'] ?>">
<div class="image">
<img src="<?= $plugin['image'] ?>" alt="">
</div>
<div class="details">
<h4><?= $plugin['name'] ?></h4>
<p><?= e(trans('system::lang.plugin.by_author', ['name' => $plugin['author']])) ?></p>
</div>
<button
type="button"
class="close"
aria-hidden="true"
data-request="onRemovePlugin"
data-request-data="code: '<?= $plugin['code'] ?>'"
data-request-confirm="<?= e(trans('system::lang.plugins.remove_confirm')) ?>"
data-stripe-load-indicator>
&times;
</button>
</li>

<?php endforeach ?>
</ul>
<?php endif ?>

</div>

</div>
<div class="col-md-5">

<!-- Recommended extras -->
<div class="suggested-products-container">
<h4 class="section-header"><?= e(trans('system::lang.plugins.recommended')) ?></h4>
<div class="scroll-panel">
<div
id="suggestedPlugins"
class="suggested-products suggested-plugins"
data-handler="onGetPopularPlugins"
data-view="plugin/suggestion"></div>
</div>
</div>

</div>

</div>

<div id="updates-app">
<plugin-updates
search-string="<?= e(trans('system::lang.plugins.search')) ?>"
upload-string="<?= e(trans('system::lang.plugins.upload')) ?>"
></plugin-updates>
</div>

<script type="text/template" data-partial="plugin/suggestion">
<div class="product">
<a
data-control="popup"
data-handler="onInstallPlugin"
data-request-data="code: '{{code}}'"
href="javascript:;">
<div class="image"><img src="{{image}}" alt=""></div>
<div class="details">
<h5 class="text-overflow">{{code}}</h5>
<p>{{description}}</p>
</div>
</a>
</div>
</script>

38 changes: 2 additions & 36 deletions modules/system/controllers/updates/_install_themes.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,41 +31,7 @@ class="product-list-manager"

<h4 class="section-header">
<a href="<?= Backend::url('cms/themes') ?>"><?= e(trans('system::lang.themes.installed')) ?></a>
<small>(<span class="product-counter"><?= count($installedThemes) ?></span>)</small>
</h4>

<?php if (!count($installedThemes)): ?>
<div class="product-list-empty">
<p><?= e(trans('system::lang.themes.no_themes')) ?></p>
</div>
<?php else: ?>
<ul class="product-list theme-list">
<?php foreach ($installedThemes as $theme): ?>

<li data-code="<?= $theme['code'] ?>">
<div class="image">
<img src="<?= $theme['image'] ?>" alt="">
</div>
<div class="details">
<h4><?= $theme['name'] ?></h4>
<p><?= e(trans('cms::lang.theme.by_author', ['name' => $theme['author']])) ?></p>
</div>
<button
type="button"
class="close"
aria-hidden="true"
data-request="onRemoveTheme"
data-request-data="code: '<?= $theme['dirName'] ?>'"
data-request-confirm="<?= e(trans('system::lang.themes.remove_confirm')) ?>"
data-stripe-load-indicator>
&times;
</button>
</li>

<?php endforeach ?>
</ul>
<?php endif ?>

</div>

</div>
Expand All @@ -78,7 +44,7 @@ class="close"
<div
id="suggestedThemes"
class="suggested-products suggested-themes"
data-handler="onGetPopularThemes"
data-handler="onGetMarketplaceThemes"
data-view="theme/suggestion"></div>
</div>
</div>
Expand All @@ -94,7 +60,7 @@ class="suggested-products suggested-themes"
<a
data-control="popup"
data-handler="onInstallTheme"
data-request-data="code: '{{code}}'"
data-request-data="code: '{{popular.code}}'"
href="javascript:;">
<div class="image"><img src="{{image}}" alt=""></div>
<div class="details">
Expand Down
Loading

0 comments on commit d328417

Please sign in to comment.