Merge branch 'develop' into ux
This commit is contained in:
commit
1085d20f8c
|
|
@ -1,7 +1,10 @@
|
|||
* **Build 125** (2014-07-xx)
|
||||
* **Build 125** (2014-07-24)
|
||||
- Theme support added.
|
||||
- Added new Theme picker to the backend via Settings > Front-end theme
|
||||
- New shorthand method for `$this->getClassExtension('Backend.Behaviors.FormController')` becomes `$this->asExtension('FormController')`.
|
||||
- Buttons inside a popup support new `data-popup-load-indicator` attribute.
|
||||
- Added a new config item to disable core updates completely (see config cms.disableCoreUpdates).
|
||||
- Added a unique alternate favicon to the Back-end area.
|
||||
|
||||
* **Build 124** (2014-07-17)
|
||||
- Improvements to Twig functions and filters.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,20 @@ return array(
|
|||
*/
|
||||
'disablePlugins' => [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Prevents application updates
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If using composer or git to download updates to the core files, set this
|
||||
| value to 'true' to prevent the update gateway from trying to download
|
||||
| these files again as part of the application update process. Plugins
|
||||
| and themes will still be downloaded.
|
||||
|
|
||||
*/
|
||||
|
||||
'disableCoreUpdates' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back-end URI prefix
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ return array(
|
|||
'mysql' => array(
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'port' => '',
|
||||
'database' => 'database',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
|
|
@ -66,6 +67,7 @@ return array(
|
|||
'pgsql' => array(
|
||||
'driver' => 'pgsql',
|
||||
'host' => 'localhost',
|
||||
'port' => '',
|
||||
'database' => 'database',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
|
|
@ -77,6 +79,7 @@ return array(
|
|||
'sqlsrv' => array(
|
||||
'driver' => 'sqlsrv',
|
||||
'host' => 'localhost',
|
||||
'port' => '',
|
||||
'database' => 'database',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
|
|
|
|||
|
|
@ -48,7 +48,10 @@ Log::useFiles(storage_path().'/logs/system.log');
|
|||
|
||||
App::error(function(Exception $exception, $code)
|
||||
{
|
||||
Log::error($exception);
|
||||
/*
|
||||
* October uses a custom error handler, see
|
||||
* System\Classes\ErrorHandler::handleException
|
||||
*/
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
|
|
@ -8,11 +8,14 @@
|
|||
* Supported data attributes:
|
||||
* - data-trigger-type, values: display, hide, enable, disable
|
||||
* - data-trigger: a CSS selector for elements that trigger the action (checkboxes)
|
||||
* - data-trigger-condition, values: checked (more conditions to add later) - determines the condition the elements
|
||||
* specified in the data-trigger should satisfy in order the condition to be considered as "true".
|
||||
* - data-trigger-condition, values:
|
||||
* - checked: determines the condition the elements specified in the data-trigger
|
||||
* should satisfy in order the condition to be considered as "true".
|
||||
* - value[somevalue]: determines if the value of data-trigger equals the specified value (somevalue)
|
||||
* the condition is considered "true".
|
||||
*
|
||||
* Example: <input type="button" class="btn disabled"
|
||||
* data-trigger-type="enable"
|
||||
* data-trigger-type="enable"
|
||||
* data-trigger="#cblist input[type=checkbox]"
|
||||
* data-trigger-condition="checked" ... >
|
||||
*
|
||||
|
|
@ -28,7 +31,7 @@
|
|||
var TriggerOn = function (element, options) {
|
||||
|
||||
var $el = this.$el = $(element);
|
||||
|
||||
|
||||
this.options = options || {};
|
||||
|
||||
if (this.options.triggerCondition === false)
|
||||
|
|
@ -40,10 +43,20 @@
|
|||
if (this.options.triggerType === false)
|
||||
throw new Error('Trigger type is not specified.')
|
||||
|
||||
if (this.options.triggerCondition == 'checked')
|
||||
this.triggerCondition = this.options.triggerCondition
|
||||
|
||||
if (this.options.triggerCondition.indexOf('value') == 0) {
|
||||
var match = this.options.triggerCondition.match(/[^[\]]+(?=])/g)
|
||||
if (match) {
|
||||
this.triggerConditionValue = match
|
||||
this.triggerCondition = 'value'
|
||||
}
|
||||
}
|
||||
|
||||
if (this.triggerCondition == 'checked' || this.triggerCondition == 'value')
|
||||
$(document).on('change', this.options.trigger, $.proxy(this.onConditionChanged, this))
|
||||
|
||||
var self = this;
|
||||
var self = this
|
||||
$el.on('oc.triggerOn.update', function(e){
|
||||
e.stopPropagation()
|
||||
self.onConditionChanged()
|
||||
|
|
@ -53,8 +66,12 @@
|
|||
}
|
||||
|
||||
TriggerOn.prototype.onConditionChanged = function() {
|
||||
if (this.options.triggerCondition == 'checked')
|
||||
this.updateTarget($(this.options.trigger + ':checked').length > 0);
|
||||
if (this.triggerCondition == 'checked') {
|
||||
this.updateTarget($(this.options.trigger + ':checked').length > 0)
|
||||
}
|
||||
else if (this.triggerCondition == 'value') {
|
||||
this.updateTarget($(this.options.trigger).val() == this.triggerConditionValue)
|
||||
}
|
||||
}
|
||||
|
||||
TriggerOn.prototype.updateTarget = function(status) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0">
|
||||
<link rel="icon" type="image/png" href="<?= URL::asset('modules/backend/assets/images/favicon.png') ?>" />
|
||||
<title data-title-template="<?= empty($this->pageTitleTemplate) ? '%s | October CMS' : e($this->pageTitleTemplate) ?>">
|
||||
<?= $this->pageTitle ?> | October CMS
|
||||
</title>
|
||||
|
|
|
|||
|
|
@ -400,7 +400,14 @@ class Controller extends BaseController
|
|||
return Response::make($responseContents, 406);
|
||||
}
|
||||
catch (Exception $ex) {
|
||||
return Response::make($ex->getMessage(), 500);
|
||||
/*
|
||||
* Display a "dumbed down" error if custom page is activated
|
||||
* otherwise display a more detailed error.
|
||||
*/
|
||||
if (Config::get('cms.customErrorPage', false))
|
||||
return Response::make($ex->getMessage(), 500);
|
||||
|
||||
return Response::make(sprintf('"%s" on line %s of %s', $ex->getMessage(), $ex->getLine(), $ex->getFile()), 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ class Theme
|
|||
|
||||
$result = [];
|
||||
foreach ($it as $fileinfo) {
|
||||
if ($fileinfo->isDot() || (substr($fileinfo->getFilename(), 0, 1) == '.'))
|
||||
if (!$fileinfo->isDir() || $fileinfo->isDot())
|
||||
continue;
|
||||
|
||||
$theme = new static;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@
|
|||
.control-updatelist h5:first-of-type {
|
||||
border-top: none;
|
||||
}
|
||||
.control-updatelist h5 i {
|
||||
margin-right: 7px;
|
||||
color: #405261;
|
||||
}
|
||||
.control-updatelist h5 small {
|
||||
text-transform: none;
|
||||
float: right;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@
|
|||
border-top: none;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 7px;
|
||||
color: @color-text-title;
|
||||
}
|
||||
|
||||
small {
|
||||
text-transform: none;
|
||||
float: right;
|
||||
|
|
|
|||
|
|
@ -206,6 +206,16 @@ class UpdateManager
|
|||
}
|
||||
$result['plugins'] = $plugins;
|
||||
|
||||
/*
|
||||
* Strip out themes that have been installed before
|
||||
*/
|
||||
$themes = [];
|
||||
foreach (array_get($result, 'themes', []) as $code => $info) {
|
||||
if (!$this->isThemeInstalled($code))
|
||||
$themes[$code] = $info;
|
||||
}
|
||||
$result['themes'] = $themes;
|
||||
|
||||
Parameters::set('system::update.count', array_get($result, 'update', 0));
|
||||
|
||||
return $result;
|
||||
|
|
@ -433,6 +443,58 @@ class UpdateManager
|
|||
@unlink($filePath);
|
||||
}
|
||||
|
||||
//
|
||||
// Themes
|
||||
//
|
||||
|
||||
/**
|
||||
* Downloads a theme from the update server.
|
||||
* @param string $name Theme name.
|
||||
* @param string $hash Expected file hash.
|
||||
* @return self
|
||||
*/
|
||||
public function downloadTheme($name, $hash)
|
||||
{
|
||||
$fileCode = $name . $hash;
|
||||
$this->requestServerFile('theme/get', $fileCode, $hash, ['name' => $name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a theme after it has been downloaded.
|
||||
*/
|
||||
public function extractTheme($name, $hash)
|
||||
{
|
||||
$fileCode = $name . $hash;
|
||||
$filePath = $this->getFilePath($fileCode);
|
||||
|
||||
if (!Zip::extract($filePath, $this->baseDirectory . '/themes/'))
|
||||
throw new ApplicationException(Lang::get('system::lang.zip.extract_failed', ['file' => $filePath]));
|
||||
|
||||
$this->setThemeInstalled($name);
|
||||
@unlink($filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a theme has ever been installed before.
|
||||
* @param string $name Theme code
|
||||
* @return boolean
|
||||
*/
|
||||
public function isThemeInstalled($name)
|
||||
{
|
||||
return array_key_exists($name, Parameters::get('system::theme.history', []));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags a theme as being installed, so it is not downloaded twice.
|
||||
* @param string $name Theme code
|
||||
*/
|
||||
public function setThemeInstalled($name)
|
||||
{
|
||||
$history = Parameters::get('system::theme.history', []);
|
||||
$history[$name] = Carbon::now()->timestamp;
|
||||
Parameters::set('system::theme.history', $history);
|
||||
}
|
||||
|
||||
//
|
||||
// Notes
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php namespace System\Console;
|
||||
|
||||
use Str;
|
||||
use Config;
|
||||
use Illuminate\Console\Command;
|
||||
use System\Classes\UpdateManager;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
|
@ -35,9 +36,29 @@ class OctoberUpdate extends Command
|
|||
$this->output->writeln('<info>Updating October...</info>');
|
||||
$manager = UpdateManager::instance()->resetNotes();
|
||||
$forceUpdate = $this->option('force');
|
||||
$pluginsOnly = $this->option('plugins');
|
||||
$coreOnly = $this->option('core');
|
||||
|
||||
/*
|
||||
* Check for disabilities
|
||||
*/
|
||||
$disableCore = $disablePlugins = $disableThemes = false;
|
||||
|
||||
if ($this->option('plugins')) {
|
||||
$disableCore = true;
|
||||
$disableThemes = true;
|
||||
}
|
||||
|
||||
if ($this->option('core')) {
|
||||
$disablePlugins = true;
|
||||
$disableThemes = true;
|
||||
}
|
||||
|
||||
if (Config::get('cms.disableCoreUpdates', false)) {
|
||||
$disableCore = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform update
|
||||
*/
|
||||
$updateList = $manager->requestUpdateList($forceUpdate);
|
||||
$updates = (int)array_get($updateList, 'update', 0);
|
||||
|
||||
|
|
@ -49,7 +70,7 @@ class OctoberUpdate extends Command
|
|||
$this->output->writeln(sprintf('<info>Found %s new %s!</info>', $updates, Str::plural('update', $updates)));
|
||||
}
|
||||
|
||||
$coreHash = $pluginsOnly ? null : array_get($updateList, 'core.hash');
|
||||
$coreHash = $disableCore ? null : array_get($updateList, 'core.hash');
|
||||
$coreBuild = array_get($updateList, 'core.build');
|
||||
|
||||
if ($coreHash) {
|
||||
|
|
@ -57,7 +78,7 @@ class OctoberUpdate extends Command
|
|||
$manager->downloadCore($coreHash);
|
||||
}
|
||||
|
||||
$plugins = $coreOnly ? [] : array_get($updateList, 'plugins');
|
||||
$plugins = $disablePlugins ? [] : array_get($updateList, 'plugins');
|
||||
foreach ($plugins as $code => $plugin) {
|
||||
$pluginName = array_get($plugin, 'name');
|
||||
$pluginHash = array_get($plugin, 'hash');
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use Str;
|
|||
use Lang;
|
||||
use File;
|
||||
use Flash;
|
||||
use Config;
|
||||
use Backend;
|
||||
use Redirect;
|
||||
use BackendMenu;
|
||||
|
|
@ -31,6 +32,11 @@ class Updates extends Controller
|
|||
|
||||
public $listConfig = ['list' => 'config_list.yaml', 'manage' => 'config_manage_list.yaml'];
|
||||
|
||||
/**
|
||||
* @var boolean If set to true, core updates will not be downloaded or extracted.
|
||||
*/
|
||||
protected $disableCoreUpdates = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
|
@ -38,6 +44,8 @@ class Updates extends Controller
|
|||
$this->addCss('/modules/system/assets/css/updates.css', 'core');
|
||||
|
||||
BackendMenu::setContext('October.System', 'system', 'updates');
|
||||
|
||||
$this->disableCoreUpdates = Config::get('cms.disableCoreUpdates', false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -98,10 +106,12 @@ class Updates extends Controller
|
|||
|
||||
switch ($stepCode) {
|
||||
case 'downloadCore':
|
||||
if ($this->disableCoreUpdates) return;
|
||||
$manager->downloadCore(post('hash'));
|
||||
break;
|
||||
|
||||
case 'extractCore':
|
||||
if ($this->disableCoreUpdates) return;
|
||||
$manager->extractCore(post('hash'), post('build'));
|
||||
break;
|
||||
|
||||
|
|
@ -109,10 +119,18 @@ class Updates extends Controller
|
|||
$manager->downloadPlugin(post('name'), post('hash'));
|
||||
break;
|
||||
|
||||
case 'downloadTheme':
|
||||
$manager->downloadTheme(post('name'), post('hash'));
|
||||
break;
|
||||
|
||||
case 'extractPlugin':
|
||||
$manager->extractPlugin(post('name'), post('hash'));
|
||||
break;
|
||||
|
||||
case 'extractTheme':
|
||||
$manager->extractTheme(post('name'), post('hash'));
|
||||
break;
|
||||
|
||||
case 'completeUpdate':
|
||||
$manager->update();
|
||||
Flash::success(Lang::get('system::lang.updates.update_success'));
|
||||
|
|
@ -148,7 +166,8 @@ class Updates extends Controller
|
|||
|
||||
$this->vars['core'] = array_get($result, 'core', false);
|
||||
$this->vars['hasUpdates'] = array_get($result, 'update', false);
|
||||
$this->vars['updateList'] = array_get($result, 'plugins', []);
|
||||
$this->vars['pluginList'] = array_get($result, 'plugins', []);
|
||||
$this->vars['themeList'] = array_get($result, 'themes', []);
|
||||
}
|
||||
catch (Exception $ex) {
|
||||
$this->handleError($ex);
|
||||
|
|
@ -176,10 +195,16 @@ class Updates extends Controller
|
|||
$plugins[$code] = array_get($plugin, 'hash', null);
|
||||
}
|
||||
|
||||
$themes = [];
|
||||
$themeList = array_get($result, 'themes', []);
|
||||
foreach ($themeList as $code => $theme) {
|
||||
$themes[$code] = array_get($theme, 'hash', null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update steps
|
||||
*/
|
||||
$updateSteps = $this->buildUpdateSteps($core, $plugins);
|
||||
$updateSteps = $this->buildUpdateSteps($core, $plugins, $themes);
|
||||
|
||||
/*
|
||||
* Finish up
|
||||
|
|
@ -204,18 +229,20 @@ class Updates extends Controller
|
|||
public function onApplyUpdates()
|
||||
{
|
||||
try {
|
||||
$plugins = post('plugins', []);
|
||||
if (!is_array($plugins))
|
||||
$plugins = [];
|
||||
|
||||
$coreHash = post('hash');
|
||||
$coreBuild = post('build');
|
||||
$core = [$coreHash, $coreBuild];
|
||||
|
||||
$plugins = post('plugins', []);
|
||||
if (!is_array($plugins)) $plugins = [];
|
||||
|
||||
$themes = post('themes', []);
|
||||
if (!is_array($themes)) $themes = [];
|
||||
|
||||
/*
|
||||
* Update steps
|
||||
*/
|
||||
$updateSteps = $this->buildUpdateSteps($core, $plugins);
|
||||
$updateSteps = $this->buildUpdateSteps($core, $plugins, $themes);
|
||||
|
||||
/*
|
||||
* Finish up
|
||||
|
|
@ -234,13 +261,16 @@ class Updates extends Controller
|
|||
return $this->makePartial('execute');
|
||||
}
|
||||
|
||||
private function buildUpdateSteps($core, $plugins)
|
||||
private function buildUpdateSteps($core, $plugins, $themes)
|
||||
{
|
||||
if (!is_array($core))
|
||||
$core = [null, null];
|
||||
|
||||
if (!is_array($plugins))
|
||||
$plugins = [];
|
||||
|
||||
if (!is_array($core))
|
||||
$core = [null, null];
|
||||
if (!is_array($themes))
|
||||
$themes = [];
|
||||
|
||||
$updateSteps = [];
|
||||
list($coreHash, $coreBuild) = $core;
|
||||
|
|
@ -265,6 +295,15 @@ class Updates extends Controller
|
|||
];
|
||||
}
|
||||
|
||||
foreach ($themes as $name => $hash) {
|
||||
$updateSteps[] = [
|
||||
'code' => 'downloadTheme',
|
||||
'label' => Lang::get('system::lang.updates.theme_downloading', compact('name')),
|
||||
'name' => $name,
|
||||
'hash' => $hash
|
||||
];
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract
|
||||
*/
|
||||
|
|
@ -286,6 +325,15 @@ class Updates extends Controller
|
|||
];
|
||||
}
|
||||
|
||||
foreach ($themes as $name => $hash) {
|
||||
$updateSteps[] = [
|
||||
'code' => 'extractTheme',
|
||||
'label' => Lang::get('system::lang.updates.theme_extracting', compact('name')),
|
||||
'name' => $name,
|
||||
'hash' => $hash
|
||||
];
|
||||
}
|
||||
|
||||
return $updateSteps;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
|
||||
<?php if ($core): ?>
|
||||
<h5>
|
||||
<i class="icon-cube"></i>
|
||||
<?= e(trans('system::lang.system.name')) ?>
|
||||
<?php if ($core['old_build']): ?>
|
||||
<?= e(trans('system::lang.updates.core_build_old', ['build'=>$core['old_build']])) ?>
|
||||
<small><?= e(trans('system::lang.updates.core_build_old', ['build'=>$core['old_build']])) ?></small>
|
||||
<?php endif ?>
|
||||
</h5>
|
||||
<dl>
|
||||
|
|
@ -26,8 +27,23 @@
|
|||
<input type="hidden" name="build" value="<?= e($core['build']) ?>" />
|
||||
<?php endif ?>
|
||||
|
||||
<?php foreach ($updateList as $code => $plugin): ?>
|
||||
<?php foreach ($themeList as $code => $theme): ?>
|
||||
<h5>
|
||||
<i class="icon-picture-o"></i>
|
||||
<?= e(array_get($theme, 'name', 'Unknown')) ?>
|
||||
<small><?= e(trans('system::lang.updates.theme_label')) ?></small>
|
||||
</h5>
|
||||
<dl>
|
||||
<dt><?= e(array_get($theme, 'version', 'v1.0.0')) ?></dt>
|
||||
<dd><?= e(trans('system::lang.updates.theme_new_install')) ?></dd>
|
||||
</dl>
|
||||
|
||||
<input type="hidden" name="themes[<?= e($code) ?>]" value="<?= e($theme['hash']) ?>" />
|
||||
<?php endforeach ?>
|
||||
|
||||
<?php foreach ($pluginList as $code => $plugin): ?>
|
||||
<h5>
|
||||
<i class="icon-puzzle-piece"></i>
|
||||
<?= e($plugin['name']) ?>
|
||||
|
||||
<?php if ($plugin['old_version']): ?>
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ return [
|
|||
'plugin_version_none' => 'New plugin',
|
||||
'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',
|
||||
'theme_extracting' => 'Unpacking theme: :name',
|
||||
'update_label' => 'Update software',
|
||||
'update_completing' => 'Finishing update process',
|
||||
'update_loading' => 'Loading available updates...',
|
||||
|
|
|
|||
Loading…
Reference in New Issue