| Commit | Line | Data |
|---|---|---|
| c573bbbd | 1 | <?php |
| c573bbbd KS |
2 | /** |
| 3 | * @file | |
| 2d9c2350 KS |
4 | * Allows administrators to use php code snippets to |
| 5 | * define allowed values or default values. The snippets | |
| 6 | * are stored in a database table and retrieved in | |
| 7 | * callback functions. | |
| c573bbbd KS |
8 | */ |
| 9 | ||
| 10 | /** | |
| c573bbbd KS |
11 | * Implementation of hook_perm(). |
| 12 | */ | |
| 68d24e95 | 13 | function cck_permission() { |
| ecc284c7 YC |
14 | return array( |
| 15 | // TODO : simplify machine name and update existing perms ? | |
| 16 | 'Use PHP input for field settings (dangerous - grant with care)' => array( | |
| 17 | 'title' => t('Use PHP input for field settings'), | |
| 18 | 'description' => t('Enter PHP code in the field for the field settings that allow it. Warning: Give to trusted roles only; this permission has security implications.'), | |
| 19 | ), | |
| 20 | ); | |
| c573bbbd KS |
21 | } |
| 22 | ||
| 23 | /** | |
| 78cc2178 KS |
24 | * Add fields to allowed values form to allow |
| 25 | * users to input a function or a PHP snippet | |
| 26 | * that will return the allowed values. | |
| c573bbbd | 27 | */ |
| 78cc2178 KS |
28 | function cck_form_alter(&$form, $form_state, $form_id) { |
| 29 | switch ($form_id) { | |
| 30 | case 'field_ui_field_settings_form': | |
| 31 | $field = field_info_field($form['field']['field_name']['#value']); | |
| 32 | if ($field['module'] == 'list') { | |
| 41d887a5 YC |
33 | // @todo : core should put that for us. |
| 34 | $form['#field'] = $field; | |
| 78cc2178 | 35 | cck_allowed_values_form($form, $form_state, $field); |
| 2d9c2350 | 36 | $form['#validate'][] = 'cck_allowed_values_validate'; |
| 78cc2178 KS |
37 | } |
| 38 | break; | |
| 39 | case 'field_ui_field_edit_form': | |
| 40 | $field = $form['#field']; | |
| 41 | if ($field['module'] == 'list') { | |
| 2d9c2350 | 42 | cck_default_value_form($form, $form_state, $field); |
| 78cc2178 | 43 | cck_allowed_values_form($form, $form_state, $field); |
| 2d9c2350 KS |
44 | $form['#validate'][] = 'cck_allowed_values_validate'; |
| 45 | $form['#validate'][] = 'cck_default_value_validate'; | |
| 78cc2178 KS |
46 | } |
| 47 | break; | |
| 48 | } | |
| c573bbbd KS |
49 | } |
| 50 | ||
| 41e5083c KS |
51 | /** |
| 52 | * Add fields to allowed values form to allow | |
| 53 | * users to input a function or a PHP snippet | |
| 54 | * that will return the allowed values. | |
| 55 | */ | |
| d5d3500b | 56 | function cck_allowed_values_form(&$form, $form_state, $field) { |
| 41e5083c KS |
57 | $php_code = cck_field_get_setting('allowed_values_php', 'field', $field); |
| 58 | $allowed_values_function = $form['field']['settings']['allowed_values_function']['#value']; | |
| 59 | if (!empty($php_code)) { | |
| 60 | $allowed_values_function = 'cck_allowed_values_php'; | |
| 61 | } | |
| d5d3500b | 62 | |
| 41e5083c KS |
63 | // Add a field where users can specify some PHP |
| 64 | // code that will return the allowed values list. | |
| 41e5083c KS |
65 | $form['field']['settings']['allowed_values_php'] = array( |
| 66 | '#access' => user_access('Use PHP input for field settings (dangerous - grant with care)'), | |
| 67 | '#type' => 'textarea', | |
| 68 | '#title' => t('Allowed values PHP code'), | |
| 69 | '#default_value' => $php_code, | |
| 41d887a5 YC |
70 | '#description' => t('Advanced usage only: PHP code that returns an array of allowed values. Should not include <?php ?> delimiters. If this field is filled out, the value returned by this code will be used as the response to the function <strong>cck_allowed_values_php</strong> and will override any other allowed values list or function specified above. Expected format: <pre>!sample</pre>', array( |
| 71 | '!sample' => t("return array(\n value_1 => label_1,\n value_2 => label_2\n ...\n);"), | |
| 41e5083c | 72 | )), |
| 41d887a5 | 73 | '#weight' => 5, |
| 41e5083c | 74 | ); |
| d5d3500b | 75 | |
| 41d887a5 YC |
76 | // Add a field where users can specify a function |
| 77 | // to return the allowed values list. | |
| 78 | $form['field']['settings']['allowed_values_function'] = array( | |
| 79 | '#type' => 'textfield', | |
| 80 | '#title' => t('Allowed values function'), | |
| 81 | '#default_value' => $allowed_values_function, | |
| 82 | '#description' => t('The name of a function that will return the allowed values list.'), | |
| 83 | '#weight' => 6, | |
| 84 | '#states' => array( | |
| 85 | 'visible' => array( | |
| 86 | ':input[name="field[settings][allowed_values_php]"]' => array('empty' => TRUE), | |
| 87 | ), | |
| 88 | ) | |
| 89 | ); | |
| 41e5083c KS |
90 | } |
| 91 | ||
| 2d9c2350 KS |
92 | /** |
| 93 | * Add fields to default value form to allow | |
| 94 | * users to input a function or a PHP snippet | |
| 95 | * that will return the default values. | |
| 96 | */ | |
| d5d3500b | 97 | function cck_default_value_form(&$form, $form_state, $field) { |
| 2d9c2350 | 98 | $instance = field_info_instance($form['instance']['entity_type']['#value'], $field['field_name'], $form['instance']['bundle']['#value']); |
| 41d887a5 YC |
99 | $default_value_function = !empty($instance['default_value_function']) ? $instance['default_value_function'] : ''; |
| 100 | $php_code = cck_field_get_setting('default_value_php', 'instance', $field, $instance); | |
| 2d9c2350 KS |
101 | if (!empty($php_code)) { |
| 102 | $default_value_function = 'cck_default_value_php'; | |
| 103 | } | |
| d5d3500b | 104 | |
| 2d9c2350 KS |
105 | // Add a field where users can specify some PHP |
| 106 | // code that will return the default value. | |
| 01e7cc15 | 107 | module_load_include('install', $field['module']); |
| d5d3500b YC |
108 | $schema = module_invoke($field['module'], 'field_schema', $field); |
| 109 | $columns = array_keys($schema['columns']); | |
| 2d9c2350 | 110 | $sample = t("return array(\n 0 => array(@columns),\n // You'll usually want to stop here. Provide more values\n // if you want your 'default value' to be multi-valued:\n 1 => array(@columns),\n 2 => ...\n);", array('@columns' => implode(', ', $columns))); |
| d5d3500b | 111 | |
| 2d9c2350 KS |
112 | $form['instance']['default_value_widget']['default_value_php'] = array( |
| 113 | '#access' => user_access('Use PHP input for field settings (dangerous - grant with care)'), | |
| 114 | '#type' => 'textarea', | |
| 115 | '#title' => t('Default value PHP code'), | |
| 116 | '#default_value' => $php_code, | |
| 117 | '#description' => t('Advanced usage only: PHP code that returns a default value. Should not include <?php ?> delimiters. If this field is filled out, the value returned by this code will be used as the response to the function <strong>cck_default_value_php</strong> and will override any other default value or function specified above. Expected format: <pre>!sample</pre>To figure out the expected format, you can use the <em>devel load</em> tab provided by <a href="@link_devel">devel module</a> on a content page.', array( | |
| 118 | '!sample' => $sample, | |
| 119 | '@link_devel' => 'http://www.drupal.org/project/devel', | |
| 120 | )), | |
| 41d887a5 YC |
121 | '#weight' => 5, |
| 122 | '#parents' => array('instance', 'default_value_php'), | |
| 2d9c2350 | 123 | ); |
| d5d3500b | 124 | |
| 41d887a5 YC |
125 | // Add a field where users can specify a function |
| 126 | // to return the default value. | |
| 127 | $form['instance']['default_value_widget']['default_value_function'] = array( | |
| 128 | '#type' => 'textfield', | |
| 129 | '#title' => t('Default value function'), | |
| 130 | '#default_value' => $default_value_function, | |
| 131 | '#description' => t('The name of a function that will return the default value.'), | |
| 132 | '#states' => array( | |
| 133 | 'visible' => array( | |
| 134 | ':input[name="instance[default_value_php]"]' => array('empty' => TRUE), | |
| 135 | ), | |
| 136 | ), | |
| 137 | '#weight' => 6, | |
| 138 | '#parents' => array('instance', 'default_value_function'), | |
| 139 | ); | |
| 2d9c2350 KS |
140 | } |
| 141 | ||
| 142 | /** | |
| 143 | * Validation handler to store php allowed values. | |
| 144 | */ | |
| 41d887a5 | 145 | function cck_allowed_values_validate(&$form, &$form_state) { |
| d5d3500b YC |
146 | $field = $form['#field']; |
| 147 | ||
| 2d9c2350 KS |
148 | $php_code = $form_state['values']['field']['settings']['allowed_values_php']; |
| 149 | $allowed_values_function = $form_state['values']['field']['settings']['allowed_values_function']; | |
| 150 | if (!empty($php_code)) { | |
| 151 | $allowed_values_function = 'cck_allowed_values_php'; | |
| 152 | } | |
| 153 | elseif (empty($php_code) && $allowed_values_function == 'cck_allowed_values_php') { | |
| 154 | $allowed_values_function = ''; | |
| 155 | } | |
| 41d887a5 YC |
156 | form_set_value($form['field']['settings']['allowed_values_function'], $allowed_values_function, $form_state); |
| 157 | // @todo This should be done at submit time, not validate. | |
| 2d9c2350 KS |
158 | cck_field_set_setting('allowed_values_php', 'field', $php_code, $field); |
| 159 | } | |
| 160 | ||
| 161 | /** | |
| 162 | * Validation handler to store php default values. | |
| 163 | */ | |
| 41d887a5 | 164 | function cck_default_value_validate(&$form, &$form_state) { |
| d5d3500b YC |
165 | $field = $form['#field']; |
| 166 | $instance = $form['#instance']; | |
| 167 | ||
| 2d9c2350 | 168 | $default_value_function = $form_state['values']['instance']['default_value_function']; |
| 41d887a5 | 169 | $php_code = $form_state['values']['instance']['default_value_php']; |
| 2d9c2350 KS |
170 | if (!empty($php_code)) { |
| 171 | $default_value_function = 'cck_default_value_php'; | |
| 172 | } | |
| 173 | elseif (empty($php_code) && $default_value_function == 'cck_default_value_php') { | |
| 174 | $default_value_function = ''; | |
| 175 | } | |
| 41d887a5 YC |
176 | form_set_value($form['instance']['default_value_widget']['default_value_function'], $default_value_function, $form_state); |
| 177 | // @todo This should be done at submit time, not validate. | |
| d5d3500b | 178 | cck_field_set_setting('default_value_php', 'instance', $php_code, $field, $instance); |
| 2d9c2350 KS |
179 | } |
| 180 | ||
| 181 | ||
| c573bbbd | 182 | function cck_debug_field_info() { |
| 8376bb8b | 183 | if (function_exists('dsm')) { |
| de7b1259 YC |
184 | module_load_include('inc', 'field', 'field.info'); |
| 185 | dsm(_field_info_collate_types()); | |
| 186 | dsm(_field_info_collate_fields()); | |
| 187 | return ''; | |
| 188 | } | |
| 189 | else { | |
| 190 | return t('You need to enable devel.module to see this page'); | |
| 191 | } | |
| c573bbbd KS |
192 | } |
| 193 | ||
| 194 | /** | |
| c6189ea2 KS |
195 | * We store all settings in a flat text field, but some settings |
| 196 | * will be arrays that need to be serialized and unserialized, | |
| 197 | * like the default_value. | |
| 198 | */ | |
| 199 | function cck_serialized_settings() { | |
| 200 | return array('default_value'); | |
| 201 | } | |
| 202 | ||
| 203 | /** | |
| 204 | * Helper function to retrieve field settings stored by CCK. | |
| fda5a014 | 205 | * |
| c6189ea2 KS |
206 | * CCK uses the 'cck_field_settings' table to store custom settings |
| 207 | * not used by core. | |
| fda5a014 | 208 | * |
| 99d33fb1 | 209 | * Field settings will have no $instance nor a db bundle column. |
| c6189ea2 | 210 | */ |
| b338b91f | 211 | function cck_field_get_setting($setting, $setting_type, $field, $instance = NULL, $langcode = LANGUAGE_NONE) { |
| 99d33fb1 KS |
212 | if ($setting_type == 'field' || empty($instance)) { |
| 213 | $value = db_select('cck_field_settings', 'fs')->fields('fs', array('setting_option')) | |
| 78cc2178 | 214 | ->condition('fs.field_name', $field['field_name']) |
| 99d33fb1 KS |
215 | ->condition('fs.setting', $setting) |
| 216 | ->condition('fs.setting_type', $setting_type) | |
| fda5a014 | 217 | ->execute()->fetchField(); |
| 99d33fb1 KS |
218 | } |
| 219 | else { | |
| 220 | $value = db_select('cck_field_settings', 'fs')->fields('fs', array('setting_option')) | |
| 99d33fb1 | 221 | ->condition('fs.field_name', $field['field_name']) |
| 78cc2178 | 222 | ->condition('fs.entity_type', $instance['entity_type']) |
| 99d33fb1 | 223 | ->condition('fs.bundle', $instance['bundle']) |
| b338b91f | 224 | ->condition('fs.language', $langcode) |
| 78cc2178 KS |
225 | ->condition('fs.setting', $setting) |
| 226 | ->condition('fs.setting_type', $setting_type) | |
| 99d33fb1 KS |
227 | ->execute()->fetchField(); |
| 228 | } | |
| fda5a014 | 229 | |
| c6189ea2 KS |
230 | if (in_array($setting, cck_serialized_settings())) { |
| 231 | $value = unserialize($value); | |
| 232 | } | |
| 233 | return $value; | |
| 234 | } | |
| 235 | ||
| 236 | /** | |
| 237 | * Helper function to set field settings stored by CCK. | |
| fda5a014 | 238 | * |
| c6189ea2 KS |
239 | * CCK uses the 'cck_field_settings' table to store custom settings |
| 240 | * not used by core. | |
| fda5a014 | 241 | * |
| 99d33fb1 | 242 | * Field settings will have no $instance nor a db bundle column. |
| c6189ea2 | 243 | */ |
| b338b91f | 244 | function cck_field_set_setting($setting, $setting_type, $value, $field, $instance = NULL, $langcode = LANGUAGE_NONE) { |
| c6189ea2 | 245 | // Delete any prior values. |
| 99d33fb1 | 246 | $bundle = ($setting_type == 'field' || empty($instance)) ? NULL : $instance['bundle']; |
| a8397343 | 247 | $entity_type = ($setting_type == 'field' || empty($instance)) ? NULL : $instance['entity_type']; |
| 99d33fb1 KS |
248 | if ($setting_type == 'field' || empty($instance)) { |
| 249 | db_delete('cck_field_settings') | |
| 250 | ->condition('field_name', $field['field_name']) | |
| 251 | ->condition('setting', $setting) | |
| 252 | ->condition('setting_type', $setting_type) | |
| 253 | ->execute(); | |
| 254 | } | |
| 255 | else { | |
| 256 | db_delete('cck_field_settings') | |
| 257 | ->condition('field_name', $field['field_name']) | |
| a8397343 | 258 | ->condition('entity_type', $entity_type) |
| 99d33fb1 | 259 | ->condition('bundle', $bundle) |
| b338b91f | 260 | ->condition('language', $langcode) |
| 99d33fb1 KS |
261 | ->condition('setting', $setting) |
| 262 | ->condition('setting_type', $setting_type) | |
| 263 | ->execute(); | |
| 264 | } | |
| c6189ea2 KS |
265 | // Create the new values. |
| 266 | if (in_array($setting, cck_serialized_settings())) { | |
| 267 | $value = serialize($value); | |
| 268 | } | |
| 269 | $record = array( | |
| 270 | 'field_name' => $field['field_name'], | |
| a8397343 | 271 | 'entity_type' => $entity_type, |
| 99d33fb1 | 272 | 'bundle' => $bundle, |
| b338b91f | 273 | 'language' => $langcode, |
| c6189ea2 KS |
274 | 'setting' => $setting, |
| 275 | 'setting_option' => $value, | |
| 276 | 'setting_type' => $setting_type, | |
| 277 | ); | |
| 278 | $primary_keys = array(); | |
| 279 | drupal_write_record('cck_field_settings', $record, $primary_keys); | |
| 280 | } | |
| 281 | ||
| 282 | /** | |
| b338b91f KS |
283 | * Callback to return default value constructed |
| 284 | * from php code snippet. | |
| 285 | */ | |
| 286 | function cck_default_value_php($entity_type, $entity, $field, $instance, $langcode = LANGUAGE_NONE) { | |
| 287 | $default_value = array(); | |
| 288 | ob_start(); | |
| 289 | $result = eval(cck_field_get_setting('default_value_php', 'instance', $field, $instance, $langcode, $flatten = TRUE)); | |
| 41d887a5 | 290 | ob_end_clean(); |
| b338b91f | 291 | if (is_array($result)) { |
| 41d887a5 | 292 | $default_value = $result; |
| b338b91f | 293 | } |
| 41d887a5 | 294 | return $default_value; |
| b338b91f KS |
295 | } |
| 296 | ||
| 297 | /** | |
| 78cc2178 KS |
298 | * Callback to return allowed values constructed |
| 299 | * from php code snippet. | |
| 300 | */ | |
| 301 | function cck_allowed_values_php($field, $flatten = TRUE) { | |
| 302 | $allowed_values = array(); | |
| 303 | ob_start(); | |
| 304 | $result = eval(cck_field_get_setting('allowed_values_php', 'field', $field)); | |
| 41d887a5 | 305 | ob_end_clean(); |
| 78cc2178 KS |
306 | if (is_array($result)) { |
| 307 | if ($flatten) { | |
| 308 | $result = cck_array_flatten($result); | |
| 309 | } | |
| 310 | $allowed_values = $result; | |
| 311 | } | |
| 78cc2178 KS |
312 | return $allowed_values; |
| 313 | } | |
| 314 | ||
| 315 | /** | |
| 316 | * Helper function to flatten an array of allowed values. | |
| 317 | * | |
| 318 | * @param $array | |
| 319 | * A single or multidimensional array. | |
| 320 | * @return | |
| 321 | * A flattened array. | |
| 322 | */ | |
| 323 | function cck_array_flatten($array) { | |
| 324 | $result = array(); | |
| 325 | if (is_array($array)) { | |
| 326 | foreach ($array as $key => $value) { | |
| 327 | if (is_array($value)) { | |
| 328 | $result += cck_array_flatten($value); | |
| 329 | } | |
| 330 | else { | |
| 331 | $result[$key] = $value; | |
| 332 | } | |
| 333 | } | |
| 334 | } | |
| 335 | return $result; | |
| 336 | } | |
| 337 | ||
| 338 | /** | |
| 78cc2178 | 339 | * Implements hook_content_migrate_field_alter(). |
| d5d3500b | 340 | * |
| 78cc2178 KS |
341 | * Use this to tweak the conversion of field settings |
| 342 | * from the D6 style to the D7 style for specific | |
| 343 | * situations not handled by basic conversion, | |
| 344 | * as when field types or settings are changed. | |
| d5d3500b | 345 | * |
| 78cc2178 KS |
346 | * $field_value['widget_type'] is available to |
| 347 | * see what widget type was originally used. | |
| bccc8ae0 | 348 | */ |
| 78cc2178 | 349 | function cck_content_migrate_field_alter(&$field_value) { |
| f0fdcdbf | 350 | if (!empty($field_value['settings']['allowed_values_php'])) { |
| 78cc2178 KS |
351 | $field_value['settings']['allowed_values_function'] = 'cck_allowed_values_php'; |
| 352 | cck_field_set_setting('allowed_values_php', 'field', $field_value['settings']['allowed_values_php'], $field_value); | |
| 353 | } | |
| b338b91f KS |
354 | } |
| 355 | ||
| 356 | /** | |
| 357 | * Implements hook_content_migrate_instance_alter(). | |
| d5d3500b | 358 | * |
| b338b91f KS |
359 | * Use this to tweak the conversion of instance or widget settings |
| 360 | * from the D6 style to the D7 style for specific | |
| 361 | * situations not handled by basic conversion, as when | |
| 362 | * formatter or widget names or settings are changed. | |
| 363 | */ | |
| 364 | function cck_content_migrate_instance_alter(&$instance_value) { | |
| 365 | if (!empty($instance_value['settings']['default_value_php'])) { | |
| 366 | $field_value = content_migrate_get_field_values($instance_value['field_name']); | |
| 367 | $instance_value['settings']['default_value_function'] = 'cck_default_value_php'; | |
| 368 | cck_field_set_setting('default_value_php', 'instance', $instance_value['settings']['default_value_php'], $field_value, $instance_value); | |
| 369 | } | |
| 370 | } |