View source
<?php
define('VBO_SNR_NO_FIELD_EXLUSIONS', '_none_');
function vbo_search_and_replace_action_info() {
if (!module_exists('content')) {
return array();
}
return array(
'vbo_search_and_replace_action' => array(
'type' => 'node',
'description' => t('Search and Replace'),
'configurable' => TRUE,
'rules_ignore' => TRUE,
),
);
}
function vbo_search_and_replace_action_form($context) {
$form = array();
if (!isset($context['settings'])) {
$context['settings'] = vbo_search_and_replace_action_views_bulk_operations_form_default_settings();
}
if ($context['settings']['selection_widget'] == 'checkboxes' && $context['settings']['checkbox_columns']) {
$style = '<style>
.views-bulk-operations-form .form-checkboxes.fields-to-search .form-item {
width: 200px;
display: inline-block;
}</style>';
drupal_set_html_head($style);
}
$options = vbo_search_and_replace_get_available_fields($context, $context['settings']['selection_widget'] == 'select');
$form['fields_to_search'] = array(
'#title' => t('Field(s) to Search'),
'#type' => $context['settings']['selection_widget'],
'#multiple' => TRUE,
'#size' => 20,
'#description' => t('Choose which field(s) to perform a search and replace on'),
'#options' => $options,
'#required' => TRUE,
'#attributes' => array(
'class' => 'fields-to-search',
),
'#default_value' => array(),
);
$form['all_fields'] = array(
'#type' => 'value',
'#default_value' => array_slice(vbo_search_and_replace_get_available_fields($context), 1),
);
$form['search'] = array(
'#title' => t('Search'),
'#type' => 'textarea',
'#description' => t('The string to search for, that will be replaced'),
'#required' => TRUE,
);
$form['replace'] = array(
'#title' => t('Replace'),
'#type' => 'textarea',
'#description' => t('The replacement string. The search string will be replaced with this.'),
);
$form['advanced'] = array(
'#title' => t('Advanced Options'),
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#attributes' => array(
'class' => 'search-and-replace-advanced-options',
),
);
$form['advanced']['details'] = array(
'#value' => t('Enhanced searches can be performed by specifying a prefix and a suffix for the search string. Only results that match the prefix, the search string and the suffix will be affected, however, only the search string will be replaced. <br/>
<em><strong>Example 1:</strong><br/>
<ul>
<li> *Search String: "brown"</li>
<li> *Replacement String: "yellow"</li>
</ul>
Using the above parameters, all the instances of "brown" will be changed to "yellow"<br/>
<strong>Example 1:</strong><br/>
<ul>
<li> *Prefix: "the quick "</li>
<li> *Search String: "brown"</li>
<li> *Suffix: " fox"</li>
<li> *Replacement String: "yellow"</li>
</ul>
Using the above parameters, "brown" will only be replaced with "yellow" if it is wrapped in the prefix and suffix. So, "the quick brown fox" will become to "the quick yellow fox"</em>'),
'#prefix' => '<div class="description">',
'#suffix' => '</div>',
);
$form['advanced']['search_prefix'] = array(
'#title' => t('Search Prefix'),
'#type' => 'textfield',
'#description' => t('The string that search string must be immediately preceeded by in order for a match to be made'),
);
$form['advanced']['search_suffix'] = array(
'#title' => t('Search Suffix'),
'#type' => 'textfield',
'#description' => t('The string that the search string must be immediately followed by in order for a match to be made'),
);
$form['advanced']['case_sensitive'] = array(
'#title' => t('Case Sensitive'),
'#type' => 'checkbox',
'#default_value' => 0,
'#description' => t('Whether or not the search should be case sensitive'),
);
$form['advanced']['exact_match'] = array(
'#title' => t('Exact Match'),
'#type' => 'checkbox',
'#default_value' => 0,
'#description' => t('Check this if the entire field must match the search parameters including the prefix and suffix. <i>example: With this option selected, for the search string "The quick brown fox" to obtain a match, the entire contents of the field must be "The quick brown fox". A field with the value "The quick brown fox jumps over the lazy dog" will not be considered a match</i>'),
);
return $form;
}
function vbo_search_and_replace_action_submit($form, &$form_state) {
$fields = $form_state['values']['fields_to_search'];
$all_fields = content_fields();
$properties = vbo_search_and_replace_node_properties();
if (isset($fields['_all_']) && $fields['_all_']) {
$fields = array();
foreach ($form_state['values']['all_fields'] as $key => $value) {
if (array_key_exists($key, $properties)) {
$fields[$key] = $properties[$key];
}
else {
$fields[$key] = $all_fields[$key]['widget']['label'];
}
}
}
else {
foreach ($fields as $key => $value) {
if ($value) {
if (array_key_exists($key, $properties)) {
$fields[$key] = $properties[$key];
}
else {
$fields[$key] = $all_fields[$key]['widget']['label'];
}
}
else {
unset($fields[$key]);
}
}
}
$settings = array(
'search_prefix' => $form_state['values']['search_prefix'],
'search_suffix' => $form_state['values']['search_suffix'],
'case_sensitive' => $form_state['values']['case_sensitive'],
'exact_match' => $form_state['values']['exact_match'],
);
return array(
'fields' => $fields,
'search_and_replace_settings' => $settings,
'search' => $form_state['values']['search'],
'replace' => $form_state['values']['replace'],
);
}
function vbo_search_and_replace_action(&$node, $context) {
$node_changed = FALSE;
$replacements = array(
'@node_type' => $node->type,
'@node_title' => $node->title,
);
$properties = vbo_search_and_replace_node_properties();
$settings = $context['search_and_replace_settings'];
foreach ($context['fields'] as $field_name => $field_label) {
$replacements['@field_label'] = $field_label;
if (property_exists($node, $field_name)) {
$replaced = '';
if (array_key_exists($field_name, $properties)) {
$replaced = _vbo_search_and_replace_search_and_replace($context['search'], $context['replace'], $node->{$field_name}, $settings);
if ($node->{$field_name} != $replaced) {
$replacements['@old'] = $node->{$field_name};
$replacements['@new'] = $replaced;
$node->{$field_name} = $replaced;
$node_changed = TRUE;
drupal_set_message(t('Field @field_label in @node_type: @node_title changed from: "@old" to "@new"', $replacements));
}
else {
drupal_set_message(t('Field @field_label in @node_type: @node_title skipped', $replacements));
}
}
else {
foreach ($node->{$field_name} as $delta => $item) {
$replaced = _vbo_search_and_replace_search_and_replace($context['search'], $context['replace'], $node->{$field_name}[$delta]['value'], $settings);
if ($node->{$field_name}[$delta]['value'] != $replaced) {
$replacements['@old'] = $node->{$field_name}[$delta]['value'];
$replacements['@new'] = $replaced;
$node->{$field_name}[$delta]['value'] = $replaced;
$node_changed = TRUE;
drupal_set_message(t('Field @field_label in @node_type: @node_title changed from: "@old" to "@new"', $replacements));
}
else {
drupal_set_message(t('Field @field_label in @node_type: @node_title skipped', $replacements));
}
}
}
}
}
if ($node_changed) {
node_save($node);
}
}
function vbo_search_and_replace_action_views_bulk_operations_form($settings) {
$fields = array(
VBO_SNR_NO_FIELD_EXLUSIONS => t('- No Exclusions -'),
) + vbo_search_and_replace_node_properties();
$form = array();
foreach (content_fields() as $field) {
if ($field['widget']['type'] == 'text_textarea' || $field['widget']['type'] == 'text_textfield') {
$fields[$field['type_name']][$field['field_name']] = $field['widget']['label'] . ' (' . $field['field_name'] . ')';
}
}
foreach ($fields as $type => $field) {
if (count($fields[$type]) > 1) {
sort($fields[$type]);
}
}
if (empty($settings['exclude_fields'])) {
$settings['exclude_fields'] = array(
VBO_SNR_NO_FIELD_EXLUSIONS,
);
}
if (empty($settings['selection_widget'])) {
$settings['widget'] = 'checkboxes';
}
if (empty($settings['checkbox_columns'])) {
$settings['checkbox_columns'] = 1;
}
$form['selection_widget'] = array(
'#type' => 'select',
'#title' => t('Widget for selecting fields'),
'#options' => array(
'select' => 'Select List',
'checkboxes' => 'Checkboxes',
),
'#description' => t('Select the widget that will be presented to the user to select which fields to perform the search and replace on'),
'#default_value' => $settings['selection_widget'],
);
$form['checkbox_columns'] = array(
'#type' => 'checkbox',
'#title' => t('Display checkboxes inline'),
'#description' => t('If you have checkboxes selected for the widget, this option will add a little bit of styling to the page to display the checkboxes inline as columns.'),
'#default_value' => $settings['checkbox_columns'],
);
$form['exclude_fields'] = array(
'#type' => 'select',
'#title' => t('Exclude fields'),
'#options' => $fields,
'#multiple' => TRUE,
'#size' => 20,
'#description' => t('Select which field(s) to exclude from search and replace. NOTE: Only textfields and textareas that belong to node types that are selected in the view will be available for search and replace, this list is simply a way to further exclude fields from being available for search and replace.'),
'#default_value' => $settings['exclude_fields'],
);
return $form;
}
function vbo_search_and_replace_action_views_bulk_operations_form_validate($form, $form_state) {
if (empty($form_state['values']['exclude_fields'])) {
form_set_error($form_state['values']['_error_element_base'] . 'exclude_fields', t('You must select at least one item in the list. Select "- No Exlusions -" if you wish to make all fields available for search and replace.'));
}
}
function vbo_search_and_replace_action_views_bulk_operations_form_default_settings() {
$settings['exclude_fields'] = array(
VBO_SNR_NO_FIELD_EXLUSIONS,
);
$settings['selection_widget'] = 'checkboxes';
$settings['checkbox_columns'] = 1;
return $settings;
}
function vbo_search_and_replace_node_properties() {
return array(
'title' => 'Title',
'body' => 'Body',
'teaser' => 'Teaser',
);
}
function vbo_search_and_replace_get_available_fields($context, $nested = FALSE) {
$options = array(
VBO_ACTION_FIELDS_ALL => "*All Fields",
) + vbo_search_and_replace_node_properties();
if (isset($context['selection']) && isset($context['view'])) {
$nids = array_map('_views_bulk_operations_get_oid', $context['selection'], array_fill(0, count($context['selection']), $context['view']->base_field));
$result = db_query("SELECT DISTINCT type FROM {node} WHERE nid IN (%s)", implode(',', $nids));
}
else {
$result = db_query("SELECT type from {node_type}");
}
$fields = array();
while ($type = db_result($result)) {
$type_info = content_types($type);
$fields += $type_info['fields'];
}
foreach ($fields as $field) {
if ($field['widget']['type'] != 'text_textarea' && $field['widget']['type'] != 'text_textfield') {
continue;
}
if (module_exists('content_permissions') && in_array('edit ' . $field['field_name'], module_invoke('content_permissions', 'perm')) && !user_access('edit ' . $field['field_name'])) {
continue;
}
if (!empty($context['settings']['exclude_fields']) && in_array($field['field_name'], $context['settings']['exclude_fields']) && !in_array(VBO_SNR_NO_FIELD_EXLUSIONS, $context['settings']['exclude_fields'])) {
continue;
}
if ($nested) {
$options[$field['type_name']][$field['field_name']] = $field['widget']['label'];
}
else {
$options[$field['field_name']] = $field['widget']['label'];
}
}
if ($nested) {
foreach ($options as $type => $fields) {
if (is_array($options[$type])) {
asort($options[$type]);
}
}
}
else {
asort($options);
}
return $options;
}
function _vbo_search_and_replace_search_and_replace($search, $replace, $subject, $settings = array()) {
$settings['search_prefix'] = isset($settings['search_prefix']) ? $settings['search_prefix'] : '';
$settings['search_suffix'] = isset($settings['search_suffix']) ? $settings['search_suffix'] : '';
$settings['case_sensitive'] = isset($settings['case_sensitive']) ? $settings['case_sensitive'] : '';
$settings['exact_match'] = isset($settings['exact_match']) ? $settings['exact_match'] : '';
$search = $settings['search_prefix'] . $search . $settings['search_suffix'];
$replace = $settings['search_prefix'] . $replace . $settings['search_suffix'];
if ($settings['exact_match']) {
if ($subject === $search) {
$subject = $replace;
}
}
else {
if ($settings['case_sensitive']) {
if (strpos($subject, $search) !== FALSE) {
$subject = str_replace($search, $replace, $subject);
}
}
else {
if (strpos(strtolower($subject), strtolower($search)) !== FALSE) {
$subject = str_ireplace($search, $replace, $subject);
}
}
}
return $subject;
}