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