Merge branch 'develop' into media-manager

This commit is contained in:
Samuel Georges 2015-04-23 18:09:18 +10:00
commit 9173e3bb9a
20 changed files with 203 additions and 93 deletions

View File

@ -1,3 +1,7 @@
* **Build 246** (2015-04-21)
- Adds experimental command `october:mirror` for generating symbolic links in a public directory.
- Various performance improvements.
* **Build 239** (2015-04-06)
- Installing plugins has a new interface and themes can now be installed using the back-end.

View File

@ -6,6 +6,7 @@ use File;
use Config;
use Illuminate\Routing\Controller as ControllerBase;
use October\Rain\Router\Helper as RouterHelper;
use Closure;
/**
* The Backend controller class.
@ -16,6 +17,13 @@ use October\Rain\Router\Helper as RouterHelper;
*/
class BackendController extends ControllerBase
{
use \October\Rain\Extension\ExtendableTrait;
/**
* @var array Behaviors implemented by this controller.
*/
public $implement;
/**
* @var string Allows early access to page action.
*/
@ -26,6 +34,22 @@ class BackendController extends ControllerBase
*/
public static $params;
/**
* Instantiate a new BackendController instance.
*/
public function __construct()
{
$this->extendableConstruct();
}
/**
* Extend this object properties upon construction.
*/
public static function extend(Closure $callback)
{
self::extendableExtendCallback($callback);
}
/**
* Finds and serves the requested backend controller.
* If the controller cannot be found, returns the Cms page with the URL /404.

View File

@ -292,6 +292,10 @@ class FileUpload extends FormWidgetBase
}
try {
if (!Input::hasFile('file_data')) {
throw new ApplicationException('File missing from request');
}
$uploadedFile = Input::file('file_data');
$validationRules = ['max:'.File::getMaxFilesize()];

View File

@ -0,0 +1,49 @@
<?php namespace Cms\Classes;
use App;
use Illuminate\Routing\Controller as ControllerBase;
use Closure;
/**
* The CMS controller class.
* The base controller services front end pages.
*
* @package october\cms
* @author Alexey Bobkov, Samuel Georges
*/
class CmsController extends ControllerBase
{
use \October\Rain\Extension\ExtendableTrait;
/**
* @var array Behaviors implemented by this controller.
*/
public $implement;
/**
* Instantiate a new CmsController instance.
*/
public function __construct()
{
$this->extendableConstruct();
}
/**
* Extend this object properties upon construction.
*/
public static function extend(Closure $callback)
{
self::extendableExtendCallback($callback);
}
/**
* Finds and serves the request using the primary controller.
* @param string $url Specifies the requested page URL.
* If the parameter is omitted, the current URL used.
* @return string Returns the processed page content.
*/
public function run($url = null)
{
return App::make('Cms\Classes\Controller')->run($url);
}
}

View File

@ -3,7 +3,7 @@
use File;
use Twig_Error;
use Cms\Classes\SectionParser;
use ApplicationException;
use October\Rain\Exception\ApplicationException;
use Exception;
/**

View File

@ -664,7 +664,7 @@ class Controller
list($componentName, $handlerName) = explode('::', $handler);
$componentObj = $this->findComponentByName($componentName);
if ($componentObj && method_exists($componentObj, $handlerName)) {
if ($componentObj && $componentObj->methodExists($handlerName)) {
$this->componentContext = $componentObj;
$result = $componentObj->runAjaxHandler($handlerName);
return ($result) ?: true;
@ -1076,7 +1076,7 @@ class Controller
$url = substr($url, 1);
}
$routeAction = 'Cms\Classes\Controller@run';
$routeAction = 'Cms\Classes\CmsController@run';
$actionExists = Route::getRoutes()->getByAction($routeAction) !== null;
if ($actionExists) {
@ -1288,50 +1288,4 @@ class Controller
}
}
}
//
// Keep Laravel Happy
//
/**
* Get the middleware assigned to the controller.
*
* @return array
*/
public function getMiddleware()
{
return [];
}
/**
* Get the registered "before" filters.
*
* @return array
*/
public function getBeforeFilters()
{
return [];
}
/**
* Get the registered "after" filters.
*
* @return array
*/
public function getAfterFilters()
{
return [];
}
/**
* Execute an action on the controller.
*
* @param string $method
* @param array $parameters
* @return \Symfony\Component\HttpFoundation\Response
*/
public function callAction($method, $parameters)
{
return call_user_func_array(array($this, $method), $parameters);
}
}

View File

@ -308,12 +308,11 @@ class Theme
public function getPreviewImageUrl()
{
$previewPath = '/assets/images/theme-preview.png';
$path = $this->getPath().$previewPath;
if (!File::exists($path)) {
return URL::asset('modules/cms/assets/images/default-theme-preview.png');
if (File::exists($this->getPath().$previewPath)) {
return URL::asset('themes/'.$this->getDirName().$previewPath);
}
return URL::asset('themes/'.$this->getDirName().$previewPath);
return URL::asset('modules/cms/assets/images/default-theme-preview.png');
}
/**

View File

@ -8,5 +8,5 @@ App::before(function ($request) {
* The CMS module intercepts all URLs that were not
* handled by the back-end modules.
*/
Route::any('{slug}', 'Cms\Classes\Controller@run')->where('slug', '(.*)?');
Route::any('{slug}', 'Cms\Classes\CmsController@run')->where('slug', '(.*)?');
});

View File

@ -113,9 +113,12 @@ class DebugExtension extends Twig_Extension
elseif (is_array($var)) {
$caption = static::ARRAY_CAPTION;
}
else {
elseif (is_object($var)) {
$caption = [static::OBJECT_CAPTION, get_class($var)];
}
else {
$caption = [static::OBJECT_CAPTION, gettype($var)];
}
$result .= $this->dump($var, $caption);
}
@ -443,6 +446,9 @@ class DebugExtension extends Twig_Extension
$vars = [];
foreach ($info->getProperties() as $property) {
if ($property->isStatic()) {
continue; // Only non-static
}
if (!$property->isPublic()) {
continue; // Only public
}

View File

@ -345,16 +345,17 @@ class ServiceProvider extends ModuleServiceProvider
*/
protected function registerPrivilegedActions()
{
$requests = ['/combine', '@/system/updates', '@/backend/auth'];
$requests = ['/combine', '@/system/updates', '@/system/install', '@/backend/auth'];
$commands = ['october:up', 'october:update'];
/*
* Requests
*/
$path = RouterHelper::normalizeUrl(Request::path());
$backendUri = RouterHelper::normalizeUrl(Config::get('cms.backendUri'));
foreach ($requests as $request) {
if (substr($request, 0, 1) == '@') {
$request = Config::get('cms.backendUri') . substr($request, 1);
$request = $backendUri . substr($request, 1);
}
if (stripos($path, $request) === 0) {

View File

@ -7,6 +7,7 @@
margin: 0;
padding: 10px 0;
overflow: hidden;
/* clearfix */
}
.product-list li button {
position: absolute;
@ -38,9 +39,6 @@
padding-bottom: 10px;
overflow: hidden;
}
.plugin-list li:last-child {
border-bottom: none;
}
.plugin-list li .image {
float: left;
margin-right: 15px;
@ -61,6 +59,9 @@
color: #C03F31;
font-weight: 400;
}
.plugin-list li:last-child {
border-bottom: none;
}
.theme-list li {
float: left;
padding: 0;
@ -70,11 +71,6 @@
background: #fff;
position: relative;
border-radius: 3px;
}
.theme-list li:hover {
border-color: transparent;
}
.theme-list li {
-webkit-transition: border .2s linear;
-moz-transition: border .2s linear;
transition: border .2s linear;
@ -86,9 +82,6 @@
width: 210px;
height: 140px;
}
.theme-list li:hover .image {
opacity: 0;
}
.theme-list li .details {
position: absolute;
bottom: 0;
@ -97,9 +90,6 @@
padding: 10px;
overflow: hidden;
}
.theme-list li:hover .details {
opacity: 1;
}
.theme-list li h4 {
padding: 15px 0 0;
margin: 0;
@ -111,32 +101,34 @@
text-transform: uppercase;
font-size: 12px;
}
.theme-list li:hover {
border-color: transparent;
}
.theme-list li:hover .image {
opacity: 0;
}
.theme-list li:hover .details {
opacity: 1;
}
.suggested-products {
padding: 0;
}
.suggested-products .product {
padding: 0;
}
.suggested-products .image {
float: left;
position: relative;
}
.suggested-products .image img {
width: 40px;
height: 40px;
margin-top: 10px;
}
.suggested-themes .image img {
width: 60px;
height: 40px;
}
.suggested-products .image {
float: left;
position: relative;
}
.suggested-products .details {
margin-left: 50px;
padding: 10px 0;
}
.suggested-themes .details {
margin-left: 70px;
}
.suggested-products .details h5 {
margin: 0 0 3px;
font-size: 14px;
@ -175,6 +167,13 @@
.suggested-products a:hover .image img {
opacity: .5;
}
.suggested-themes .image img {
width: 60px;
height: 40px;
}
.suggested-themes .details {
margin-left: 70px;
}
/*!
* Typeahead
*/
@ -185,6 +184,24 @@
text-align: left;
padding-bottom: 15px;
}
.product-search > i.icon {
position: absolute;
top: 50%;
right: 15px;
font-size: 24px;
margin-top: -20px;
color: rgba(0, 0, 0, 0.35);
}
.product-search > i.icon.loading {
display: block;
width: 24px;
height: 24px;
background-image: url(../../../../backend/assets/images/loading-indicator-transparent.svg);
background-size: 24px 24px;
background-position: 50% 50%;
-webkit-animation: spin 1s linear infinite;
animation: spin 1s linear infinite;
}
.twitter-typeahead {
width: 100%;
}

View File

@ -53,7 +53,21 @@
var engine = new Bloodhound({
name: 'products',
method: 'POST',
remote: window.location.pathname + '?search=' + searchType + '&query=%QUERY',
remote: {
url: window.location.pathname + '?search=' + searchType + '&query=%QUERY',
ajax: {
beforeSend: function() {
$('.icon', $form).hide()
$('.icon.loading', $form).show()
$el.data('searchReady', false)
},
complete: function() {
$('.icon', $form).show()
$('.icon.loading', $form).hide()
$el.data('searchReady', true)
}
}
},
datumTokenizer: function(d) {
return Bloodhound.tokenizers.whitespace(d.val)
},
@ -92,6 +106,9 @@
$el = $(el),
$input = $el.find('.product-search-input.tt-input:first')
if (!$input.data('searchReady'))
return
$el.popup()
$input.typeahead('val', '')

View File

@ -205,6 +205,25 @@
margin: 0 auto 0 auto;
text-align: left;
padding-bottom: 15px;
> i.icon {
position: absolute;
top: 50%;
right: 15px;
font-size: 24px;
margin-top: -20px;
color: rgba(0,0,0,.35);
}
> i.icon.loading {
display: block;
width: 24px;
height: 24px;
background-image: url(../../../../backend/assets/images/loading-indicator-transparent.svg);
background-size: 24px 24px;
background-position: 50% 50%;
.animation(spin 1s linear infinite);
}
}
.twitter-typeahead {
width: 100%;
@ -247,11 +266,9 @@
.tt-suggestion {
font-size: 14px;
line-height: 18px;
+ {
.tt-suggestion {
font-size: 14px;
border-top: 1px solid #ccc;
}
+ .tt-suggestion {
font-size: 14px;
border-top: 1px solid #ccc;
}
}
.tt-suggestions {

View File

@ -210,6 +210,14 @@ class PluginManager
View::addNamespace($pluginNamespace, $viewsPath);
}
/*
* Add init, if available
*/
$initFile = $pluginPath . '/init.php';
if (!self::$noInit && File::exists($initFile)) {
require $initFile;
}
/*
* Add routes, if available
*/

View File

@ -14,6 +14,8 @@
placeholder="search plugins to install..."
data-search-type="plugins"
/>
<i class="icon icon-search"></i>
<i class="icon loading" style="display: none"></i>
</div>
</form>

View File

@ -14,6 +14,8 @@
placeholder="search themes to install..."
data-search-type="themes"
/>
<i class="icon icon-search"></i>
<i class="icon loading" style="display: none"></i>
</div>
</form>

View File

@ -23,7 +23,7 @@ return [
'ru' => 'Russian',
'se' => 'Swedish',
'sk' => 'Slovak (Slovakia)',
'tr' => 'Turkish'
'tr' => 'Turkish',
'nb-no' => 'Norwegian (Bokmål)'
],
'directory' => [

View File

@ -23,7 +23,7 @@ return [
'ru' => 'Russian',
'se' => 'Swedish',
'sk' => 'Slovak (Slovakia)',
'tr' => 'Turkish'
'tr' => 'Turkish',
'nb-no' => 'Norska (Bokmål)'
],
'directory' => [

View File

@ -2,6 +2,7 @@
use Str;
use Model;
use Exception;
/**
* Model for logging system errors and debug trace messages
@ -38,7 +39,10 @@ class EventLog extends Model
$record->details = (array) $details;
}
$record->save();
try {
$record->save();
}
catch (Exception $ex) {}
return $record;
}

View File

@ -50,7 +50,8 @@ trait ViewMaker
public function makePartial($partial, $params = [], $throwException = true)
{
if (!File::isPathSymbol($partial) && realpath($partial) === false) {
$partial = '_' . strtolower($partial) . '.htm';
$folder = strpos($partial, '/') !== false ? dirname($partial) . '/' : '';
$partial = $folder . '_' . strtolower(basename($partial)).'.htm';
}
$partialPath = $this->getViewPath($partial);
@ -136,7 +137,8 @@ trait ViewMaker
public function makeLayoutPartial($partial, $params = [])
{
if (!File::isLocalPath($partial) && !File::isPathSymbol($partial)) {
$partial = '_' . strtolower($partial);
$folder = strpos($partial, '/') !== false ? dirname($partial) . '/' : '';
$partial = $folder . '_' . strtolower(basename($partial));
}
return $this->makeLayout($partial, $params);