| Commit | Line | Data |
|---|---|---|
| d93afe47 DP |
1 | <?php |
| 2 | // $Id$ | |
| 0da420f9 JP |
3 | /** |
| 4 | * @file | |
| 5 | * FileField: Defines a CCK file field type. | |
| 6 | * | |
| 7 | * Uses content.module to store the fid and field specific metadata, | |
| 8 | * and Drupal's {files} table to store the actual file data. | |
| 9 | */ | |
| d93afe47 | 10 | |
| 3f29854f | 11 | include_once('field_file.inc'); |
| adb434fc | 12 | |
| d93afe47 DP |
13 | /** |
| 14 | * Implementation of hook_install(). | |
| 15 | */ | |
| 16 | function filefield_install() { | |
| e7c83331 | 17 | drupal_load('module', 'content'); |
| adb434fc JP |
18 | content_notify('install', 'filefield'); |
| 19 | } | |
| 20 | ||
| 21 | /** | |
| 0da420f9 JP |
22 | * Implementation of hook_uninstall(). |
| 23 | */ | |
| adb434fc | 24 | function filefield_uninstall() { |
| e7c83331 | 25 | drupal_load('module', 'content'); |
| adb434fc | 26 | content_notify('uninstall', 'filefield'); |
| d93afe47 | 27 | } |
| d7762f12 | 28 | |
| adb434fc | 29 | /** |
| 0da420f9 JP |
30 | * Implementation of hook_enable(). |
| 31 | */ | |
| adb434fc | 32 | function filefield_enable() { |
| e7c83331 | 33 | drupal_load('module', 'content'); |
| adb434fc JP |
34 | content_notify('enable', 'filefield'); |
| 35 | } | |
| 36 | ||
| 37 | /** | |
| 0da420f9 JP |
38 | * Implementation of hook_disable(). |
| 39 | */ | |
| adb434fc | 40 | function filefield_disable() { |
| e7c83331 | 41 | drupal_load('module', 'content'); |
| adb434fc JP |
42 | content_notify('disable', 'filefield'); |
| 43 | } | |
| 44 | ||
| 4589bd94 | 45 | /** |
| e3623331 NH |
46 | * Implementation of hook_requirements(). |
| 47 | * | |
| 48 | * Display information about getting upload progress bars working. | |
| 49 | */ | |
| 50 | function filefield_requirements($phase) { | |
| 51 | $requirements = array(); | |
| 52 | // Ensure translations don't break at install time | |
| 53 | $t = get_t(); | |
| 54 | ||
| 55 | // Report Drupal version | |
| 56 | if ($phase == 'runtime') { | |
| 57 | $implementation = filefield_progress_implementation(); | |
| df3c897f NH |
58 | $apache = strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== FALSE; |
| 59 | $fastcgi = strpos($_SERVER['SERVER_SOFTWARE'], 'mod_fastcgi') !== FALSE || strpos($_SERVER["SERVER_SOFTWARE"], 'mod_fcgi') !== FALSE; | |
| e3623331 | 60 | $php_52 = version_compare(phpversion(), '5.2.0', '>'); |
| 4c56b6af | 61 | $description = NULL; |
| e3623331 NH |
62 | if (!$apache || !$php_52) { |
| 63 | $value = $t('Not enabled'); | |
| 64 | $description = $t('Your server is not capable of displaying file upload progress. File upload progress requires PHP 5.2 and an Apache server.'); | |
| 65 | $severity = REQUIREMENT_INFO; | |
| 66 | } | |
| df3c897f NH |
67 | elseif ($fastcgi) { |
| 68 | $value = $t('Not enabled'); | |
| 69 | $description = $t('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php and not as FastCGI.'); | |
| 70 | $severity = REQUIREMENT_INFO; | |
| 71 | } | |
| e3623331 NH |
72 | elseif (!$implementation && extension_loaded('apc')) { |
| 73 | $value = $t('Not enabled'); | |
| 74 | $description = $t('Your server is capable of displaying file upload progress through APC, but it is not enabled. Add <code>apc.rfc1867 = 1</code> to your php.ini configuration. Alternatively, it is recommended to use <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>, which supports more than one simultaneous upload.'); | |
| a11bb496 | 75 | $severity = REQUIREMENT_INFO; |
| e3623331 NH |
76 | } |
| 77 | elseif (!$implementation) { | |
| 78 | $value = $t('Not enabled'); | |
| be1951d5 | 79 | $description = t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a> (preferred) or to install <a href="http://us2.php.net/apc">APC</a>.'); |
| a11bb496 | 80 | $severity = REQUIREMENT_INFO; |
| e3623331 NH |
81 | } |
| 82 | elseif ($implementation == 'apc') { | |
| 83 | $value = $t('Enabled (<a href="http://php.net/manual/en/apc.configuration.php#ini.apc.rfc1867">APC RFC1867</a>)'); | |
| a24e2e78 | 84 | $description = t('Your server is capable of displaying file upload progress using APC RFC1867. Note that only one upload at a time is supported. It is recommended to use the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a> if possible.'); |
| e3623331 NH |
85 | $severity = REQUIREMENT_OK; |
| 86 | } | |
| 87 | elseif ($implementation == 'uploadprogress') { | |
| 88 | $value = $t('Enabled (<a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>)'); | |
| 89 | $severity = REQUIREMENT_OK; | |
| 90 | } | |
| 91 | $requirements['filefield_progress'] = array( | |
| 92 | 'title' => $t('Upload progress'), | |
| 93 | 'value' => $value, | |
| 94 | 'severity' => $severity, | |
| 95 | 'description' => $description, | |
| 96 | ); | |
| 97 | } | |
| 98 | ||
| 99 | return $requirements; | |
| 100 | } | |
| 101 | ||
| 102 | /** | |
| 9f375d7f | 103 | * Implementation of hook_update_last_removed(). |
| 4589bd94 | 104 | */ |
| 9f375d7f NH |
105 | function filefield_update_last_removed() { |
| 106 | return 3; | |
| 4589bd94 | 107 | } |
| 3d23d9df | 108 | |
| 9f375d7f NH |
109 | /** |
| 110 | * Upgrade FileField to Drupal 6. | |
| 111 | */ | |
| 3d23d9df | 112 | function filefield_update_6001() { |
| e82b6a18 | 113 | if ($abort = content_check_update('filefield')) { |
| 114 | return $abort; | |
| 115 | } | |
| 116 | ||
| 1a05ff77 | 117 | $ret = array(); |
| e76d77f0 | 118 | include_once(drupal_get_path('module', 'content') .'/includes/content.admin.inc'); |
| 28b1c58e | 119 | |
| 20649e70 NH |
120 | // Rename the field type from file to filefield. adhere to module namespace. |
| 121 | $ret[] = update_sql("UPDATE {content_node_field} SET type = 'filefield', module = 'filefield', active = 1 WHERE type = 'file'"); | |
| 122 | // Rename default widget to filefield_widget. adhere to module namespace. | |
| 123 | $ret[] = update_sql("UPDATE {content_node_field_instance} SET widget_type = 'filefield_widget', widget_module = 'filefield', widget_active = 1 WHERE widget_type = 'file'"); | |
| 28b1c58e | 124 | |
| 20649e70 | 125 | // Update list default value and force list settings. |
| 28b1c58e DP |
126 | $result = db_query("SELECT * FROM {content_node_field} WHERE type = 'filefield'"); |
| 127 | while ($field = db_fetch_object($result)) { | |
| e76d77f0 | 128 | $updated = FALSE; |
| 28b1c58e DP |
129 | $field_settings = unserialize($field->global_settings); |
| 130 | if (!isset($field_settings['list_default']) || !is_numeric($field_settings['list_default'])) { | |
| 131 | $field_settings['list_default'] = 1; | |
| e76d77f0 | 132 | $updated = TRUE; |
| 28b1c58e | 133 | } |
| 20649e70 NH |
134 | |
| 135 | // Set behavior to match old force_list behavior. | |
| 28b1c58e DP |
136 | if (!empty($field_settings['force_list'])) { |
| 137 | $field_settings['list_default'] = 1; | |
| 7e784adc | 138 | $field_settings['force_list_default'] = 1; |
| e76d77f0 | 139 | $updated = TRUE; |
| 28b1c58e DP |
140 | } |
| 141 | if ($updated) { | |
| 9f375d7f | 142 | db_query("UPDATE {content_node_field} SET global_settings = '%s' WHERE field_name = '%s'", serialize($field_settings), $field->field_name); |
| 28b1c58e DP |
143 | } |
| 144 | } | |
| 145 | ||
| 20649e70 NH |
146 | // Re-enable all the FileFields on the site. |
| 147 | content_associate_fields('filefield'); | |
| 28b1c58e | 148 | |
| 20649e70 NH |
149 | // Build a list of fields that need data updating. |
| 150 | $fields = array(); | |
| 151 | foreach (content_types_install() as $type_name => $type_fields) { | |
| 152 | foreach ($type_fields as $field) { | |
| 153 | if ($field['type'] == 'filefield') { | |
| 154 | // We only process a given field once. | |
| 155 | $fields[$field['field_name']] = $field; | |
| 156 | } | |
| 157 | } | |
| 158 | } | |
| 159 | ||
| 6c32f1e1 | 160 | // Update database storage (add data column, remove description, set NOT NULL). |
| e76d77f0 | 161 | foreach ($fields as $field) { |
| 3d23d9df | 162 | $new_field = $field; |
| 6c32f1e1 NH |
163 | |
| 164 | // Setup the previous definition. | |
| 165 | $field['columns']['description'] = array('type' => 'varchar'); | |
| 166 | $field['columns']['fid']['not null'] = TRUE; | |
| 167 | $field['columns']['list']['not null'] = TRUE; | |
| 168 | unset($field['columns']['data']); | |
| 169 | ||
| 170 | // Setup the new definition. | |
| 171 | $new_field['columns']['data'] = array('type' => 'text', 'serialize' => TRUE); | |
| 172 | $new_field['columns']['fid']['not null'] = FALSE; | |
| 173 | $new_field['columns']['list']['size'] = 'tiny'; | |
| 174 | $new_field['columns']['list']['not null'] = FALSE; | |
| 175 | unset($new_field['columns']['description']); | |
| 176 | ||
| 3d23d9df DP |
177 | content_alter_db($field, $new_field); |
| 178 | } | |
| 7e784adc | 179 | |
| c7981f82 DP |
180 | // Build a batch that migrates the data in each filefield |
| 181 | $batch = array( | |
| 182 | 'title' => t('Migrating filefield values'), | |
| 183 | 'operations' => array(), | |
| 184 | 'file' => drupal_get_path('module', 'filefield') .'/filefield.install', | |
| 185 | ); | |
| 20649e70 NH |
186 | foreach ($fields as $field_name => $field) { |
| 187 | if ($field['type'] == 'filefield') { | |
| 188 | $batch['operations'][] = array('_filefield_update_6001_move_operation', array($field)); | |
| 189 | $batch['operations'][] = array('_filefield_update_6001_drop_operation', array($field)); | |
| c7981f82 DP |
190 | } |
| 191 | } | |
| 192 | batch_set($batch); | |
| 193 | ||
| 28b1c58e | 194 | |
| 20649e70 | 195 | // Clear caches. |
| e76d77f0 NH |
196 | cache_clear_all('*', content_cache_tablename(), TRUE); |
| 197 | cache_clear_all('*', 'cache', TRUE); | |
| 1a05ff77 | 198 | return $ret; |
| c7981f82 DP |
199 | } |
| 200 | ||
| 201 | /** | |
| 35873ed9 NH |
202 | * Migrate field settings from 'force_list_default' and 'show_description'. |
| 203 | */ | |
| 204 | function filefield_update_6100() { | |
| 205 | $ret = array(); | |
| 206 | ||
| 207 | module_load_include('inc', 'content', 'includes/content.crud'); | |
| 208 | ||
| 209 | $fields = content_fields(); | |
| 210 | foreach ($fields as $field) { | |
| 211 | if ($field['type'] == 'filefield') { | |
| 89250b08 NH |
212 | if (isset($field['force_list_default'])) { |
| 213 | $field['list_field'] = !$field['force_list_default']; | |
| 214 | } | |
| 215 | if (isset($field['show_description'])) { | |
| 216 | $field['description_field'] = $field['show_description']; | |
| 217 | } | |
| 35873ed9 | 218 | _content_field_write($field); |
| 7982f68b | 219 | $ret[] = array('success' => TRUE, 'query' => t('The file field %field has been updated with new settings.', array('%field' => $field['field_name']))); |
| 35873ed9 NH |
220 | } |
| 221 | } | |
| 222 | ||
| 89250b08 NH |
223 | cache_clear_all('*', content_cache_tablename(), TRUE); |
| 224 | cache_clear_all('*', 'cache', TRUE); | |
| 225 | ||
| 35873ed9 NH |
226 | return $ret; |
| 227 | } | |
| 228 | ||
| b7e24734 NH |
229 | /** |
| 230 | * Set fid to NULL where files have been deleted. | |
| 231 | * | |
| 232 | * This is a double-cleanup from Drupal 5 versions, where fid used to be 0 for | |
| 233 | * empty rows or sometimes referred to a nonexistent FID altogether. | |
| 234 | */ | |
| 235 | function filefield_update_6101() { | |
| 236 | $ret = array(); | |
| 237 | ||
| 238 | module_load_include('inc', 'content', 'includes/content.crud'); | |
| 239 | ||
| 240 | $fields = content_fields(); | |
| 241 | ||
| 242 | foreach ($fields as $field) { | |
| 243 | if ($field['type'] == 'filefield') { | |
| 244 | $db_info = content_database_info($field); | |
| 245 | if (isset($db_info['columns']['fid'])) { | |
| 246 | $table = $db_info['table']; | |
| 247 | $fid_column = $db_info['columns']['fid']['column']; | |
| 248 | $list_column = $db_info['columns']['list']['column']; | |
| 89c3edc1 | 249 | $ret[] = update_sql("UPDATE {" . $table . "} SET $fid_column = NULL, $list_column = NULL WHERE $fid_column NOT IN (SELECT fid FROM {files})"); |
| b7e24734 NH |
250 | } |
| 251 | } | |
| 252 | } | |
| 253 | ||
| 254 | return $ret; | |
| 255 | } | |
| 35873ed9 NH |
256 | |
| 257 | /** | |
| a7cd42d9 NH |
258 | * Fix corrupted serialized data in the "data" column. |
| 259 | */ | |
| 260 | function filefield_update_6102(&$sandbox) { | |
| c395e97c NH |
261 | // Update removed. This turned out to be a bug in CCK core, so it is being |
| 262 | // fixed directly in CCK rather than in FileField. | |
| 263 | // See http://drupal.org/node/407446. | |
| 264 | return array(); | |
| a7cd42d9 NH |
265 | } |
| 266 | ||
| 267 | /** | |
| dc1623bb NH |
268 | * Convert "Extensible File" to a normal "File" widget. |
| 269 | */ | |
| 270 | function filefield_update_6103() { | |
| 271 | $ret = array(); | |
| 272 | ||
| 273 | $ret[] = update_sql("UPDATE {". content_instance_tablename() ."} SET widget_type = 'filefield_widget' WHERE widget_type = 'filefield_combo'"); | |
| 274 | ||
| 275 | cache_clear_all('*', content_cache_tablename(), TRUE); | |
| 276 | cache_clear_all('*', 'cache', TRUE); | |
| 277 | ||
| 278 | return $ret; | |
| 279 | } | |
| 280 | ||
| 281 | /** | |
| 124f81c9 NH |
282 | * Delete the filefield_token module entry in the system table. |
| 283 | */ | |
| 284 | function filefield_update_6104() { | |
| 285 | $ret = array(); | |
| 286 | ||
| 287 | $ret[] = update_sql("DELETE FROM {system} WHERE type = 'module' AND name = 'filefield_token'"); | |
| 288 | ||
| 289 | return $ret; | |
| 290 | } | |
| 291 | ||
| 292 | /** | |
| c7981f82 DP |
293 | * Move the list and descriptions column into the serialized data column. |
| 294 | */ | |
| 28b1c58e | 295 | function _filefield_update_6001_move_operation($field, &$context) { |
| c7981f82 DP |
296 | // Setup the first through |
| 297 | if (!isset($context['sandbox']['progress'])) { | |
| 298 | $db_info = content_database_info($field); | |
| c7981f82 DP |
299 | $context['sandbox']['db_info'] = $db_info; |
| 300 | $context['sandbox']['table'] = $db_info['table']; | |
| 301 | $context['sandbox']['col_data'] = $db_info['columns']['data']['column']; | |
| 302 | $context['sandbox']['col_desc'] = $db_info['columns']['description']['column']; | |
| 303 | $context['sandbox']['max'] = db_result(db_query("SELECT COUNT(*) FROM {". $db_info['table'] ."}")); | |
| 304 | $context['sandbox']['progress'] = 0; | |
| 305 | $context['sandbox']['current_node'] = 0; | |
| 306 | } | |
| 307 | ||
| c7981f82 DP |
308 | // Work our way through the field values 50 rows at a time. |
| 309 | $limit = 50; | |
| 310 | $result = db_query_range("SELECT * FROM {{$context['sandbox']['table']}} WHERE vid > %d ORDER BY nid ASC", $context['sandbox']['current_node'], 0, $limit); | |
| 311 | while ($row = db_fetch_array($result)) { | |
| 312 | // Try to unserialize the data column. | |
| 313 | if (!empty($row[$context['sandbox']['col_data']])) { | |
| 314 | $data = unserialize($row[$context['sandbox']['col_data']]); | |
| 315 | } | |
| 316 | if (empty($data)) { | |
| 317 | $data = array(); | |
| 318 | } | |
| 319 | ||
| 320 | // Copy move the values from the columns into the array... | |
| 321 | $data['description'] = $row[$context['sandbox']['col_desc']]; | |
| 322 | ||
| 323 | // ...serialize it and store it back to the db. | |
| 324 | db_query("UPDATE {{$context['sandbox']['table']}} SET {$context['sandbox']['col_data']} = '%s' WHERE vid = %d", serialize($data), $row['vid']); | |
| 325 | ||
| 326 | // Update our progress information. | |
| 327 | $context['sandbox']['progress']++; | |
| 328 | $context['sandbox']['current_node'] = $row['vid']; | |
| 329 | } | |
| 330 | ||
| 331 | // Inform the batch engine that we are not finished, | |
| 332 | // and provide an estimation of the completion level we reached. | |
| 333 | if ($context['sandbox']['progress'] != $context['sandbox']['max']) { | |
| 334 | $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; | |
| 335 | } | |
| 336 | } | |
| 337 | ||
| 338 | /** | |
| 339 | * Drop the list and description columns. | |
| 340 | */ | |
| 28b1c58e | 341 | function _filefield_update_6001_drop_operation($field, &$context) { |
| 0ed57194 | 342 | $ret = array(); |
| c7981f82 DP |
343 | $db_info = content_database_info($field); |
| 344 | // TODO: Now that the data has been migrated we can drop the columns. | |
| 0ed57194 | 345 | db_drop_field($ret, $db_info['table'], $db_info['columns']['description']['column']); |
| c7981f82 DP |
346 | $context['finished'] = 1; |
| 347 | } |