'fieldset', '#title' => t('WYSIWYG Filter'), '#collapsible' => TRUE, '#collapsed' => FALSE, ); $valid_elements = wysiwyg_filter_get_valid_elements($format); $elements_blacklist = wysiwyg_filter_get_elements_blacklist(); foreach ($elements_blacklist as $i => $element) { $elements_blacklist[$i] = '<'. $element .'>'; } $form['wysiwyg_filter']['wysiwyg_filter_valid_elements_raw_'. $format] = array( '#type' => 'textarea', '#title' => t('HTML elements and attributes'), '#default_value' => $valid_elements, '#cols' => 60, '#rows' => min(20, max(5, substr_count($valid_elements, "\n") + 2)), '#description' => t('
This option allows you to specify which HTML elements and attributes are allowed in TinyMCE valid_elements format.
Syntax tips:'. t('This section allows you to select which style properties can be used for HTML elements where the "style" attribute has been allowed. The WYSIWYG Filter will strip out style properties (and their values) not explicitly enabled here. On the other hand, for allowed style properties the WYSIWYG Filter will check their values for strict CSS syntax and strip out those that do not match.') .'
'. ''. t('Additional matching rules should be specified from the "Advanced rules" section below for a few of these properties that may contain URLs in their values ("background", "background-image", "list-style" and "list-style-image"). Otherwise, these style properties will be ignored from user input.') .'
', ); $style_property_groups = wysiwyg_filter_get_style_property_groups(); $enabled_style_properties = array(); $i = 0; foreach ($style_property_groups as $group => $group_info) { $style_properties = variable_get('wysiwyg_filter_styles_'. $group .'_'. $format, array()); $enabled_style_properties += array_filter($style_properties); $form['wysiwyg_filter']['styles']['wysiwyg_filter_styles_'. $group .'_'. $format] = array( '#type' => 'checkboxes', '#title' => $group_info['title'], '#default_value' => $style_properties, '#options' => drupal_map_assoc(array_keys($group_info['properties'])), '#checkall' => TRUE, '#prefix' => ''. t('Use the following options to configure additional rules for certain HTML element attributes. As a safety measure, these rules should be defined explicitly. Otherwise, the corresponding HTML element attributes will be ignored from user input.') .'
', ); _wysiwyg_filter_clear_messages(); $valid_elements_parsed = wysiwyg_filter_get_valid_elements($format, TRUE); foreach (wysiwyg_filter_get_advanced_rules() as $rule_key => $rule_info) { $field_name = 'wysiwyg_filter_'. $rule_key .'_'. $format; $default_value = implode(",\n", variable_get($field_name, array())); $form['wysiwyg_filter']['advanced_rules'][$field_name] = array( '#type' => 'textarea', '#title' => $rule_info['title'], '#default_value' => $default_value, '#cols' => 60, '#rows' => min(10, max(2, substr_count($default_value, "\n") + 2)), '#description' => $rule_info['description'], ); // Display warning if the field is empty but the rule definition is not // complete. if (empty($default_value) && !_wysiwyg_filter_is_rule_definition_complete($rule_info, $valid_elements_parsed, $enabled_style_properties)) { drupal_set_message($rule_info['required_by_message'], 'warning'); $form['wysiwyg_filter']['advanced_rules']['#collapsed'] = FALSE; } } $form['wysiwyg_filter']['nofollow'] = array( '#type' => 'fieldset', '#title' => t('Spam link deterrent settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('As a measure to reduce the effectiveness of spam links, it is often recommended to add rel="nofollow" to posted links leading to external sites. The WYSIWYG Filter can easily do this for you while HTML is being processed with almost no additional performance impact.'), ); $form['wysiwyg_filter']['nofollow']['wysiwyg_filter_nofollow_policy_'. $format] = array( '#type' => 'radios', '#title' => t('Policy'), '#options' => array( 'disabled' => t('Disabled - Do not add rel="nofollow" to any link.'), 'whitelist' => t('Whitelist - Add rel="nofollow" to all links except those leading to domain names specified in the list below.'), 'blacklist' => t('Blacklist - Add rel="nofollow" to all links leading to domain names specified in the list below.'), ), '#default_value' => variable_get('wysiwyg_filter_nofollow_policy_'. $format, 'whitelist'), '#description' => t('If you choose the whitelist option, be sure to add your own domain names to the list!'), ); $parts = parse_url($base_url); // Note that domains list is stored by our submit handler in array form where // dots have been escaped, so we need here to revert the process to get a clean // string for user input where dots are unescaped. $nofollow_domains = str_replace('\.', '.', implode(",\n", variable_get('wysiwyg_filter_nofollow_domains_'. $format, array($parts['host'])))); $form['wysiwyg_filter']['nofollow']['wysiwyg_filter_nofollow_domains_'. $format] = array( '#type' => 'textarea', '#title' => t('Domains list'), '#default_value' => $nofollow_domains, '#cols' => 60, '#rows' => min(10, max(5, substr_count($nofollow_domains, "\n") + 2)), '#description' => t('Enter a comma separated list of top level domain names. Note that all subdomains will also be included. Example: example.com will match example.com, www.example.com, etc.'), ); return $form; } /** * Implementation of hook_form_FORM_ID_alter(). * * Because filter format forms are merged, any common keys need to be added in * a form_alter. Otherwise, e.g. submit handlers added by one module would be * overwritten by those of another module. */ function wysiwyg_filter_form_filter_admin_configure_alter(&$form, $form_state) { if (isset($form['wysiwyg_filter'])) { $form['#validate'][] = 'wysiwyg_filter_settings_filter_validate'; // Add the submit callback to the beginning of the array because we need // to prepare data for system_settings_form_submit(). array_unshift($form['#submit'], 'wysiwyg_filter_settings_filter_submit'); } } /** * Validate if the given rule definition is complete. * * @param $rule_info * An array of information about the rule we are about to check. * @param $elements * The array of all valid elements enabled for the current filter. * @param $style_properties * The array of all style properties enabled for the current filter. * @return * TRUE if the rule definiton is complete, FALSE otherwise. * * @see wysiwyg_filter_parse_valid_elements() * @see wysiwyg_filter_get_advanced_rules() */ function _wysiwyg_filter_is_rule_definition_complete($rule_info, $elements, $style_properties) { foreach ($elements as $tag => $attributes) { if (isset($attributes[$rule_info['required_by']])) { // If this rule is not dependent on style properties, then we found it, // while we should not, so the rule is not complete. if (empty($rule_info['required_by_styles'])) { return FALSE; } // If this rule is dependent on style properties, then we need to check // if the related style properties exist. foreach ($rule_info['required_by_styles'] as $style_property) { if (isset($style_properties[$style_property])) { return FALSE; } } } } return TRUE; } /** * Clear any warning message we might have set previously. */ function _wysiwyg_filter_clear_messages() { $messages = drupal_get_messages('warning'); if (!empty($messages)) { foreach (wysiwyg_filter_get_advanced_rules() as $rule_info) { $my_messages[] = $rule_info['required_by_message']; } foreach ($messages['warning'] as $warning) { if (!in_array($warning, $my_messages)) { drupal_set_message($warning, 'warning'); } } } } /** * Validate filter settings form. * * @ingroup forms */ function wysiwyg_filter_settings_filter_validate($form, &$form_state) { $format = $form_state['values']['format']; // Check elements against hardcoded backlist. $elements_blacklist = wysiwyg_filter_get_elements_blacklist(); $valid_elements = trim($form_state['values']['wysiwyg_filter_valid_elements_raw_'. $format]); $valid_elements = wysiwyg_filter_parse_valid_elements($valid_elements); $forbidden_elements = array(); foreach (array_keys($valid_elements) as $element) { if (in_array($element, $elements_blacklist)) { $forbidden_elements[] = $element; } } if (!empty($forbidden_elements)) { form_set_error('wysiwyg_filter_valid_elements_raw_'. $format, t('The following elements cannot be allowed: %elements.', array('%elements' => implode(', ', $forbidden_elements)))); } foreach (wysiwyg_filter_get_advanced_rules() as $rule_key => $rule_info) { $field_name = 'wysiwyg_filter_'. $rule_key .'_'. $format; $expressions = array_filter(explode(',', preg_replace('#\s+#', ',', trim($form_state['values'][$field_name])))); $errors = array(); foreach ($expressions as $expression) { if (preg_match('`[*?]\*|\*\?`', $expression)) { $errors[] = t('Invalid expression %expression. Please, do not use more than one consecutive asterisk (**) or one that is next to a question mark wildcard (?* or *?).', array('%expression' => $expression)); } if (!preg_match($rule_info['validate_regexp'], $expression)) { $errors[] = t('Invalid expression %expression. Please, check the syntax of the %field field.', array('%expression' => $expression, '%field' => $rule_info['title'])); } } if (!empty($errors)) { form_set_error($field_name, implode('