mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT [file_link id=n] shortcode support for file links in HtmlEditorField
This commit is contained in:
parent
586ca7374f
commit
898c8f5497
@ -49,6 +49,8 @@ Object::useCustomClass('Datetime', 'SS_Datetime', true);
|
||||
*/
|
||||
define('MCE_ROOT', 'sapphire/thirdparty/tinymce/');
|
||||
|
||||
ShortcodeParser::get('default')->register('file_link', array('File', 'link_shortcode_handler'));
|
||||
|
||||
/**
|
||||
* The secret key that needs to be sent along with pings to /Email_BounceHandler
|
||||
*
|
||||
@ -81,4 +83,4 @@ SS_Cache::pick_backend('aggregatestore', 'aggregate', 1000);
|
||||
Deprecation::notification_version('3.0.0');
|
||||
|
||||
// TODO Remove once new ManifestBuilder with submodule support is in place
|
||||
require_once('admin/_config.php');
|
||||
require_once('admin/_config.php');
|
||||
|
@ -137,7 +137,44 @@ class File extends DataObject {
|
||||
* @var array
|
||||
*/
|
||||
protected static $cache_file_fields = null;
|
||||
|
||||
|
||||
/**
|
||||
* Replace "[file_link id=n]" shortcode with an anchor tag or link to the file.
|
||||
* @param $arguments array Arguments to the shortcode
|
||||
* @param $content string Content of the returned link (optional)
|
||||
* @param $parser object Specify a parser to parse the content (see {@link ShortCodeParser})
|
||||
* @return string anchor HTML tag if content argument given, otherwise file path link
|
||||
*/
|
||||
public static function link_shortcode_handler($arguments, $content = null, $parser = null) {
|
||||
if(!isset($arguments['id']) || !is_numeric($arguments['id'])) return;
|
||||
|
||||
if (
|
||||
!($record = DataObject::get_by_id('File', $arguments['id'])) // Get the file by ID.
|
||||
&& !($record = DataObject::get_one('ErrorPage', '"ErrorCode" = \'404\'')) // Link to 404 page directly.
|
||||
) {
|
||||
return; // There were no suitable matches at all.
|
||||
}
|
||||
|
||||
// build the HTML tag
|
||||
if($content) {
|
||||
// build some useful meta-data (file type and size) as data attributes
|
||||
$attrs = ' ';
|
||||
if($record instanceof File) {
|
||||
foreach(array(
|
||||
'class' => 'file',
|
||||
'data-type' => $record->getExtension(),
|
||||
'data-size' => $record->getSize()
|
||||
) as $name => $value) {
|
||||
$attrs .= sprintf('%s="%s" ', $name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return sprintf('<a href="%s"%s>%s</a>', $record->Link(), rtrim($attrs), $parser->parse($content));
|
||||
} else {
|
||||
return $record->Link();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a File object by the given filename.
|
||||
*
|
||||
@ -167,10 +204,10 @@ class File extends DataObject {
|
||||
return Director::baseURL() . $this->RelativeLink();
|
||||
}
|
||||
|
||||
function RelativeLink(){
|
||||
function RelativeLink() {
|
||||
return $this->Filename;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 3.0 Use getTreeTitle()
|
||||
*/
|
||||
|
@ -307,7 +307,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
||||
$siteTree,
|
||||
new TextField('external', _t('HtmlEditorField.URL', 'URL'), 'http://'),
|
||||
new EmailField('email', _t('HtmlEditorField.EMAIL', 'Email address')),
|
||||
new TreeDropdownField('file', _t('HtmlEditorField.FILE', 'File'), 'File', 'Filename', 'Title', true),
|
||||
new TreeDropdownField('file', _t('HtmlEditorField.FILE', 'File'), 'File', 'ID', 'Title', true),
|
||||
new TextField('Anchor', _t('HtmlEditorField.ANCHORVALUE', 'Anchor')),
|
||||
new TextField('Description', _t('HtmlEditorField.LINKDESCR', 'Link description')),
|
||||
new CheckboxField('TargetBlank', _t('HtmlEditorField.LINKOPENNEWWIN', 'Open link in a new window?')),
|
||||
@ -663,4 +663,4 @@ class HtmlEditorField_Image extends HtmlEditorField_File {
|
||||
return ($this->file) ? $this->file->CMSThumbnail() : sprintf('<img src="%s" />', $this->url);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
href = this.find(':input[name=file]').val();
|
||||
href = '[file_link id=' + this.find(':input[name=file]').val() + ']';
|
||||
target = '_blank';
|
||||
break;
|
||||
|
||||
@ -532,7 +532,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
email: RegExp.$1,
|
||||
Description: title
|
||||
};
|
||||
} else if(href.match(/^(assets\/.*)$/)) {
|
||||
} else if(href.match(/^(assets\/.*)$/) || href.match(/^\[file_link\s*(?:%20)?id=([0-9]+)\]?(#.*)?$/)) {
|
||||
return {
|
||||
LinkType: 'file',
|
||||
file: RegExp.$1,
|
||||
@ -565,7 +565,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
LinkType: 'internal'
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('form.htmleditorfield-linkform input[name=LinkType]').entwine({
|
||||
@ -967,4 +967,4 @@ function sapphiremce_cleanup(type, value) {
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,39 @@ class FileTest extends SapphireTest {
|
||||
static $fixture_file = 'FileTest.yml';
|
||||
|
||||
protected $extraDataObjects = array('FileTest_MyCustomFile');
|
||||
|
||||
|
||||
public function testLinkShortcodeHandler() {
|
||||
$testFile = $this->objFromFixture('File', 'asdf');
|
||||
$errorPage = $this->objFromFixture('ErrorPage', '404');
|
||||
|
||||
$parser = new ShortcodeParser();
|
||||
$parser->register('file_link', array('File', 'link_shortcode_handler'));
|
||||
|
||||
$fileShortcode = sprintf('[file_link id=%d]', $testFile->ID);
|
||||
$fileEnclosed = sprintf('[file_link id=%d]Example Content[/file_link]', $testFile->ID);
|
||||
|
||||
$fileShortcodeExpected = $testFile->Link();
|
||||
$fileEnclosedExpected = sprintf('<a href="%s" class="file" data-type="txt" data-size="977 KB">Example Content</a>', $testFile->Link());
|
||||
|
||||
$this->assertEquals($fileShortcodeExpected, $parser->parse($fileShortcode), 'Test that simple linking works.');
|
||||
$this->assertEquals($fileEnclosedExpected, $parser->parse($fileEnclosed), 'Test enclosed content is linked.');
|
||||
|
||||
$testFile->delete();
|
||||
|
||||
$fileShortcode = '[file_link id="-1"]';
|
||||
$fileEnclosed = '[file_link id="-1"]Example Content[/file_link]';
|
||||
|
||||
$fileShortcodeExpected = $errorPage->Link();
|
||||
$fileEnclosedExpected = sprintf('<a href="%s">Example Content</a>', $errorPage->Link());
|
||||
|
||||
$this->assertEquals($fileShortcodeExpected, $parser->parse($fileShortcode), 'Test link to 404 page if no suitable matches.');
|
||||
$this->assertEquals($fileEnclosedExpected, $parser->parse($fileEnclosed));
|
||||
|
||||
$this->assertEquals('', $parser->parse('[file_link]'), 'Test that invalid ID attributes are not parsed.');
|
||||
$this->assertEquals('', $parser->parse('[file_link id="text"]'));
|
||||
$this->assertEquals('', $parser->parse('[file_link]Example Content[/file_link]'));
|
||||
}
|
||||
|
||||
function testCreateWithFilenameWithSubfolder() {
|
||||
// Note: We can't use fixtures/setUp() for this, as we want to create the db record manually.
|
||||
// Creating the folder is necessary to avoid having "Filename" overwritten by setName()/setRelativePath(),
|
||||
@ -373,4 +405,4 @@ class FileTest extends SapphireTest {
|
||||
|
||||
class FileTest_MyCustomFile extends File implements TestOnly {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -27,4 +27,8 @@ File:
|
||||
file1-folder1:
|
||||
Filename: assets/FileTest-folder1/File1.txt
|
||||
Name: File1.txt
|
||||
ParentID: =>Folder.folder1
|
||||
ParentID: =>Folder.folder1
|
||||
ErrorPage:
|
||||
404:
|
||||
Title: Page not Found
|
||||
ErrorCode: 404
|
||||
|
Loading…
Reference in New Issue
Block a user