ENHANCEMENT [file_link id=n] shortcode support for file links in HtmlEditorField

This commit is contained in:
Sean Harvey 2012-03-01 21:13:42 +13:00
parent 586ca7374f
commit 898c8f5497
6 changed files with 88 additions and 13 deletions

View File

@ -49,6 +49,8 @@ Object::useCustomClass('Datetime', 'SS_Datetime', true);
*/ */
define('MCE_ROOT', 'sapphire/thirdparty/tinymce/'); 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 * The secret key that needs to be sent along with pings to /Email_BounceHandler
* *

View File

@ -138,6 +138,43 @@ class File extends DataObject {
*/ */
protected static $cache_file_fields = null; 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. * Find a File object by the given filename.
* *
@ -167,7 +204,7 @@ class File extends DataObject {
return Director::baseURL() . $this->RelativeLink(); return Director::baseURL() . $this->RelativeLink();
} }
function RelativeLink(){ function RelativeLink() {
return $this->Filename; return $this->Filename;
} }

View File

@ -307,7 +307,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
$siteTree, $siteTree,
new TextField('external', _t('HtmlEditorField.URL', 'URL'), 'http://'), new TextField('external', _t('HtmlEditorField.URL', 'URL'), 'http://'),
new EmailField('email', _t('HtmlEditorField.EMAIL', 'Email address')), 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('Anchor', _t('HtmlEditorField.ANCHORVALUE', 'Anchor')),
new TextField('Description', _t('HtmlEditorField.LINKDESCR', 'Link description')), new TextField('Description', _t('HtmlEditorField.LINKDESCR', 'Link description')),
new CheckboxField('TargetBlank', _t('HtmlEditorField.LINKOPENNEWWIN', 'Open link in a new window?')), new CheckboxField('TargetBlank', _t('HtmlEditorField.LINKOPENNEWWIN', 'Open link in a new window?')),

View File

@ -379,7 +379,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
break; break;
case 'file': case 'file':
href = this.find(':input[name=file]').val(); href = '[file_link id=' + this.find(':input[name=file]').val() + ']';
target = '_blank'; target = '_blank';
break; break;
@ -532,7 +532,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
email: RegExp.$1, email: RegExp.$1,
Description: title Description: title
}; };
} else if(href.match(/^(assets\/.*)$/)) { } else if(href.match(/^(assets\/.*)$/) || href.match(/^\[file_link\s*(?:%20)?id=([0-9]+)\]?(#.*)?$/)) {
return { return {
LinkType: 'file', LinkType: 'file',
file: RegExp.$1, file: RegExp.$1,

View File

@ -9,6 +9,38 @@ class FileTest extends SapphireTest {
protected $extraDataObjects = array('FileTest_MyCustomFile'); 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() { function testCreateWithFilenameWithSubfolder() {
// Note: We can't use fixtures/setUp() for this, as we want to create the db record manually. // 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(), // Creating the folder is necessary to avoid having "Filename" overwritten by setName()/setRelativePath(),

View File

@ -28,3 +28,7 @@ File:
Filename: assets/FileTest-folder1/File1.txt Filename: assets/FileTest-folder1/File1.txt
Name: File1.txt Name: File1.txt
ParentID: =>Folder.folder1 ParentID: =>Folder.folder1
ErrorPage:
404:
Title: Page not Found
ErrorCode: 404