Skip to content

Commit

Permalink
Merge pull request #9419 from colemanw/CRM-19649
Browse files Browse the repository at this point in the history
CRM-19649 - Multiple wysiwyg config presets
  • Loading branch information
colemanw authored Nov 21, 2016
2 parents 7f57eaf + 9931611 commit ff61eaa
Show file tree
Hide file tree
Showing 14 changed files with 1,480 additions and 83 deletions.
2 changes: 1 addition & 1 deletion CRM/Admin/Form/MessageTemplates.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public function buildQuickForm() {
'cols' => '80',
'rows' => '8',
'onkeyup' => "return verify(this)",
'class' => 'crm-wysiwyg-fullpage',
'preset' => 'civimail',
)
);
}
Expand Down
109 changes: 71 additions & 38 deletions CRM/Admin/Page/CKEditorConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,47 @@
*/
class CRM_Admin_Page_CKEditorConfig extends CRM_Core_Page {

const CONFIG_FILENAME = '[civicrm.files]/persist/crm-ckeditor-config.js';
const CONFIG_FILEPATH = '[civicrm.files]/persist/crm-ckeditor-';

/**
* Default settings if config file has not been initialized
* Settings that cannot be configured in "advanced options"
*
* @var array
*/
public $defaultSettings = array(
'skin' => 'moono',
'extraPlugins' => '',
public $blackList = array(
'on',
'skin',
'extraPlugins',
'toolbarGroups',
'removeButtons',
'filebrowserBrowseUrl',
'filebrowserImageBrowseUrl',
'filebrowserFlashBrowseUrl',
'filebrowserUploadUrl',
'filebrowserImageUploadUrl',
'filebrowserFlashUploadUrl',
);

public $preset;

/**
* Run page.
*
* @return string
*/
public function run() {
$this->preset = CRM_Utils_Array::value('preset', $_REQUEST, 'default');

// If the form was submitted, take appropriate action.
if (!empty($_POST['revert'])) {
self::deleteConfigFile();
self::deleteConfigFile($this->preset);
}
elseif (!empty($_POST['config'])) {
$this->save($_POST);
}

$settings = $this->getConfigSettings();

CRM_Core_Resources::singleton()
->addScriptFile('civicrm', 'bower_components/ckeditor/ckeditor.js', 0, 'page-header')
->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js', 1)
Expand All @@ -76,12 +91,21 @@ public function run() {
->addStyleFile('civicrm', 'bower_components/ckeditor/samples/css/samples.css')
->addVars('ckConfig', array(
'plugins' => array_values($this->getCKPlugins()),
'blacklist' => $this->blackList,
'settings' => $settings,
));

$configUrl = self::getConfigUrl($this->preset);
if (!$configUrl) {
$configUrl = self::getConfigUrl('default');
}

$this->assign('preset', $this->preset);
$this->assign('presets', CRM_Core_OptionGroup::values('wysiwyg_presets', FALSE, FALSE, FALSE, NULL, 'label', TRUE, FALSE, 'name'));
$this->assign('skins', $this->getCKSkins());
$this->assign('skin', $this->getConfigSetting('skin'));
$this->assign('extraPlugins', $this->getConfigSetting('extraPlugins'));
$this->assign('configUrl', self::getConfigUrl());
$this->assign('skin', CRM_Utils_Array::value('skin', $settings));
$this->assign('extraPlugins', CRM_Utils_Array::value('extraPlugins', $settings));
$this->assign('configUrl', $configUrl);
$this->assign('revertConfirm', htmlspecialchars(ts('Are you sure you want to revert all changes?', array('escape' => 'js'))));

CRM_Utils_System::appendBreadCrumb(array(array(
Expand All @@ -107,15 +131,20 @@ public function save($params) {
// Standardize line-endings
. preg_replace('~\R~u', "\n", $params['config']);

// Use defaultSettings as a whitelist so we don't just insert any old junk into the file
foreach ($this->defaultSettings as $key => $default) {
if (isset($params[$key]) && strlen($params[$key])) {
// Use all params starting with config_
foreach ($params as $key => $val) {
$val = trim($val);
if (strpos($key, 'config_') === 0 && strlen($val)) {
if ($val != 'true' && $val != 'false' && $val[0] != '{' && $val[0] != '[' && !is_numeric($val)) {
$val = json_encode($val);
}
$pos = strrpos($config, '};');
$setting = "\n\tconfig.$key = '{$params[$key]}';\n";
$key = preg_replace('/^config_/', 'config.', $key);
$setting = "\n\t{$key} = {$val};\n";
$config = substr_replace($config, $setting, $pos, 0);
}
}
self::saveConfigFile($config);
self::saveConfigFile($this->preset, $config);
if (!empty($params['save'])) {
CRM_Core_Session::setStatus(ts("You may need to clear your browser's cache to see the changes in CiviCRM."), ts('CKEditor Saved'), 'success');
}
Expand Down Expand Up @@ -172,57 +201,61 @@ private function getCKSkins() {
}

/**
* @param $setting
* @return string
* @return array
*/
private function getConfigSetting($setting) {
$value = CRM_Utils_Array::value($setting, $this->defaultSettings, '');
$file = self::getConfigFile();
private function getConfigSettings() {
$matches = $result = array();
$file = self::getConfigFile($this->preset);
$result['skin'] = 'moono';
if ($file) {
$contents = file_get_contents($file);
$matches = array();
preg_match("/\sconfig\.$setting\s?=\s?'([^']*)'/", $contents, $matches);
if ($matches) {
$value = $matches[1];
preg_match_all("/\sconfig\.(\w+)\s?=\s?([^;]*);/", $contents, $matches);
foreach ($matches[1] as $i => $match) {
$result[$match] = trim($matches[2][$i], ' "\'');
}
}
return $value;
return $result;
}

/**
* @return null|string
* @param string $preset
* Omit to get an array of all presets
* @return array|null|string
*/
public static function getConfigUrl() {
if (self::getConfigFile()) {
return Civi::paths()->getUrl(self::CONFIG_FILENAME, 'absolute');
public static function getConfigUrl($preset = NULL) {
$items = array();
$presets = CRM_Core_OptionGroup::values('wysiwyg_presets', FALSE, FALSE, FALSE, NULL, 'name');
foreach ($presets as $key => $name) {
if (self::getConfigFile($name)) {
$items[$name] = Civi::paths()->getUrl(self::CONFIG_FILEPATH . $name . '.js', 'absolute');
}
}
return NULL;
return $preset ? CRM_Utils_Array::value($preset, $items) : $items;
}

/**
* @param bool $checkIfFileExists
* If false, this fn will return fileName even if it doesn't exist
* @param string $preset
*
* @return null|string
*/
public static function getConfigFile($checkIfFileExists = TRUE) {
$fileName = Civi::paths()->getPath(self::CONFIG_FILENAME);
return !$checkIfFileExists || is_file($fileName) ? $fileName : NULL;
public static function getConfigFile($preset = 'default') {
$fileName = Civi::paths()->getPath(self::CONFIG_FILEPATH . $preset . '.js');
return is_file($fileName) ? $fileName : NULL;
}

/**
* @param string $contents
*/
public static function saveConfigFile($contents) {
$file = self::getConfigFile(FALSE);
public static function saveConfigFile($preset, $contents) {
$file = Civi::paths()->getPath(self::CONFIG_FILEPATH . $preset . '.js');
file_put_contents($file, $contents);
}

/**
* Delete config file.
*/
public static function deleteConfigFile() {
$file = self::getConfigFile();
public static function deleteConfigFile($preset) {
$file = self::getConfigFile($preset);
if ($file) {
unlink($file);
}
Expand Down
4 changes: 4 additions & 0 deletions CRM/Core/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ public function &add(
if ($type == 'wysiwyg' || in_array($type, self::$html5Types)) {
$attributes = ($attributes ? $attributes : array()) + array('class' => '');
$attributes['class'] = ltrim($attributes['class'] . " crm-form-$type");
if ($type == 'wysiwyg' && isset($attributes['preset'])) {
$attributes['data-preset'] = $attributes['preset'];
unset($attributes['preset']);
}
$type = $type == 'wysiwyg' ? 'textarea' : 'text';
}
// @see http://wiki.civicrm.org/confluence/display/CRMDOC/crmDatepicker
Expand Down
5 changes: 1 addition & 4 deletions CRM/Core/Resources.php
Original file line number Diff line number Diff line change
Expand Up @@ -728,10 +728,7 @@ public function coreResourceList($region) {
$editor = Civi::settings()->get('editor_id');
if ($editor == "CKEditor") {
$items[] = "js/wysiwyg/crm.ckeditor.js";
$ckConfig = CRM_Admin_Page_CKEditorConfig::getConfigUrl();
if ($ckConfig) {
$items[] = array('config' => array('CKEditorCustomConfig' => $ckConfig));
}
$items[] = array('config' => array('CKEditorCustomConfig' => CRM_Admin_Page_CKEditorConfig::getConfigUrl()));
}

// These scripts are only needed by back-office users
Expand Down
2 changes: 1 addition & 1 deletion CRM/Event/Form/ManageEvent/EventInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public function buildQuickForm() {
$this->addSelect('participant_listing_id', array('placeholder' => ts('Disabled'), 'option_url' => NULL));

$this->add('textarea', 'summary', ts('Event Summary'), $attributes['summary']);
$this->add('wysiwyg', 'description', ts('Complete Description'), $attributes['event_description']);
$this->add('wysiwyg', 'description', ts('Complete Description'), $attributes['event_description'] + array('preset' => 'civievent'));
$this->addElement('checkbox', 'is_public', ts('Public Event'));
$this->addElement('checkbox', 'is_share', ts('Allow sharing through social media?'));
$this->addElement('checkbox', 'is_map', ts('Include Map to Event Location'));
Expand Down
10 changes: 5 additions & 5 deletions CRM/Event/Form/ManageEvent/Registration.php
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ public function buildQuickForm() {
*
*/
public function buildRegistrationBlock(&$form) {
$attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event', 'intro_text') + array('class' => 'collapsed');
$attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event', 'intro_text') + array('class' => 'collapsed', 'preset' => 'civievent');
$form->add('wysiwyg', 'intro_text', ts('Introductory Text'), $attributes);
$form->add('wysiwyg', 'footer_text', ts('Footer Text'), $attributes);

Expand Down Expand Up @@ -406,8 +406,8 @@ public function buildConfirmationBlock(&$form) {
$form->addYesNo('is_confirm_enabled', ts('Use a confirmation screen?'), NULL, NULL, array('onclick' => "return showHideByValue('is_confirm_enabled','','confirm_screen_settings','block','radio',false);"));
}
$form->add('text', 'confirm_title', ts('Title'), $attributes['confirm_title']);
$form->add('wysiwyg', 'confirm_text', ts('Introductory Text'), $attributes['confirm_text'] + array('class' => 'collapsed'));
$form->add('wysiwyg', 'confirm_footer_text', ts('Footer Text'), $attributes['confirm_text'] + array('class' => 'collapsed'));
$form->add('wysiwyg', 'confirm_text', ts('Introductory Text'), $attributes['confirm_text'] + array('class' => 'collapsed', 'preset' => 'civievent'));
$form->add('wysiwyg', 'confirm_footer_text', ts('Footer Text'), $attributes['confirm_text'] + array('class' => 'collapsed', 'preset' => 'civievent'));
}

/**
Expand Down Expand Up @@ -436,8 +436,8 @@ public function buildMailBlock(&$form) {
public function buildThankYouBlock(&$form) {
$attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event');
$form->add('text', 'thankyou_title', ts('Title'), $attributes['thankyou_title']);
$form->add('wysiwyg', 'thankyou_text', ts('Introductory Text'), $attributes['thankyou_text'] + array('class' => 'collapsed'));
$form->add('wysiwyg', 'thankyou_footer_text', ts('Footer Text'), $attributes['thankyou_text'] + array('class' => 'collapsed'));
$form->add('wysiwyg', 'thankyou_text', ts('Introductory Text'), $attributes['thankyou_text'] + array('class' => 'collapsed', 'preset' => 'civievent'));
$form->add('wysiwyg', 'thankyou_footer_text', ts('Footer Text'), $attributes['thankyou_text'] + array('class' => 'collapsed', 'preset' => 'civievent'));
}

/**
Expand Down
56 changes: 56 additions & 0 deletions CRM/Upgrade/Incremental/php/FourSeven.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,15 @@ public function upgrade_4_7_13($rev) {
$this->addTask('Add column to allow for payment processors to set what card types are accepted', 'addAcceptedCardTypesField');
}

/**
* Upgrade function.
*
* @param string $rev
*/
public function upgrade_4_7_14($rev) {
$this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
$this->addTask('Add WYSIWYG Editor Presets', 'addWysiwygPresets');
}

/*
* Important! All upgrade functions MUST add a 'runSql' task.
Expand Down Expand Up @@ -882,4 +891,51 @@ public static function addAcceptedCardTypesField() {
return TRUE;
}

/**
* CRM-19372 Add field to store accepted credit credit cards for a payment processor.
* @return bool
*/
public static function addWysiwygPresets() {
CRM_Core_BAO_OptionGroup::ensureOptionGroupExists(array(
'name' => 'wysiwyg_presets',
'title' => ts('WYSIWYG Editor Presets'),
'is_reserved' => 1,
));
$values = array(
'default' => array('label' => ts('Default'), 'is_default' => 1),
'civimail' => array('label' => ts('CiviMail'), 'component_id' => 'CiviMail'),
'civievent' => array('label' => ts('CiviEvent'), 'component_id' => 'CiviEvent'),
);
foreach ($values as $name => $value) {
civicrm_api3('OptionValue', 'create', $value + array(
'options' => array('match' => array('name', 'option_group_id')),
'name' => $name,
'option_group_id' => 'wysiwyg_presets',
));
}
$fileName = Civi::paths()->getPath('[civicrm.files]/persist/crm-ckeditor-config.js');
// Ensure the config file contains the allowedContent setting
if (file_exists($fileName)) {
$config = file_get_contents($fileName);
$pos = strrpos($config, '};');
$setting = "\n\tconfig.allowedContent = true;\n";
$config = substr_replace($config, $setting, $pos, 0);
unlink($fileName);
}
// Create config file if it doesn't exist
else {
$config = "CKEDITOR.editorConfig = function( config ) {\n\tconfig.allowedContent = true;\n};\n";
// Make sure directories exist
if (!is_dir(Civi::paths()->getPath('[civicrm.files]'))) {
mkdir(Civi::paths()->getPath('[civicrm.files]'));
}
if (!is_dir(Civi::paths()->getPath('[civicrm.files]/persist'))) {
mkdir(Civi::paths()->getPath('[civicrm.files]/persist'));
}
}
$newFileName = Civi::paths()->getPath('[civicrm.files]/persist/crm-ckeditor-default.js');
file_put_contents($newFileName, $config);
return TRUE;
}

}
2 changes: 1 addition & 1 deletion ang/crmMailing/BodyHtml.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
crm-ui-insert-rx="insert:body_html"
ng-model="mailing.body_html"
ng-blur="checkTokens(mailing, 'body_html', 'insert:body_html')"
class="crm-wysiwyg-fullpage"
data-preset="civimail"
></textarea>
<span ng-model="body_html_tokens" crm-ui-validate="hasAllTokens(mailing, 'body_html')"></span>
<div ng-show="htmlForm.$error.crmUiValidate" class="crmMailing-error-link">
Expand Down
Loading

0 comments on commit ff61eaa

Please sign in to comment.