Skip to content

Commit

Permalink
Tinymce5 (#455)
Browse files Browse the repository at this point in the history
* Added symfony.bundle conf
* Added bundle conf
* Adding tinymce 5
  • Loading branch information
helios-ag authored Aug 29, 2021
1 parent 5112476 commit ab52b44
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
continue-on-error: false
strategy:
matrix:
php-version: ['7.2.5', '7.3', '7.4', '8.0']
php-version: ['7.4', '8.0']
steps:
- name: 'Checkout code'
uses: actions/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"exclude": ["/tests", "./github"]
},
"require": {
"php": "^7.2 || ^8.0",
"php": "^7.4 || ^8.0",
"ext-json": "*",
"symfony/framework-bundle": "^4.4 || ^5.0 || ^5.2",
"symfony/twig-bundle": "^4.4 || ^5.0 || ^5.2",
Expand Down
207 changes: 207 additions & 0 deletions src/Resources/public/tinymceElfinder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
window.tinymceElfinder = function(opts) {
// elFinder node
let elfNode = $('<div/>');
if (opts.nodeId) {
elfNode.attr('id', opts.nodeId);
delete opts.nodeId;
}

// upload target folder hash
const uploadTargetHash = opts.uploadTargetHash || 'L1_Lw';
delete opts.uploadTargetHash;

// get elFinder insrance
const getfm = open => {
// CSS class name of TinyMCE conntainer
const cls = (tinymce.majorVersion < 5)? 'mce-container' : 'tox';
return new Promise((resolve, reject) => {
// elFinder instance
let elf;

// Execute when the elFinder instance is created
const done = () => {
if (open) {
// request to open folder specify
if (!Object.keys(elf.files()).length) {
// when initial request
elf.one('open', () => {
elf.file(open)? resolve(elf) : reject(elf, 'errFolderNotFound');
});
} else {
// elFinder has already been initialized
new Promise((res, rej) => {
if (elf.file(open)) {
res();
} else {
// To acquire target folder information
elf.request({cmd: 'parents', target: open}).done(e =>{
elf.file(open)? res() : rej();
}).fail(() => {
rej();
});
}
}).then(() => {
if (elf.cwd().hash == open) {
resolve(elf);
} else {
// Open folder after folder information is acquired
elf.exec('open', open).done(() => {
resolve(elf);
}).fail(err => {
reject(elf, err? err : 'errFolderNotFound');
});
}
}).catch((err) => {
reject(elf, err? err : 'errFolderNotFound');
});
}
} else {
// show elFinder manager only
resolve(elf);
}
};

// Check elFinder instance
if (elf = elfNode.elfinder('instance')) {
// elFinder instance has already been created
done();
} else {
// To create elFinder instance
elf = elfNode.dialogelfinder(Object.assign({
// dialog title
title : 'File Manager',
// start folder setting
startPathHash : open? open : void(0),
// Set to do not use browser history to un-use location.hash
useBrowserHistory : false,
// Disable auto open
autoOpen : false,
// elFinder dialog width
width : '90%',
// elFinder dialog height
height : '90%',
// set getfile command options
commandsOptions : {
getfile: {
oncomplete : 'close'
}
},
bootCallback : (fm) => {
// set z-index
fm.getUI().css('z-index', parseInt($('body>.'+cls+':last').css('z-index')) + 100);
},
getFileCallback : (files, fm) => {}
}, opts)).elfinder('instance');
done();
}
});
};

this.browser = function(callback, value, meta) {
getfm().then(fm => {
let cgf = fm.getCommand('getfile');
const regist = () => {
fm.options.getFileCallback = cgf.callback = (file, fm) => {
var url, reg, info;

// URL normalization
url = fm.convAbsUrl(file.url);

// Make file info
info = file.name + ' (' + fm.formatSize(file.size) + ')';

// Provide file and text for the link dialog
if (meta.filetype == 'file') {
callback(url, {text: info, title: info});
}

// Provide image and alt text for the image dialog
if (meta.filetype == 'image') {
callback(url, {alt: info});
}

// Provide alternative source and posted for the media dialog
if (meta.filetype == 'media') {
callback(url);
}
};
fm.getUI().dialogelfinder('open');
};
if (cgf) {
// elFinder booted
regist();
} else {
// elFinder booting now
fm.bind('init', () => {
cgf = fm.getCommand('getfile');
regist();
});
}
});

return false;
};

this.uploadHandler = function (blobInfo, success, failure) {
new Promise(function(resolve, reject) {
getfm(uploadTargetHash).then(fm => {
let fmNode = fm.getUI(),
file = blobInfo.blob(),
clipdata = true;
const err = (e) => {
var dlg = e.data.dialog || {};
if (dlg.hasClass('elfinder-dialog-error') || dlg.hasClass('elfinder-confirm-upload')) {
fmNode.dialogelfinder('open');
fm.unbind('dialogopened', err);
}
},
closeDlg = () => {
if (!fm.getUI().find('.elfinder-dialog-error:visible,.elfinder-confirm-upload:visible').length) {
fmNode.dialogelfinder('close');
}
};

// check file object
if (file.name) {
// file blob of client side file object
clipdata = void(0);
}
// Bind err function and exec upload
fm.bind('dialogopened', err).exec('upload', {
files: [file],
target: uploadTargetHash,
clipdata: clipdata, // to get unique name on connector
dropEvt: {altKey: true, ctrlKey: true} // diable watermark on demo site
}, void(0), uploadTargetHash)
.done(data => {
if (data.added && data.added.length) {
fm.url(data.added[0].hash, { async: true }).done(function(url) {
// prevent to use browser cache
url += (url.match(/\?/)? '&' : '?') + '_t=' + data.added[0].ts;
resolve(fm.convAbsUrl(url));
}).fail(function() {
reject(fm.i18n('errFileNotFound'));
});
} else {
reject(fm.i18n(data.error? data.error : 'errUpload'));
}
})
.fail(err => {
const error = fm.parseError(err);
reject(fm.i18n(error? (error === 'userabort'? 'errAbort' : error) : 'errUploadNoFiles'));
})
.always(() => {
fm.unbind('dialogopened', err);
closeDlg();
});
}).catch((fm, err) => {
const error = fm.parseError(err);
reject(fm.i18n(error? (error === 'userabort'? 'errAbort' : error) : 'errUploadNoFiles'));
});
}).then((url) => {
success(url);
}).catch((err) => {
failure(err);
});
};
};
9 changes: 9 additions & 0 deletions src/Resources/views/Elfinder/helper/_tinymce5.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script type="text/javascript">
(function() {
const mceElf = new tinymceElfinder({
// connector URL (Use elFinder Demo site's connector for this demo)
url: "{{ url('elfinder', {'instance': instance}) }}",
nodeId: 'elfinder'
});
})();
</script>
46 changes: 16 additions & 30 deletions src/Twig/Extension/FMElfinderExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@

class FMElfinderExtension extends AbstractExtension
{
/**
* @var Environment
*/
protected $twig;

protected Environment $twig;

public function __construct(Environment $twig)
{
Expand All @@ -33,21 +31,19 @@ public function getFunctions()
return [
new TwigFunction('elfinder_tinymce_init', [$this, 'tinymce'], $options),
new TwigFunction('elfinder_tinymce_init4', [$this, 'tinymce4'], $options),
new TwigFunction('elfinder_tinymce_init4', [$this, 'tinymce5'], $options),
new TwigFunction('elfinder_summernote_init', [$this, 'summernote'], $options),
];
}

/**
* @param string $instance
* @param array $parameters
*
* @return mixed
*
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
public function tinymce($instance = 'default', $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0'])
public function tinymce(string $instance = 'default', array $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0'])
{
if (!is_string($instance)) {
throw new RuntimeError('The function can be applied to strings only.');
Expand All @@ -65,21 +61,12 @@ public function tinymce($instance = 'default', $parameters = ['width' => 900, 'h
}

/**
* @param string $instance
* @param array $parameters
*
* @return mixed
*
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
public function tinymce4($instance = 'default', $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0'])
public function tinymce4(string $instance = 'default', array $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0']): string
{
if (!is_string($instance)) {
throw new RuntimeError('The function can be applied to strings only.');
}

return $this->twig->render(
'@FMElfinder/Elfinder/helper/_tinymce4.html.twig',
[
Expand All @@ -91,23 +78,22 @@ public function tinymce4($instance = 'default', $parameters = ['width' => 900, '
);
}

public function tinymce5(string $instance = 'default'): string
{
return $this->twig->render(
'@FMElfinder/Elfinder/helper/_tinymce5.html.twig', [
'instance' => $instance,
]
);
}

/**
* @param string $instance
* @param string $selector
* @param array $parameters
*
* @return mixed
*
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
public function summernote($instance = 'default', $selector = '.summenote', $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0'])
public function summernote(string $instance = 'default', string $selector = '.summenote', array $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0']): string
{
if (!is_string($instance)) {
throw new RuntimeError('The function can be applied to strings only.');
}

return $this->twig->render(
'@FMElfinder/Elfinder/helper/_summernote.html.twig',
[
Expand All @@ -125,7 +111,7 @@ public function summernote($instance = 'default', $selector = '.summenote', $par
*
* @see Twig_ExtensionInterface::getName()
*/
public function getName()
public function getName(): string
{
return 'fm_elfinder_init';
}
Expand Down
25 changes: 0 additions & 25 deletions tests/Form/Type/ElFinderTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,8 @@ public function testGetName()
$this->assertEquals('elfinder', $type->getName());
}

public function testGetParentOld()
{
if (version_compare(Kernel::VERSION_ID, '20800') >= 0) {
$this->markTestSkipped('No need to test on symfony >= 2.8');
}
$type = new ElFinderType();
$this->assertEquals('text', $type->getParent());
}

public function testConfigureOptions()
{
if (version_compare(Kernel::VERSION_ID, '20600') < 0) {
$this->markTestSkipped('No need to test on symfony < 2.6');
}
$resolver = new OptionsResolver();
$type = new ElFinderType();
$type->configureOptions($resolver);
Expand All @@ -37,19 +25,6 @@ public function testConfigureOptions()
$this->assertTrue($resolver->isDefined('homeFolder'));
}

public function testLegacySetDefaultOptions()
{
if (version_compare(Kernel::VERSION_ID, '20600') >= 0) {
$this->markTestSkipped('No need to test on symfony >= 2.6');
}
$resolver = new OptionsResolver();
$type = new ElFinderType();
$type->setDefaultOptions($resolver);
$this->assertTrue($resolver->isKnown('enable'));
$this->assertTrue($resolver->isKnown('instance'));
$this->assertTrue($resolver->isKnown('homeFolder'));
}

public function testBuildView()
{
$options = [
Expand Down
Loading

0 comments on commit ab52b44

Please sign in to comment.