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