Fix tinymce plugins

This commit is contained in:
Damian Mooyman 2017-10-03 14:08:24 +13:00
parent cdefd19091
commit 5ffe64f024
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
6 changed files with 85 additions and 30 deletions

View File

@ -4,7 +4,6 @@ namespace SilverStripe\Core\Manifest;
use InvalidArgumentException;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\View\TemplateGlobalProvider;
/**
@ -23,21 +22,11 @@ class ModuleResourceLoader implements TemplateGlobalProvider
*/
public function resolvePath($resource)
{
// String of the form vendor/package:resource. Excludes "http://bla" as that's an absolute URL
if (!preg_match('#(?<module>[^/: ]*/[^/: ]*) *: *(?<resource>[^ ]*)#', $resource, $matches)) {
return $resource;
$resourceObj = $this->resolveModuleResource($resource);
if ($resourceObj) {
return $resourceObj->getRelativePath();
}
$module = $matches['module'];
$resource = $matches['resource'];
$moduleObj = ModuleLoader::getModule($module);
if (!$moduleObj) {
throw new InvalidArgumentException("Can't find module '$module'");
}
$resourceObj = $moduleObj->getResource($resource);
if (!$resourceObj->exists()) {
throw new InvalidArgumentException("Module '$module' does not have specified resource '$resource'");
}
return $resourceObj->getRelativePath();
return $resource;
}
/**
@ -48,9 +37,11 @@ class ModuleResourceLoader implements TemplateGlobalProvider
*/
public function resolveURL($resource)
{
/** @var ResourceURLGenerator $generator */
$generator = Injector::inst()->get(ResourceURLGenerator::class);
return $generator->urlForResource($this->resolvePath($resource));
$resourceObj = $this->resolveModuleResource($resource);
if ($resourceObj) {
return $resourceObj->getURL();
}
return $resource;
}
/**
@ -82,4 +73,30 @@ class ModuleResourceLoader implements TemplateGlobalProvider
'resourceURL'
];
}
/**
* Return module resource for the given path, if specified as one.
* Returns null if not a module resource.
*
* @param string $resource
* @return ModuleResource|null
*/
protected function resolveModuleResource($resource)
{
// String of the form vendor/package:resource. Excludes "http://bla" as that's an absolute URL
if (!preg_match('#(?<module>[^/: ]*/[^/: ]*) *: *(?<resource>[^ ]*)#', $resource, $matches)) {
return null;
}
$module = $matches['module'];
$resource = $matches['resource'];
$moduleObj = ModuleLoader::getModule($module);
if (!$moduleObj) {
throw new InvalidArgumentException("Can't find module '$module'");
}
$resourceObj = $moduleObj->getResource($resource);
if (!$resourceObj->exists()) {
throw new InvalidArgumentException("Module '$module' does not have specified resource '$resource'");
}
return $resourceObj;
}
}

View File

@ -8,6 +8,7 @@ use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Flushable;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Manifest\ModuleResource;
/**
* Generates tinymce config using a combined file generated via a standard
@ -90,9 +91,11 @@ class TinyMCECombinedGenerator implements TinyMCEScriptGenerator, Flushable
foreach ($config->getPlugins() as $plugin => $path) {
// Add external plugin
if ($path) {
// Convert URLS to relative paths
if (Director::is_absolute_url($path) || strpos($path, '/') === 0) {
// De-absolute site urls
if ($path instanceof ModuleResource) {
// Resolve path / url later
$files[] = $path;
} elseif (Director::is_absolute_url($path) || strpos($path, '/') === 0) {
// Convert URLS to relative paths
$path = Director::makeRelative($path);
if ($path) {
$files[] = $path;
@ -122,6 +125,9 @@ class TinyMCECombinedGenerator implements TinyMCEScriptGenerator, Flushable
// Process source files
$files = array_filter(array_map(function ($file) {
if ($file instanceof ModuleResource) {
return $file;
}
// Prioritise preferred paths
$paths = [
$file,
@ -162,11 +168,25 @@ SCRIPT;
SCRIPT;
// Load all tinymce script files into buffer
foreach ($files as $file) {
$buffer[] = $this->getFileContents(Director::baseFolder() . '/' . $file);
foreach ($files as $path) {
if ($path instanceof ModuleResource) {
$path = $path->getPath();
} else {
$path = Director::baseFolder() . '/' . $path;
}
$buffer[] = $this->getFileContents($path);
}
$filesList = Convert::raw2js(implode(',', $files));
// Generate urls for all files
$fileURLS = array_map(function ($path) {
if ($path instanceof ModuleResource) {
return $path->getURL();
}
return $path;
}, $files);
// Join list of paths
$filesList = Convert::raw2js(implode(',', $fileURLS));
// Mark all themes, plugins and languages as done
$buffer[] = "window.tinymce.each('$filesList'.split(','),".
"function(f){tinymce.ScriptLoader.markDone(baseURL+f);});";
@ -175,7 +195,6 @@ SCRIPT;
return implode("\n", $buffer) . "\n";
}
/**
* Returns the contents of the script file if it exists and removes the UTF-8 BOM header if it exists.
*

View File

@ -353,6 +353,7 @@ class TinyMCEConfig extends HTMLEditorConfig
* - null - Will be treated as a stardard plugin in the standard location
* - relative path - Will be treated as a relative url
* - absolute url - Some url to an external plugin
* - An instance of ModuleResource object containing the plugin
*
* @param string|array $plugin,... a string, or several strings, or a single array of strings - The plugins to enable
* @return $this
@ -395,7 +396,8 @@ class TinyMCEConfig extends HTMLEditorConfig
/**
* Gets the list of all enabled plugins as an associative array.
* Array keys are the plugin names, and values are potentially the plugin location
* Array keys are the plugin names, and values are potentially the plugin location,
* or ModuleResource object
*
* @return array
*/

View File

@ -4,7 +4,7 @@ namespace SilverStripe\Forms\Tests\HTMLEditor;
use SilverStripe\Control\Director;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Core\Manifest\Module;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
use SilverStripe\Forms\HTMLEditor\TinyMCECombinedGenerator;
@ -21,7 +21,9 @@ class TinyMCECombinedGeneratorTest extends SapphireTest
Director::config()->set('alternate_base_folder', __DIR__ . '/TinyMCECombinedGeneratorTest');
Director::config()->set('alternate_base_url', 'http://www.mysite.com/basedir/');
SSViewer::config()->set('themes', [SSViewer::DEFAULT_THEME]);
TinyMCEConfig::config()->set('base_dir', 'tinymce');
TinyMCEConfig::config()
->set('base_dir', 'tinymce')
->set('editor_css', [ 'mycode/editor.css' ]);
}
protected function tearDown()
@ -33,6 +35,7 @@ class TinyMCECombinedGeneratorTest extends SapphireTest
public function testConfig()
{
$module = new Module(Director::baseFolder().'/mycode', Director::baseFolder());
// Disable nonces
$c = new TinyMCEConfig();
$c->setTheme('testtheme');
@ -47,6 +50,7 @@ class TinyMCECombinedGeneratorTest extends SapphireTest
'plugin5' => null,
'plugin6' => '/basedir/mycode/plugin6.js',
'plugin7' => '/basedir/mycode/plugin7.js',
'plugin8' => $module->getResource('plugin8.js'),
)
);
HTMLEditorConfig::set_config('testconfig', $c);
@ -70,6 +74,8 @@ class TinyMCECombinedGeneratorTest extends SapphireTest
$this->assertContains("/* plugin4/langs/en.js */\n", $content);
$this->assertContains("/* plugin5.js */\n", $content);
$this->assertContains("/* plugin6.js */\n", $content);
// module-resource plugin
$this->assertContains("/* plugin8.js */\n", $content);
// Exclude non-local plugins
$this->assertNotContains('plugin2.js', $content);
$this->assertNotContains('plugin3.js', $content);
@ -80,10 +86,19 @@ class TinyMCECombinedGeneratorTest extends SapphireTest
$this->assertContains("/* theme.js */\n", $content);
$this->assertContains("/* testtheme/langs/en.js */\n", $content);
// Register done scripts
// Check plugin links included
$this->assertContains(
<<<EOS
tinymce.each('tinymce/langs/en.js,mycode/plugin1.js,tinymce/plugins/plugin4/plugin.min.js,tinymce/plugins/plugin4/langs/en.js,tinymce/plugins/plugin5/plugin.js,mycode/plugin6.js,tinymce/themes/testtheme/theme.js,tinymce/themes/testtheme/langs/en.js'.split(','),function(f){tinymce.ScriptLoader.markDone(baseURL+f);});
tinymce.each('tinymce/langs/en.js,mycode/plugin1.js,tinymce/plugins/plugin4/plugin.min.js,tinymce/plugins/plugin4/langs/en.js,tinymce/plugins/plugin5/plugin.js,mycode/plugin6.js,/basedir/mycode/plugin8.js?m=
EOS
,
$content
);
// Check theme links included
$this->assertContains(
<<<EOS
tinymce/themes/testtheme/theme.js,tinymce/themes/testtheme/langs/en.js'.split(','),function(f){tinymce.ScriptLoader.markDone(baseURL+f);});
EOS
,
$content

View File

@ -0,0 +1 @@
/* editor.css */

View File

@ -0,0 +1 @@
/* plugin8.js */