Merge branch 'develop' of github.com:octobercms/october into develop

This commit is contained in:
alekseybobkov 2015-04-25 14:33:47 -07:00
commit a4ab611228
10 changed files with 199 additions and 38 deletions

View File

@ -15,15 +15,14 @@
## Black list protected files
##
RewriteRule ^themes/.*/(layouts|pages|partials)/.*.htm index.php [L,NC]
RewriteRule ^uploads/protected/.* index.php [L,NC]
RewriteRule ^bootstrap/.* index.php [L,NC]
RewriteRule ^config/.* index.php [L,NC]
RewriteRule ^vendor/.* index.php [L,NC]
RewriteRule ^storage/cms/.* index.php [L,NC]
RewriteRule ^storage/logs/.* index.php [L,NC]
RewriteCond %{REQUEST_URI} !storage/temp/public
RewriteRule ^storage/temp/.* index.php [L,NC]
RewriteRule ^storage/framework/.* index.php [L,NC]
RewriteRule ^storage/temp/protected/.* index.php [L,NC]
RewriteRule ^storage/app/uploads/protected/.* index.php [L,NC]
##
## White listed folders and files

View File

@ -1,3 +1,7 @@
* **Build 24x** (2015-04-xx)
- Protected files can now be downloaded by administrators using the `fileupload` form widget.
- The `{% content %}` tag now supports passing parameters, parsed by a basic template engine (see Cms > Content block docs).
* **Build 247** (2015-04-23)
- Added Media Manager feature.

View File

@ -0,0 +1,67 @@
<?php namespace Backend\Controllers;
use App;
use Backend;
use System\Models\File as FileModel;
use Backend\Classes\Controller;
use ApplicationException;
use Exception;
/**
* Backend files controller
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*
*/
class Files extends Controller
{
public function get($code = null)
{
try {
if (!$code) {
throw new ApplicationException('Missing code');
}
$parts = explode('!', base64_decode($code));
if (count($parts) < 2) {
throw new ApplicationException('Invalid code');
}
list($id, $hash) = $parts;
if (!$file = FileModel::find((int) $id)) {
throw new ApplicationException('Unable to find file');
}
$verifyCode = self::getUniqueCode($file);
if ($code != $verifyCode) {
throw new ApplicationException('Invalid hash');
}
echo $file->output();
exit;
}
catch (Exception $ex) {}
/*
* Fall back on Cms controller
*/
return App::make('Cms\Classes\Controller')->setStatusCode(404)->run('/404');
}
public static function getDownloadUrl($file)
{
return Backend::url('backend/files/get/' . self::getUniqueCode($file));
}
public static function getUniqueCode($file)
{
if (!$file) {
return null;
}
$hash = md5($file->file_name . '!' . $file->disk_name);
return base64_encode($file->id . '!' . $hash);
}
}

View File

@ -94,7 +94,7 @@ class FileUpload extends FormWidgetBase
/**
* Prepares the view data
*/
public function prepareVars()
protected function prepareVars()
{
$this->vars['fileList'] = $this->getFileList();
$this->vars['singleFile'] = array_get($this->vars['fileList'], 0, null);
@ -107,14 +107,19 @@ class FileUpload extends FormWidgetBase
protected function getFileList()
{
$list = $this->getRelationObject()->withDeferred($this->sessionKey)->orderBy('sort_order')->get();
$list = $this
->getRelationObject()
->withDeferred($this->sessionKey)
->orderBy('sort_order')
->get()
;
/*
* Set the thumb for each file
* Decorate each file with thumb and custom download path
*/
foreach ($list as $file) {
$file->thumb = $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions);
}
$list->each(function($file){
$this->decorateFileAttributes($file);
});
return $list;
}
@ -325,8 +330,7 @@ class FileUpload extends FormWidgetBase
$fileRelation->add($file, $this->sessionKey);
$file->thumb = $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions);
$result = $file;
$result = $this->decorateFileAttributes($file);
}
catch (Exception $ex) {
@ -336,4 +340,20 @@ class FileUpload extends FormWidgetBase
header('Content-Type: application/json');
die($result);
}
/**
* Adds the bespoke thumb and path property used by this widget.
* @return System\Models\File
*/
protected function decorateFileAttributes($file)
{
$file->thumb = $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions);
// Internal download link
if (!$file->isImage() || !$file->isPublic()) {
$file->path = \Backend\Controllers\Files::getDownloadUrl($file);
}
return $file;
}
}

View File

@ -61,7 +61,7 @@
<a
href="{{path}}"
class="uploader-file-link oc-icon-paper-clip"
class="uploader-file-link oc-icon-paperclip"
target="_blank"></a>
</div>
</div>

View File

@ -28,6 +28,7 @@ use October\Rain\Exception\AjaxException;
use October\Rain\Exception\SystemException;
use October\Rain\Exception\ValidationException;
use October\Rain\Exception\ApplicationException;
use October\Rain\Parse\Template as TextParser;
use Illuminate\Http\RedirectResponse;
/**
@ -894,8 +895,11 @@ class Controller
/**
* Renders a requested content file.
* The framework uses this method internally.
* @param string $name The content view to load.
* @param array $parameters Parameter variables to pass to the view.
* @return string
*/
public function renderContent($name)
public function renderContent($name, $parameters = [])
{
/*
* Extensibility
@ -915,6 +919,13 @@ class Controller
$fileContent = $content->parsedMarkup;
/*
* Parse basic template variables
*/
if (!empty($parameters)) {
$fileContent = TextParser::parse($fileContent, $parameters);
}
/*
* Extensibility
*/

View File

@ -1,8 +1,8 @@
<?php namespace Cms\Twig;
use Twig_Node;
use Twig_Node_Expression;
use Twig_Compiler;
use Twig_NodeInterface;
/**
* Represents a content node
@ -12,9 +12,9 @@ use Twig_Compiler;
*/
class ContentNode extends Twig_Node
{
public function __construct(Twig_Node_Expression $name, $lineno, $tag = 'content')
public function __construct(Twig_NodeInterface $nodes, $paramNames, $lineno, $tag = 'content')
{
parent::__construct(['name' => $name], [], $lineno, $tag);
parent::__construct(['nodes' => $nodes], ['names' => $paramNames], $lineno, $tag);
}
/**
@ -24,11 +24,25 @@ class ContentNode extends Twig_Node
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$compiler->write("\$context['__cms_content_params'] = [];\n");
for ($i = 1; $i < count($this->getNode('nodes')); $i++) {
$compiler->write("\$context['__cms_content_params']['".$this->getAttribute('names')[$i-1]."'] = ");
$compiler->write('twig_escape_filter($this->env, ');
$compiler->subcompile($this->getNode('nodes')->getNode($i));
$compiler->write(")");
$compiler->write(";\n");
}
$compiler
->addDebugInfo($this)
->write("echo \$this->env->getExtension('CMS')->contentFunction(")
->subcompile($this->getNode('name'))
->subcompile($this->getNode('nodes')->getNode(0))
->write(", \$context['__cms_content_params']")
->write(");\n")
;
$compiler->write("unset(\$context['__cms_content_params']);\n");
}
}

View File

@ -1,13 +1,19 @@
<?php namespace Cms\Twig;
use Twig_Node;
use Twig_Token;
use Twig_TokenParser;
use Twig_Error_Syntax;
/**
* Parser for the {% content %} Twig tag.
*
* <pre>
* {% content "intro.htm" %}
*
* {% content "intro.md" name='John' %}
*
* {% content "intro/txt" name='John', year=2013 %}
* </pre>
*
* @package october\cms
@ -24,10 +30,39 @@ class ContentTokenParser extends Twig_TokenParser
*/
public function parse(Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$name = $this->parser->getExpressionParser()->parseExpression();
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new ContentNode($name, $token->getLine(), $this->getTag());
$paramNames = [];
$nodes = [$name];
$end = false;
while (!$end) {
$current = $stream->next();
switch ($current->getType()) {
case Twig_Token::NAME_TYPE:
$paramNames[] = $current->getValue();
$stream->expect(Twig_Token::OPERATOR_TYPE, '=');
$nodes[] = $this->parser->getExpressionParser()->parseExpression();
break;
case Twig_Token::BLOCK_END_TYPE:
$end = true;
break;
default:
throw new Twig_Error_Syntax(
sprintf('Invalid syntax in the content tag. Line %s', $lineno),
$stream->getCurrent()->getLine(),
$stream->getFilename()
);
break;
}
}
return new ContentNode(new Twig_Node($nodes), $paramNames, $token->getLine(), $this->getTag());
}
/**

View File

@ -118,11 +118,13 @@ class Extension extends Twig_Extension
/**
* Renders a content file.
* @param string $name Specifies the content block name.
* @param array $parameters A optional list of parameters to pass to the content.
* @return string Returns the file contents.
*/
public function contentFunction($name)
public function contentFunction($name, $parameters = [])
{
return $this->controller->renderContent($name);
return $this->controller->renderContent($name, $parameters);
}
/**

View File

@ -296,14 +296,14 @@ class Updates extends Controller
$core = [null, null];
}
if (!is_array($plugins)) {
$plugins = [];
}
if (!is_array($themes)) {
$themes = [];
}
if (!is_array($plugins)) {
$plugins = [];
}
$updateSteps = [];
list($coreHash, $coreBuild) = $core;
@ -318,19 +318,19 @@ class Updates extends Controller
];
}
foreach ($plugins as $name => $hash) {
foreach ($themes as $name => $hash) {
$updateSteps[] = [
'code' => 'downloadPlugin',
'label' => Lang::get('system::lang.updates.plugin_downloading', compact('name')),
'code' => 'downloadTheme',
'label' => Lang::get('system::lang.updates.theme_downloading', compact('name')),
'name' => $name,
'hash' => $hash
];
}
foreach ($themes as $name => $hash) {
foreach ($plugins as $name => $hash) {
$updateSteps[] = [
'code' => 'downloadTheme',
'label' => Lang::get('system::lang.updates.theme_downloading', compact('name')),
'code' => 'downloadPlugin',
'label' => Lang::get('system::lang.updates.plugin_downloading', compact('name')),
'name' => $name,
'hash' => $hash
];
@ -348,19 +348,19 @@ class Updates extends Controller
];
}
foreach ($plugins as $name => $hash) {
foreach ($themes as $name => $hash) {
$updateSteps[] = [
'code' => 'extractPlugin',
'label' => Lang::get('system::lang.updates.plugin_extracting', compact('name')),
'code' => 'extractTheme',
'label' => Lang::get('system::lang.updates.theme_extracting', compact('name')),
'name' => $name,
'hash' => $hash
];
}
foreach ($themes as $name => $hash) {
foreach ($plugins as $name => $hash) {
$updateSteps[] = [
'code' => 'extractTheme',
'label' => Lang::get('system::lang.updates.theme_extracting', compact('name')),
'code' => 'extractPlugin',
'label' => Lang::get('system::lang.updates.plugin_extracting', compact('name')),
'name' => $name,
'hash' => $hash
];
@ -600,6 +600,15 @@ class Updates extends Controller
$themes = [$name => $hash];
$plugins = [];
foreach ((array) array_get($result, 'require') as $plugin) {
if (
($name = array_get($plugin, 'code')) &&
($hash = array_get($plugin, 'hash'))
) {
$plugins[$name] = $hash;
}
}
/*
* Update steps
*/