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 ## Black list protected files
## ##
RewriteRule ^themes/.*/(layouts|pages|partials)/.*.htm index.php [L,NC] RewriteRule ^themes/.*/(layouts|pages|partials)/.*.htm index.php [L,NC]
RewriteRule ^uploads/protected/.* index.php [L,NC]
RewriteRule ^bootstrap/.* index.php [L,NC] RewriteRule ^bootstrap/.* index.php [L,NC]
RewriteRule ^config/.* index.php [L,NC] RewriteRule ^config/.* index.php [L,NC]
RewriteRule ^vendor/.* index.php [L,NC] RewriteRule ^vendor/.* index.php [L,NC]
RewriteRule ^storage/cms/.* index.php [L,NC] RewriteRule ^storage/cms/.* index.php [L,NC]
RewriteRule ^storage/logs/.* 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/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 ## 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) * **Build 247** (2015-04-23)
- Added Media Manager feature. - 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 * Prepares the view data
*/ */
public function prepareVars() protected function prepareVars()
{ {
$this->vars['fileList'] = $this->getFileList(); $this->vars['fileList'] = $this->getFileList();
$this->vars['singleFile'] = array_get($this->vars['fileList'], 0, null); $this->vars['singleFile'] = array_get($this->vars['fileList'], 0, null);
@ -107,14 +107,19 @@ class FileUpload extends FormWidgetBase
protected function getFileList() 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) { $list->each(function($file){
$file->thumb = $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions); $this->decorateFileAttributes($file);
} });
return $list; return $list;
} }
@ -325,8 +330,7 @@ class FileUpload extends FormWidgetBase
$fileRelation->add($file, $this->sessionKey); $fileRelation->add($file, $this->sessionKey);
$file->thumb = $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions); $result = $this->decorateFileAttributes($file);
$result = $file;
} }
catch (Exception $ex) { catch (Exception $ex) {
@ -336,4 +340,20 @@ class FileUpload extends FormWidgetBase
header('Content-Type: application/json'); header('Content-Type: application/json');
die($result); 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 <a
href="{{path}}" href="{{path}}"
class="uploader-file-link oc-icon-paper-clip" class="uploader-file-link oc-icon-paperclip"
target="_blank"></a> target="_blank"></a>
</div> </div>
</div> </div>

View File

@ -28,6 +28,7 @@ use October\Rain\Exception\AjaxException;
use October\Rain\Exception\SystemException; use October\Rain\Exception\SystemException;
use October\Rain\Exception\ValidationException; use October\Rain\Exception\ValidationException;
use October\Rain\Exception\ApplicationException; use October\Rain\Exception\ApplicationException;
use October\Rain\Parse\Template as TextParser;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
/** /**
@ -894,8 +895,11 @@ class Controller
/** /**
* Renders a requested content file. * Renders a requested content file.
* The framework uses this method internally. * 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 * Extensibility
@ -915,6 +919,13 @@ class Controller
$fileContent = $content->parsedMarkup; $fileContent = $content->parsedMarkup;
/*
* Parse basic template variables
*/
if (!empty($parameters)) {
$fileContent = TextParser::parse($fileContent, $parameters);
}
/* /*
* Extensibility * Extensibility
*/ */

View File

@ -1,8 +1,8 @@
<?php namespace Cms\Twig; <?php namespace Cms\Twig;
use Twig_Node; use Twig_Node;
use Twig_Node_Expression;
use Twig_Compiler; use Twig_Compiler;
use Twig_NodeInterface;
/** /**
* Represents a content node * Represents a content node
@ -12,9 +12,9 @@ use Twig_Compiler;
*/ */
class ContentNode extends Twig_Node 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) 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 $compiler
->addDebugInfo($this)
->write("echo \$this->env->getExtension('CMS')->contentFunction(") ->write("echo \$this->env->getExtension('CMS')->contentFunction(")
->subcompile($this->getNode('name')) ->subcompile($this->getNode('nodes')->getNode(0))
->write(", \$context['__cms_content_params']")
->write(");\n") ->write(");\n")
; ;
$compiler->write("unset(\$context['__cms_content_params']);\n");
} }
} }

View File

@ -1,13 +1,19 @@
<?php namespace Cms\Twig; <?php namespace Cms\Twig;
use Twig_Node;
use Twig_Token; use Twig_Token;
use Twig_TokenParser; use Twig_TokenParser;
use Twig_Error_Syntax;
/** /**
* Parser for the {% content %} Twig tag. * Parser for the {% content %} Twig tag.
* *
* <pre> * <pre>
* {% content "intro.htm" %} * {% content "intro.htm" %}
*
* {% content "intro.md" name='John' %}
*
* {% content "intro/txt" name='John', year=2013 %}
* </pre> * </pre>
* *
* @package october\cms * @package october\cms
@ -24,10 +30,39 @@ class ContentTokenParser extends Twig_TokenParser
*/ */
public function parse(Twig_Token $token) public function parse(Twig_Token $token)
{ {
$lineno = $token->getLine();
$stream = $this->parser->getStream(); $stream = $this->parser->getStream();
$name = $this->parser->getExpressionParser()->parseExpression(); $name = $this->parser->getExpressionParser()->parseExpression();
$stream->expect(Twig_Token::BLOCK_END_TYPE); $paramNames = [];
return new ContentNode($name, $token->getLine(), $this->getTag()); $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. * 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. * @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]; $core = [null, null];
} }
if (!is_array($plugins)) {
$plugins = [];
}
if (!is_array($themes)) { if (!is_array($themes)) {
$themes = []; $themes = [];
} }
if (!is_array($plugins)) {
$plugins = [];
}
$updateSteps = []; $updateSteps = [];
list($coreHash, $coreBuild) = $core; list($coreHash, $coreBuild) = $core;
@ -318,19 +318,19 @@ class Updates extends Controller
]; ];
} }
foreach ($plugins as $name => $hash) { foreach ($themes as $name => $hash) {
$updateSteps[] = [ $updateSteps[] = [
'code' => 'downloadPlugin', 'code' => 'downloadTheme',
'label' => Lang::get('system::lang.updates.plugin_downloading', compact('name')), 'label' => Lang::get('system::lang.updates.theme_downloading', compact('name')),
'name' => $name, 'name' => $name,
'hash' => $hash 'hash' => $hash
]; ];
} }
foreach ($themes as $name => $hash) { foreach ($plugins as $name => $hash) {
$updateSteps[] = [ $updateSteps[] = [
'code' => 'downloadTheme', 'code' => 'downloadPlugin',
'label' => Lang::get('system::lang.updates.theme_downloading', compact('name')), 'label' => Lang::get('system::lang.updates.plugin_downloading', compact('name')),
'name' => $name, 'name' => $name,
'hash' => $hash 'hash' => $hash
]; ];
@ -348,19 +348,19 @@ class Updates extends Controller
]; ];
} }
foreach ($plugins as $name => $hash) { foreach ($themes as $name => $hash) {
$updateSteps[] = [ $updateSteps[] = [
'code' => 'extractPlugin', 'code' => 'extractTheme',
'label' => Lang::get('system::lang.updates.plugin_extracting', compact('name')), 'label' => Lang::get('system::lang.updates.theme_extracting', compact('name')),
'name' => $name, 'name' => $name,
'hash' => $hash 'hash' => $hash
]; ];
} }
foreach ($themes as $name => $hash) { foreach ($plugins as $name => $hash) {
$updateSteps[] = [ $updateSteps[] = [
'code' => 'extractTheme', 'code' => 'extractPlugin',
'label' => Lang::get('system::lang.updates.theme_extracting', compact('name')), 'label' => Lang::get('system::lang.updates.plugin_extracting', compact('name')),
'name' => $name, 'name' => $name,
'hash' => $hash 'hash' => $hash
]; ];
@ -600,6 +600,15 @@ class Updates extends Controller
$themes = [$name => $hash]; $themes = [$name => $hash];
$plugins = []; $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 * Update steps
*/ */