N°5298 - Upgrade CKEditor to version 5 (#647)

This commit is contained in:
Benjamin Dalsass
2024-05-24 16:13:20 +02:00
committed by GitHub
parent 094a9ed82f
commit 9bf0addc9c
105 changed files with 1820 additions and 949 deletions

View File

@@ -2,86 +2,77 @@
namespace Combodo\iTop\Application\Helper;
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\Renderer\BlockRenderer;
use Combodo\iTop\Renderer\RenderingOutput;
use Dict;
use Exception;
use ExceptionLog;
use UserRights;
use MetaModel;
use DBSearch;
use utils;
use appUserPreferences;
/***
/**
* Class CKEditorHelper
*
* (34) [
* 'blockQuote',
* 'bold',
* 'link',
* 'ckfinder',
* 'codeBlock',
* 'selectAll',
* 'undo',
* 'redo',
* 'heading',
* 'horizontalLine',
* 'imageTextAlternative',
* 'toggleImageCaption',
* 'imageStyle:inline',
* 'imageStyle:alignLeft',
* 'imageStyle:alignRight',
* 'imageStyle:alignCenter',
* 'imageStyle:alignBlockLeft',
* 'imageStyle:alignBlockRight',
* 'imageStyle:block',
* 'imageStyle:side',
* 'imageStyle:wrapText',
* 'imageStyle:breakText',
* 'uploadImage',
* 'imageUpload',
* 'indent',
* 'outdent',
* 'italic',
* 'numberedList',
* 'bulletedList',
* 'mediaEmbed',
* 'insertTable',
* 'tableColumn',
* 'tableRow',
* 'mergeTableCells']
* Utilities for CKEditor.
*
* @package Combodo\iTop\Application\Helper
* @since 3.2.0
*/
class CKEditorHelper
{
/**
* Return the CKEditor config as an array
* Get the CKEditor configuration.
*
* Create a default configuration, merge it with the user preferences and overload it with the provided configuration.
*
* @param bool $bWithMentions
* @param string|null $sInitialValue
* @param array $aOverloadConfiguration
*
* @return array
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @since 3.0.0
*/
static public function GetCkeditorPref()
static public function GetCkeditorConfiguration(bool $bWithMentions, ?string $sInitialValue, array $aOverloadConfiguration = []) : array
{
// Extract language from user preferences
$sLanguageCountry = trim(UserRights::GetUserLanguage());
$sLanguage = strtolower(explode(' ', $sLanguageCountry)[0]);
$aDefaultConf = array(
// configuration
$aConfiguration = array(
'language' => $sLanguage,
'detectChanges' => [
'initialValue' => $sInitialValue
],
'objectShortcut' => [
'buttonLabel' => Dict::S('UI:ObjectShortcutInsert')
],
);
// Mentions
$aDefaultConf['mention'] = self::GetMentionConfiguration();
if($bWithMentions){
try{
$aMentionConfiguration = self::GetMentionConfiguration();
$aConfiguration['mention'] = $aMentionConfiguration;
}
catch(Exception $e){
ExceptionLog::LogException($e);
}
}
// Rich text config
$aRichTextConfig = json_decode(appUserPreferences::GetPref('richtext_config', '{}'), true);
return array_merge($aDefaultConf, $aRichTextConfig);
// merge with overloaded configuration
return array_merge($aConfiguration, $aOverloadConfiguration);
}
/**
* Get mention configuration.
*
* @return array|array[]
* @throws \CoreException
* @throws \OQLException
* @throws \Exception
*/
static private function GetMentionConfiguration() : array
{
@@ -124,4 +115,149 @@ class CKEditorHelper
return $aMentionConfiguration;
}
/**
* Configure CKEditor element (WebPage).
*
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
* @param string $sInputElementId ID of the HTML Input element
* @param string|null $sInitialValue input initial value
* @param bool $bWithMentions enable mentions
* @param array $aOverloadConfiguration overload configuration
*
* @return void
*/
public static function ConfigureCKEditorElementForWebPage(WebPage $oPage, string $sInputElementId, string $sInitialValue = null, bool $bWithMentions = false, array $aOverloadConfiguration = []): void
{
// link CKEditor JS files
foreach (static::GetJSFilesRelPathsForCKEditor() as $sFile) {
try{
$oPage->LinkScriptFromAppRoot($sFile);
}
catch(Exception $e){
ExceptionLog::LogException($e);
}
}
// retrieve CKEditor configuration
$aConfiguration = self::GetCkeditorConfiguration($bWithMentions, $sInitialValue, $aOverloadConfiguration);
// add CKEditor initialization script
$sConfigJS = json_encode($aConfiguration);
$oPage->add_ready_script("CombodoCKEditorHandler.CreateInstance('#$sInputElementId', $sConfigJS)");
// handle mentions template
if($bWithMentions){
try{
$sMentionTemplate = self::GetMentionsTemplate($sInputElementId);
$oPage->add($sMentionTemplate);
}
catch(Exception $e){
ExceptionLog::LogException($e);
}
}
}
/**
* Configure CKEditor element (RenderingOutput).
*
* @param \Combodo\iTop\Renderer\RenderingOutput $oOutput
* @param string $sInputElementId ID of the HTML Input element
* @param string|null $sInitialValue input initial value
* @param bool $bWithMentions enable mentions
* @param bool $bAddJSFiles add JS files to the output
* @param array $aOverloadConfiguration overload configuration
*
* @return void
*/
public static function ConfigureCKEditorElementForRenderingOutput(RenderingOutput $oOutput, string $sInputElementId, string $sInitialValue = null, bool $bWithMentions = false, bool $bAddJSFiles = true, array $aOverloadConfiguration = []): void
{
// link CKEditor JS files
if($bAddJSFiles){
foreach (static::GetJSFilesRelPathsForCKEditor() as $sFile) {
try{
$oOutput->AddJsFile($sFile);
}
catch(Exception $e){
ExceptionLog::LogException($e);
}
}
}
// configuration
$aConfiguration = self::GetCkeditorConfiguration($bWithMentions, $sInitialValue, $aOverloadConfiguration);
// add CKEditor initialization script
$sConfigJS = json_encode($aConfiguration);
$oOutput->AddJs("CombodoCKEditorHandler.CreateInstance('#$sInputElementId', $sConfigJS)");
// mentions template
if($bWithMentions){
try{
$sMentionTemplate = self::GetMentionsTemplate($sInputElementId);
$oOutput->add($sMentionTemplate);
}
catch(Exception $e){
ExceptionLog::LogException($e);
}
}
}
/**
* GetMentionsTemplate.
*
* @param string $sComponentId
*
* @return string
* @throws \Exception
*/
public static function GetMentionsTemplate(string $sComponentId): string
{
// twig environment
$oTwig = TwigHelper::GetTwigEnvironment(BlockRenderer::TWIG_BASE_PATH);
// mention template
$sMentionsTemplate = $oTwig->render('application/object/set/option_renderer.html.twig');
return <<<HTML
<template id="{$sComponentId}_items_template">
$sMentionsTemplate
</template>
HTML;
}
/**
* @return string[] Relative URLs to the JS files necessary for CKEditor
*/
public static function GetJSFilesRelPathsForCKEditor(): array
{
// all js file needed by ckeditor
$aJSRelPaths = [
'js/ckeditor/build/ckeditor.js',
'js/highlight/highlight.js',
'js/ckeditor.handler.js',
'js/ckeditor.feeds.js'
];
// add CKEditor translations resource
$sUserLanguage = Dict::GetUserLanguage();
$sLanguage = strtolower(explode(' ', $sUserLanguage)[0]);
$sCountry = strtolower(explode(' ', $sUserLanguage)[1]);
// add corresponding ckeditor language file
// P1 language + country
// P2 language
$sLanguageFileRelPath = 'js/ckeditor/build/translations/' . $sLanguage . '-' . $sCountry . '.js';
if(file_exists(APPROOT . $sLanguageFileRelPath)){
$aJSRelPaths[] = $sLanguageFileRelPath;
}
else {
$sLanguageFileRelPath = 'js/ckeditor/build/translations/' . $sLanguage . '.js';
if(file_exists(APPROOT . $sLanguageFileRelPath)){
$aJSRelPaths[] = $sLanguageFileRelPath;
}
}
return $aJSRelPaths;
}
}