Add logic to look for !!! in plugin updates - Fixes #785

This commit is contained in:
Samuel Georges 2015-07-11 08:29:23 +10:00
parent 8b147015ec
commit 6f4590404c
19 changed files with 670 additions and 41 deletions

View File

@ -0,0 +1,53 @@
.plugin-details-content {
padding: 0 0;
}
.plugin-details-content > *:first-child {
margin-top: 0;
}
.plugin-details-content h1 {
font-size: 28px;
}
.plugin-details-content h2 {
font-size: 24px;
}
.plugin-details-content h3 {
font-size: 20px;
}
.plugin-details-content h4 {
font-size: 17px;
}
.plugin-details-content h1,
.plugin-details-content h2 {
padding-bottom: 10px;
border-bottom: 1px solid #ccc;
}
.plugin-details-content ul,
.plugin-details-content ol {
padding-left: 20px;
}
.plugin-details-content pre {
display: block;
padding: 10px 10px 10px 20px;
font-size: 13px;
word-break: break-all;
word-wrap: break-word;
color: #fff;
background-color: #333;
margin-top: 10px;
margin-bottom: 20px;
margin-left: -20px;
margin-right: -20px;
}
.plugin-details-content pre code {
padding: 0;
font-size: inherit;
color: inherit;
white-space: pre-wrap;
background-color: transparent;
border-radius: 0;
}
.plugin-details-content ul pre,
.plugin-details-content ol pre {
margin-left: -40px;
padding-left: 40px;
}

View File

@ -196,7 +196,7 @@
display: block;
width: 24px;
height: 24px;
background-image: url(../../../../system/assets/ui/images/loader-transparent.svg);
background-image: url('../../../../system/assets/ui/images/loader-transparent.svg');
background-size: 24px 24px;
background-position: 50% 50%;
-webkit-animation: spin 1s linear infinite;

View File

@ -1,3 +1,6 @@
.important-update-label {
margin: 7px 0;
}
.control-updatelist {
border: 1px solid #ccc;
margin-bottom: 20px;
@ -8,11 +11,11 @@
.control-updatelist .update-item .item-header {
background-color: #f5f5f5;
border-bottom: 1px solid #ccc;
padding: 15px 10px;
padding: 0 10px;
}
.control-updatelist .update-item .item-header h5 {
margin: 0;
padding: 0;
padding: 15px 0;
text-transform: uppercase;
font-size: 13px;
}
@ -26,10 +29,13 @@
line-height: 13px;
margin-right: 5px;
}
.control-updatelist .update-item .item-header .important-update {
padding: 7px 0 0 0;
float: right;
}
.control-updatelist .update-item dl {
padding: 10px;
margin-bottom: 0;
font-size: 12px;
}
.control-updatelist .update-item dl:before,
.control-updatelist .update-item dl:after {
@ -43,12 +49,37 @@
.control-updatelist .update-item dl dd {
float: left;
padding: 5px 0;
line-height: 20px;
}
.control-updatelist .update-item dl dt.text-muted,
.control-updatelist .update-item dl dd.text-muted {
color: #999 !important;
}
.control-updatelist .update-item dl dt {
width: 15%;
clear: left;
font-size: 14px;
font-weight: 400;
color: #2b3e50;
}
.control-updatelist .update-item dl dd {
width: 85%;
font-size: 12px;
color: #455152;
}
.control-updatelist .update-item dl .important-update-label {
position: relative;
top: -1px;
background-color: #ab2a1c;
color: #fff;
display: inline-block;
padding: .2em .6em .3em;
font-size: 75%;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: .25em;
}
.control-updatelist .update-item:last-child {
border-bottom: none;
@ -56,6 +87,27 @@
.control-updatelist .update-item.item-danger .item-header {
background-color: #f2dede;
}
.control-updatelist .update-item.item-danger dl {
.control-updatelist .update-item.item-danger .item-header h5,
.control-updatelist .update-item.item-danger .item-header i,
.control-updatelist .update-item.item-danger .item-header {
color: #a94442;
}
.control-updatelist .update-item.item-success .item-header {
background-color: #dff0d8;
}
.control-updatelist .update-item.item-success .item-header h5,
.control-updatelist .update-item.item-success .item-header i,
.control-updatelist .update-item.item-success .item-header {
color: #3c763d;
}
.control-updatelist .update-item.item-muted {
border-bottom: none;
}
.control-updatelist .update-item.item-muted .item-header h5,
.control-updatelist .update-item.item-muted .item-header i,
.control-updatelist .update-item.item-muted .item-header {
color: rgba(0, 0, 0, 0.35);
}
.control-updatelist .update-item.item-muted dl {
display: none;
}

View File

@ -19,6 +19,55 @@
this.updateSteps = null
}
UpdateProcess.prototype.check = function() {
var $form = $('#updateForm'),
self = this
$form.request('onCheckForUpdates').done(function() {
self.evalConfirmedUpdates()
})
$form.on('change', '[data-important-update-select]', function() {
var $el = $(this),
selectedValue = $el.val(),
$updateItem = $el.closest('.update-item')
$updateItem.removeClass('item-danger item-muted item-success')
if (selectedValue == 'confirm') {
$updateItem.addClass('item-success')
}
else if (selectedValue == 'ignore' || selectedValue == 'skip') {
$updateItem.addClass('item-muted')
}
else {
$updateItem.addClass('item-danger')
}
self.evalConfirmedUpdates()
})
}
UpdateProcess.prototype.evalConfirmedUpdates = function() {
var $form = $('#updateForm'),
hasConfirmed = false
$('[data-important-update-select]', $form).each(function() {
if ($(this).val() == '') {
hasConfirmed = true
}
})
if (hasConfirmed) {
$('#updateListUpdateButton').prop('disabled', true)
$('#updateListImportantLabel').show()
}
else {
$('#updateListUpdateButton').prop('disabled', false)
$('#updateListImportantLabel').hide()
}
}
UpdateProcess.prototype.execute = function(steps) {
this.updateSteps = steps
this.runUpdate()

View File

@ -0,0 +1,51 @@
@import "../../../../backend/assets/less/core/boot.less";
@padding-standard: 20px;
@padding-container: 0;
.plugin-details-content {
padding: 0 @padding-container;
> *:first-child {
margin-top: 0;
}
h1 { font-size: @font-size-h1 - 8; }
h2 { font-size: @font-size-h2 - 6; }
h3 { font-size: @font-size-h3 - 4; }
h4 { font-size: @font-size-h4 - 1; }
h1, h2 { padding-bottom: 10px; border-bottom: 1px solid #ccc; }
ul, ol {
padding-left: @padding-standard;
}
pre {
display: block;
padding: 10px 10px 10px (@padding-standard + @padding-container);
font-size: 13px;
word-break: break-all;
word-wrap: break-word;
color: #fff;
background-color: #333;
margin-top: 10px;
margin-bottom: 20px;
margin-left: -(@padding-standard + @padding-container);
margin-right: -(@padding-standard + @padding-container);
code {
padding: 0;
font-size: inherit;
color: inherit;
white-space: pre-wrap;
background-color: transparent;
border-radius: 0;
}
}
ul pre,
ol pre {
margin-left: -((@padding-standard * 2) + @padding-container);
padding-left: ((@padding-standard * 2) + @padding-container);
}
}

View File

@ -1,5 +1,9 @@
@import "../../../../backend/assets/less/core/boot.less";
.important-update-label {
margin: 7px 0;
}
.control-updatelist {
border: 1px solid #ccc;
@ -12,11 +16,11 @@
.item-header {
background-color: #f5f5f5;
border-bottom: 1px solid #ccc;
padding: 15px 10px;
padding: 0 10px;
h5 {
margin: 0;
padding: 0;
padding: 15px 0;
text-transform: uppercase;
font-size: 13px;
@ -32,23 +36,53 @@
margin-right: 5px;
}
}
.important-update {
padding: 7px 0 0 0;
float: right;
}
}
dl {
padding: 10px;
margin-bottom: 0;
font-size: 12px;
.clearfix;
dt, dd {
float: left;
padding: 5px 0;
line-height: 20px;
&.text-muted {
color: #999 !important;
}
}
dt {
width: 15%;
clear: left;
font-size: 14px;
font-weight: 400;
color: #2b3e50;
}
dd {
width: 85%;
font-size: 12px;
color: #455152;
}
.important-update-label {
position: relative;
top: -1px;
background-color: #ab2a1c;
color: #fff;
display: inline-block;
padding: .2em .6em .3em;
font-size: 75%;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: .25em;
}
}
@ -59,11 +93,28 @@
&.item-danger {
.item-header {
background-color: @state-danger-bg;
}
dl {
color: @state-danger-text;
h5, i, & { color: @state-danger-text; }
}
}
&.item-success {
.item-header {
background-color: @state-success-bg;
h5, i, & { color: @state-success-text; }
}
}
&.item-muted {
border-bottom: none;
.item-header {
h5, i, & { color: rgba(0,0,0,.35); }
}
dl {
display: none;
}
}
}
}

View File

@ -209,6 +209,7 @@ class UpdateManager
$versions = $installed->lists('version', 'code');
$names = $installed->lists('name', 'code');
$icons = $installed->lists('icon', 'code');
$frozen = $installed->lists('is_frozen', 'code');
$build = Parameters::get('system::core.build');
$params = [
@ -241,7 +242,17 @@ class UpdateManager
$info['name'] = isset($names[$code]) ? $names[$code] : $code;
$info['old_version'] = isset($versions[$code]) ? $versions[$code] : false;
$info['icon'] = isset($icons[$code]) ? $icons[$code] : false;
$plugins[$code] = $info;
/*
* If plugin has updates frozen, do not add it to the list
* and discount an update unit.
*/
if (isset($frozen[$code]) && $frozen[$code]) {
$updateCount = max(0, --$updateCount);
}
else {
$plugins[$code] = $info;
}
}
$result['plugins'] = $plugins;

View File

@ -2,10 +2,12 @@
use Str;
use Lang;
use Html;
use File;
use Flash;
use Config;
use Backend;
use Markdown;
use Redirect;
use Response;
use BackendMenu;
@ -98,6 +100,71 @@ class Updates extends Controller
}
}
public function details($urlCode = null, $tab = null)
{
try {
$this->pageTitle = 'Plugin details';
$this->addCss('/modules/system/assets/css/updates/details.css', 'core');
$readmeFiles = ['README.md', 'readme.md'];
$upgradeFiles = ['UPGRADE.md', 'upgrade.md'];
$upgrades = $readme = $name = null;
$code = str_replace('-', '.', $urlCode);
/*
* Lookup the plugin
*/
$manager = PluginManager::instance();
$plugin = $manager->findByIdentifier($code);
$code = $manager->getIdentifier($plugin);
$path = $manager->getPluginPath($plugin);
if ($path && $plugin) {
$details = $plugin->pluginDetails();
$readme = $this->getPluginMarkdownFile($path, $readmeFiles);
$upgrades = $this->getPluginMarkdownFile($path, $upgradeFiles);
$pluginVersion = PluginVersion::whereCode($code)->first();
$this->vars['pluginName'] = array_get($details, 'name', 'system::lang.plugin.unnamed');
$this->vars['pluginVersion'] = $pluginVersion->version;
$this->vars['pluginAuthor'] = array_get($details, 'author');
$this->vars['pluginIcon'] = array_get($details, 'icon', 'icon-leaf');
$this->vars['pluginHomepage'] = array_get($details, 'homepage');
}
else {
throw new ApplicationException('Plugin not found');
}
$this->vars['activeTab'] = $tab ?: 'readme';
$this->vars['urlCode'] = $urlCode;
$this->vars['upgrades'] = $upgrades;
$this->vars['readme'] = $readme;
}
catch (Exception $ex) {
$this->handleError($ex);
}
}
protected function getPluginMarkdownFile($path, $filenames)
{
$contents = null;
foreach ($filenames as $file) {
if (!File::exists($path . '/'.$file)) continue;
$contents = File::get($path . '/'.$file);
/*
* Parse markdown, clean HTML, remove first H1 tag
*/
$contents = Markdown::parse($contents);
$contents = Html::clean($contents);
$contents = preg_replace('@<h1[^>]*?>.*?<\/h1>@si', '', $contents, 1);
}
return $contents;
}
/**
* {@inheritDoc}
*/
@ -119,6 +186,10 @@ class Updates extends Controller
return 'negative';
}
if ($record->is_frozen) {
return 'frozen';
}
return 'positive';
}
@ -193,8 +264,11 @@ class Updates extends Controller
$manager = UpdateManager::instance();
$result = $manager->requestUpdateList();
$result = $this->processImportantUpdates($result);
$this->vars['core'] = array_get($result, 'core', false);
$this->vars['hasUpdates'] = array_get($result, 'hasUpdates', false);
$this->vars['hasImportantUpdates'] = array_get($result, 'hasImportantUpdates', false);
$this->vars['pluginList'] = array_get($result, 'plugins', []);
$this->vars['themeList'] = array_get($result, 'themes', []);
}
@ -205,6 +279,31 @@ class Updates extends Controller
return ['#updateContainer' => $this->makePartial('update_list')];
}
/**
* Loops the update list and checks for actionable updates.
*/
protected function processImportantUpdates($result)
{
$hasImportantUpdates = false;
foreach (array_get($result, 'plugins', []) as $code => $plugin) {
$isImportant = false;
foreach (array_get($plugin, 'updates', []) as $version => $description) {
if (strpos($description, '!!!') === false) continue;
$isImportant = $hasImportantUpdates = true;
$detailsUrl = Backend::url('system/updates/details/'.strtolower(str_replace('.', '-', $code)).'/upgrades');
$description = str_replace('!!!', '', $description);
$result['plugins'][$code]['updates'][$version] = [$description, $detailsUrl];
}
$result['plugins'][$code]['isImportant'] = $isImportant ? '1' : '0';
}
$result['hasImportantUpdates'] = $hasImportantUpdates;
return $result;
}
/**
* Contacts the update server for a list of necessary updates.
*/
@ -258,20 +357,69 @@ class Updates extends Controller
public function onApplyUpdates()
{
try {
/*
* Process core
*/
$coreHash = post('hash');
$coreBuild = post('build');
$core = [$coreHash, $coreBuild];
$plugins = post('plugins', []);
if (!is_array($plugins)) {
/*
* Process plugins
*/
$plugins = post('plugins');
if (is_array($plugins)) {
$pluginCodes = [];
foreach ($plugins as $code => $hash) {
$pluginCodes[] = $this->decodeCode($code);
}
$plugins = array_combine($pluginCodes, $plugins);
}
else {
$plugins = [];
}
$themes = post('themes', []);
if (!is_array($themes)) {
/*
* Process themes
*/
$themes = post('themes');
if (is_array($themes)) {
$themeCodes = [];
foreach ($themes as $code => $hash) {
$themeCodes[] = $this->decodeCode($code);
}
$themes = array_combine($themeCodes, $themes);
}
else {
$themes = [];
}
/*
* Process important update actions
*/
$pluginActions = (array) post('plugin_actions');
foreach ($plugins as $code => $hash) {
$_code = $this->encodeCode($code);
if (!array_key_exists($_code, $pluginActions)) continue;
$pluginAction = $pluginActions[$_code];
if (!$pluginAction) {
throw new ApplicationException('Please select an action for plugin '. $code);
}
if ($pluginAction != 'confirm') {
unset($plugins[$code]);
}
if ($pluginAction == 'ignore') {
PluginVersion::whereCode($code)->update([
'is_frozen' => true
]);
}
}
/*
* Update steps
*/
@ -546,6 +694,7 @@ class Updates extends Controller
public function onDisablePlugins()
{
$disable = post('disable', false);
$freeze = post('freeze', false);
if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) {
$manager = PluginManager::instance();
@ -563,6 +712,7 @@ class Updates extends Controller
}
$object->is_disabled = $disable;
$object->is_frozen = $freeze;
$object->save();
}
@ -727,4 +877,23 @@ class Updates extends Controller
return array_values($popular);
}
//
// Helpers
//
/**
* Encode HTML safe product code.
*/
protected function encodeCode($code)
{
return str_replace('.', '_', $code);
}
/**
* Decode HTML safe product code.
*/
protected function decodeCode($code)
{
return str_replace('_', '.', $code);
}
}

View File

@ -0,0 +1,19 @@
<?php
$icon = null;
if ($record->is_disabled) {
$icon = 'eye-slash';
}
elseif ($record->disabledBySystem) {
$icon = 'exclamation';
}
elseif ($record->orphaned) {
$icon = 'question';
}
elseif ($record->is_frozen) {
$icon = 'lock';
}
?>
<span class="<?= $icon ? 'oc-icon-'.$icon : '' ?>">
<?= $value ?>
</span>

View File

@ -28,6 +28,21 @@
</div>
</div>
<div class="form-group">
<!-- Checkbox -->
<div class="checkbox custom-checkbox">
<input
type="checkbox"
name="freeze"
value="1"
id="pluginFreeze">
<label for="pluginFreeze">
<?= e(trans('system::lang.plugins.frozen_label')) ?>
</label>
<p class="help-block"><?= e(trans('system::lang.plugins.frozen_help')) ?></p>
</div>
</div>
</div>
<?php foreach ($checked as $id): ?>

View File

@ -1,4 +1,7 @@
<div data-control="toolbar">
<a href="<?= Backend::url('system/updates') ?>" class="btn btn-default oc-icon-chevron-left">
<?= e(trans('system::lang.updates.return_link')) ?>
</a>
<div class="btn-group">
<button
class="btn btn-default oc-icon-magic"

View File

@ -31,7 +31,7 @@
</div>
<script>
$('#checkUpdatesPopup').on('popupComplete', function(){
$('#updateForm').request('onCheckForUpdates')
$('#checkUpdatesPopup').on('popupComplete', function() {
$.oc.updateProcess.check()
})
</script>

View File

@ -9,21 +9,22 @@
</p>
<div class="control-updatelist">
<div class="control-scrollbar" style="height:300px" data-control="scrollbar">
<div class="control-scrollbar" style="height:400px" data-control="scrollbar">
<?php if ($core): ?>
<div class="update-item">
<div class="item-header">
<h5>
<i class="icon-cube"></i>
<?= e(trans('system::lang.system.name')) ?>
<?php if ($core['old_build']): ?>
<small><?= e(trans('system::lang.updates.core_build_old', ['build'=>$core['old_build']])) ?></small>
<?php endif ?>
</h5>
</div>
<dl>
<dt><?= e(trans('system::lang.updates.core_build_new', ['build'=>$core['build']])) ?></dt>
<dd><?= e(trans('system::lang.updates.core_build_new_help')) ?></dd>
<?php if ($core['old_build']): ?>
<dt class="text-muted"><?= e(trans('system::lang.updates.core_build_new', ['build'=>$core['old_build']])) ?></dt>
<dd class="text-muted"><?= e(trans('system::lang.updates.core_build')) ?></dd>
<?php endif ?>
</dl>
<input type="hidden" name="hash" value="<?= e($core['hash']) ?>" />
<input type="hidden" name="build" value="<?= e($core['build']) ?>" />
@ -36,7 +37,6 @@
<h5>
<i class="icon-picture-o"></i>
<?= e(array_get($theme, 'name', 'Unknown')) ?>
<small><?= e(trans('system::lang.updates.theme_label')) ?></small>
</h5>
</div>
<dl>
@ -44,32 +44,66 @@
<dd><?= e(trans('system::lang.updates.theme_new_install')) ?></dd>
</dl>
<input type="hidden" name="themes[<?= e($code) ?>]" value="<?= e($theme['hash']) ?>" />
<input type="hidden" name="themes[<?= e($this->encodeCode($code)) ?>]" value="<?= e($theme['hash']) ?>" />
</div>
<?php endforeach ?>
<?php foreach ($pluginList as $code => $plugin): ?>
<div class="update-item">
<div class="update-item <?= $plugin['isImportant'] ? 'item-danger' : '' ?>">
<div class="item-header">
<?php if ($plugin['isImportant']): ?>
<div class="important-update form-group form-group-sm">
<select
name="plugin_actions[<?= e($this->encodeCode($code)) ?>]"
class="form-control custom-select select-no-search"
data-important-update-select>
<option value="">-- Select action --</option>
<option value="confirm">Confirm update</option>
<option value="skip">Skip this plugin (once only)</option>
<option value="ignore">Skip this plugin (always)</option>
</select>
</div>
<?php endif ?>
<h5>
<i class="<?= e($plugin['icon'] ?: 'icon-puzzle-piece') ?>"></i>
<?= e($plugin['name']) ?>
<?php if ($plugin['old_version']): ?>
<small><?= e(trans('system::lang.updates.plugin_version_old', ['version'=>$plugin['old_version']])) ?></small>
<?php else: ?>
<small><?= e(trans('system::lang.updates.plugin_version_none')) ?></small>
<?php endif ?>
</h5>
</div>
<dl>
<?php foreach ($plugin['updates'] as $version => $description): ?>
<dt><?= e(trans('system::lang.updates.plugin_version_new', compact('version'))) ?></dt>
<dd><?= e($description) ?></dd>
<?php endforeach ?>
<?php if (!$plugin['old_version']): ?>
<dt>
<?= $plugin['version'] ?>
</dt>
<dd>
<?= e(trans('system::lang.updates.plugin_version_none')) ?>
</dd>
<?php else: ?>
<?php foreach (array_reverse($plugin['updates']) as $version => $description): ?>
<dt><?= e($version) ?></dt>
<?php if (is_array($description)): ?>
<dd>
<span class="important-update-label">Action required</span>
<?= e($description[0]) ?>
<a href="<?= $description[1] ?>" target="_blank">
View upgrade guide <i class="icon-external-link"></i>
</a>
</dd>
<?php else: ?>
<dd><?= e($description) ?></dd>
<?php endif ?>
<?php endforeach ?>
<dt class="text-muted">
<?= e($plugin['old_version']) ?>
</dt>
<dd class="text-muted">
Current version
</dd>
<?php endif ?>
</dl>
<input type="hidden" name="plugins[<?= e($code) ?>]" value="<?= e($plugin['hash']) ?>" />
<input type="hidden" name="plugins[<?= e($this->encodeCode($code)) ?>]" value="<?= e($plugin['hash']) ?>" />
</div>
<?php endforeach ?>
@ -79,8 +113,14 @@
</div>
<div class="modal-footer">
<?php if ($hasImportantUpdates): ?>
<p class="text-danger pull-left oc-icon-exclamation important-update-label" id="updateListImportantLabel">
Some updates need your attention.
</p>
<?php endif ?>
<button
type="button"
id="updateListUpdateButton"
class="btn btn-primary"
data-dismiss="popup"
data-control="popup"

View File

@ -2,11 +2,12 @@
# List Behavior Config
# ===================================
list: ~/modules/system/models/pluginversion/columns.yaml
list: ~/modules/system/models/pluginversion/columns_manage.yaml
modelClass: System\Models\PluginVersion
noRecordsMessage: backend::lang.list.no_records
showSetup: false
showCheckboxes: true
recordOnClick: $.oc.listToggleChecked(this)
toolbar:
buttons: list_manage_toolbar

View File

@ -0,0 +1,76 @@
<?php Block::put('breadcrumb') ?>
<ul>
<li><a href="<?= Backend::url('system/updates') ?>"><?= e(trans('system::lang.updates.menu_label')) ?></a></li>
<li><?= e(trans($this->pageTitle)) ?></li>
</ul>
<?php Block::endPut() ?>
<?php if (!$this->fatalError): ?>
<div class="scoreboard">
<div data-control="toolbar">
<div class="scoreboard-item title-value">
<h4>Plugin</h4>
<p class="oc-<?= $pluginIcon ?>"><?= e(trans($pluginName)) ?></p>
<?php if ($pluginHomepage): ?>
<p class="description">
<a href="<?= e($pluginHomepage) ?>">View homepage</a>
</p>
<?php endif ?>
</div>
<div class="scoreboard-item title-value">
<h4>Current version</h4>
<p><?= e($pluginVersion) ?></p>
</div>
<div class="scoreboard-item title-value">
<h4>Author</h4>
<p><?= e($pluginAuthor) ?></p>
</div>
</div>
</div>
<div class="control-tabs primary-tabs" data-control="tab">
<ul class="nav nav-tabs">
<li class="<?= $activeTab == 'readme' ? 'active' : '' ?>">
<a
href="#readme"
data-tab-url="<?= Backend::url('system/updates/details/'.$urlCode.'/readme') ?>">
Documentation
</a>
</li>
<li class="<?= $activeTab == 'upgrades' ? 'active' : '' ?>">
<a
href="#upgrades"
data-tab-url="<?= Backend::url('system/updates/details/'.$urlCode.'/upgrades') ?>">
Upgrade Guide
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane <?= $activeTab == 'readme' ? 'active' : '' ?>">
<div class="plugin-details-content">
<?php if ($readme): ?>
<?= $readme ?>
<?php else: ?>
<p>Plugin does not provide any documentation.</p>
<?php endif ?>
</div>
</div>
<div class="tab-pane <?= $activeTab == 'upgrades' ? 'active' : '' ?>">
<div class="plugin-details-content">
<?php if ($upgrades): ?>
<?= $upgrades ?>
<?php else: ?>
<p>Plugin does not provide any upgrade instructions.</p>
<?php endif ?>
</div>
</div>
</div>
</div>
<?php else: ?>
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
<p><a href="<?= Backend::url('system/updates') ?>" class="btn btn-default"><?= e(trans('system::lang.settings.return')) ?></a></p>
<?php endif ?>

View File

@ -0,0 +1,21 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DbSystemAddFrozenFlag extends Migration
{
public function up()
{
Schema::table('system_plugin_versions', function (Blueprint $table) {
$table->boolean('is_frozen')->default(0);
});
}
public function down()
{
Schema::table('system_plugin_versions', function (Blueprint $table) {
$table->dropColumn('is_frozen');
});
}
}

View File

@ -91,6 +91,8 @@ return [
'refresh' => 'Refresh',
'disabled_label' => 'Disabled',
'disabled_help' => 'Plugins that are disabled are ignored by the application.',
'frozen_label' => 'Freeze updates',
'frozen_help' => 'Plugins that are frozen will be ignored by the update process.',
'selected_amount' => 'Plugins selected: :amount',
'remove_confirm' => 'Are you sure you want to remove this plugin?',
'remove_success' => 'Successfully removed those plugins from the system.',
@ -195,6 +197,7 @@ return [
'check_label' => 'Check for updates',
'retry_label' => 'Try again',
'plugin_name' => 'Name',
'plugin_code' => 'Code',
'plugin_description' => 'Description',
'plugin_version' => 'Version',
'plugin_author' => 'Author',
@ -210,8 +213,8 @@ return [
'plugin_downloading' => 'Downloading plugin: :name',
'plugin_extracting' => 'Unpacking plugin: :name',
'plugin_version_none' => 'New plugin',
'plugin_version_old' => 'Current v:version',
'plugin_version_new' => 'v:version',
// 'plugin_version_old' => 'Current v:version',
// 'plugin_version_new' => 'v:version',
'theme_label' => 'Theme',
'theme_new_install' => 'New theme installation.',
'theme_downloading' => 'Downloading theme: :name',
@ -229,7 +232,8 @@ return [
'none' => [
'label' => 'No updates',
'help' => 'No new updates were found.'
]
],
'return_link' => 'Return to system updates'
],
'server' => [
'connect_error' => 'Error connecting to the server.',

View File

@ -49,7 +49,6 @@ class PluginVersion extends Model
$manager = PluginManager::instance();
$pluginObj = $manager->findByIdentifier($this->code);
if ($pluginObj) {
$pluginInfo = $pluginObj->pluginDetails();
foreach ($pluginInfo as $attribute => $info) {

View File

@ -0,0 +1,15 @@
# ===================================
# Column Definitions
# ===================================
columns:
code:
label: system::lang.updates.plugin_code
sortable: false
type: partial
path: column_code
version:
label: system::lang.updates.plugin_version
sortable: false