Skip to content

Tinymce5 #455

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
6 changes: 6 additions & 0 deletions .symfony.bundle.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
branches: ["master"]
maintained_branches: ["master"]
current_branch: "master"
dev_branch: "master"
dev_branch_alias: "10.x"
doc_dir: "docs/"
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