Reordering logic.
[project/file_entity.git] / file_entity.admin.inc
1 <?php
2
3 require_once dirname(__FILE__) . '/file_entity.pages.inc';
4
5 /**
6 * @file
7 * Administrative interface for file type configuration.
8 */
9
10 /**
11 * Administrative form for browsing files and performing operations on them.
12 */
13 function file_entity_admin_files($form, &$form_state) {
14 if (!empty($form_state['values']['operation'])) {
15 // The form is being rebuilt because an operation requiring confirmation
16 // was selected. Hand off to the callback of the operation at this point
17 // which should return a confirm form.
18 $operation = $form_state['values']['operation'];
19 $files = array_keys(array_filter($form_state['values']['files']));
20 return call_user_func_array($operation['callback'], array($files));
21 }
22
23 $limit = variable_get('file_entity_admin_files_limit', 50);
24
25 // Build the 'Update options' form.
26
27 $options = array();
28 $form['#operations'] = module_invoke_all('file_operations_info');
29 drupal_alter('file_entity_file_operations', $form['#operations']);
30 foreach ($form['#operations'] as $operation => $array) {
31 $options[$operation] = $array['label'];
32 }
33 $form['options'] = array(
34 '#type' => 'fieldset',
35 '#title' => t('Update options'),
36 '#attributes' => array('class' => array('container-inline')),
37 '#access' => user_access('administer files') && !empty($options),
38 );
39 $form['options']['operation'] = array(
40 '#type' => 'select',
41 '#title' => t('Operation'),
42 '#title_display' => 'invisible',
43 '#options' => $options,
44 );
45 $form['options']['submit'] = array(
46 '#type' => 'submit',
47 '#value' => t('Update'),
48 );
49
50 // Build the sortable table header.
51 $header = array(
52 'title' => array('data' => t('Title'), 'field' => 'f.filename'),
53 'type' => array('data' => t('Type'), 'field' => 'f.filemime'),
54 'size' => array('data' => t('Size'), 'field' => 'f.filesize'),
55 'author' => array('data' => t('Author'), 'field' => 'u.name'),
56 'timestamp' => array('data' => t('Updated'), 'field' => 'f.timestamp', 'sort' => 'desc'),
57 'operations' => array('data' => t('Operations')),
58 );
59
60 $query = db_select('file_managed', 'f')->extend('PagerDefault')->extend('TableSort');
61 $query->join('users', 'u', 'f.uid = u.uid');
62 $query->fields('f', array('fid'));
63 $query->fields('u', array('uid'));
64 $query->condition('f.status', FILE_STATUS_PERMANENT);
65 $query->limit($limit);
66 $query->orderByHeader($header);
67
68 foreach (array_keys(file_entity_get_hidden_stream_wrappers()) as $name) {
69 $query->condition('f.uri', $name . '%', 'NOT LIKE');
70 }
71
72 // Result array keys are file IDs, values are the file owner's UIDs.
73 $result = $query->execute()->fetchAllKeyed();
74
75 // Load all the file entities.
76 $files = $form['#files'] = file_load_multiple(array_keys($result));
77
78 // Hide the operations form if there are no files to operate on.
79 $form['options']['#access'] &= !empty($files);
80
81 // Load all the file owner user entities to display usernames.
82 $accounts = $form['#accounts'] = user_load_multiple(array_unique($result));
83
84 $destination = drupal_get_destination();
85 $options = array();
86 foreach ($files as $file) {
87 $options[$file->fid] = array(
88 'title' => theme('file_entity_file_link', array('file' => $file)),
89 'type' => check_plain($file->filemime),
90 'size' => format_size($file->filesize),
91 'author' => theme('username', array('account' => $accounts[$file->uid])),
92 'timestamp' => format_date($file->timestamp, 'short'),
93 );
94
95 $options[$file->fid]['operations'] = array(
96 'data' => array(
97 '#theme' => 'links__file_operations',
98 '#links' => array(),
99 '#attributes' => array('class' => array('links', 'inline')),
100 ),
101 );
102
103 $options[$file->fid]['operations']['data']['#links']['edit'] = array(
104 'title' => t('Edit'),
105 'href' => 'file/' . $file->fid . '/edit',
106 'query' => $destination,
107 );
108
109 $options[$file->fid]['operations']['data']['#links']['delete'] = array(
110 'title' => t('Delete'),
111 'href' => 'file/' . $file->fid . '/delete',
112 'query' => $destination,
113 );
114 }
115
116 $form['files'] = array(
117 '#type' => 'tableselect',
118 '#header' => $header,
119 '#options' => $options,
120 '#empty' => t('No files available.'),
121 '#attributes' => array('class' => array('file-display-table', 'clear')),
122 );
123 $form['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
124
125 return $form;
126 }
127
128
129 /**
130 * Validate file_entity_admin_files form submissions.
131 *
132 * Check if any files have been selected to perform the chosen
133 * 'Update option' on.
134 */
135 function file_entity_admin_files_validate($form, &$form_state) {
136 // Error if there are no items to select.
137 if (!is_array($form_state['values']['files']) || !count(array_filter($form_state['values']['files']))) {
138 form_set_error('', t('No files selected.'));
139 }
140 }
141
142 /**
143 * Submit handler for file_entity_admin_files.
144 */
145 function file_entity_admin_files_submit($form, &$form_state) {
146 $operations = $form['#operations'];
147 $operation = $operations[$form_state['values']['operation']];
148
149 // In the case of an operation which needs confirmation, rebuild the form.
150 if (!empty($operation['confirm'])) {
151 $form_state['rebuild'] = TRUE;
152 $form_state['values']['operation'] = $operation;
153 return;
154 }
155
156 // Filter out unchecked nodes
157 $files = array_filter($form_state['values']['files']);
158 if ($function = $operation['callback']) {
159 // Add in callback arguments if present.
160 if (isset($operation['callback arguments'])) {
161 $args = array_merge(array($files), $operation['callback arguments']);
162 }
163 else {
164 $args = array($files);
165 }
166 call_user_func_array($function, $args);
167 cache_clear_all();
168 }
169 }
170
171 /**
172 * Displays the file type admin overview page.
173 */
174 function file_entity_list_types_page() {
175 $types = file_info_file_types();
176 $entity_info = entity_get_info('file');
177 $field_ui = module_exists('field_ui');
178 $header = array(
179 array('data' => t('Name')),
180 array('data' => t('Operations'), 'colspan' => $field_ui ? '3' : '1'),
181 );
182 $rows = array();
183
184 foreach ($types as $type => $info) {
185 $row = array(array('data' => theme('file_entity_file_type_overview', $info)));
186 $path = isset($entity_info['bundles'][$type]['admin']['real path']) ? $entity_info['bundles'][$type]['admin']['real path'] : NULL;
187 if ($field_ui) {
188 $row[] = array('data' => isset($path) ? l(t('manage fields'), $path . '/fields') : '');
189 $row[] = array('data' => isset($path) ? l(t('manage display'), $path . '/display') : '');
190 }
191 $row[] = array('data' => isset($path) ? l(t('manage file display'), $path . '/file-display') : '');
192 $rows[] = $row;
193 }
194
195 $build['file_type_table'] = array(
196 '#theme' => 'table',
197 '#header' => $header,
198 '#rows' => $rows,
199 '#empty' => t('No file types available.'),
200 );
201
202 return $build;
203 }
204
205 /**
206 * Form callback; presents file display settings for a given view mode.
207 */
208 function file_entity_file_display_form($form, &$form_state, $file_type, $view_mode) {
209 $form['#file_type'] = $file_type;
210 $form['#view_mode'] = $view_mode;
211 $form['#tree'] = TRUE;
212 $form['#attached']['js'][] = drupal_get_path('module', 'file_entity') . '/file_entity.admin.js';
213
214 // Retrieve available formatters for this file type and load all configured
215 // filters for existing text formats.
216 $formatters = file_info_formatter_types();
217 foreach ($formatters as $name => $formatter) {
218 if (isset($formatter['file types']) && !in_array($file_type, $formatter['file types'])) {
219 unset($formatters[$name]);
220 }
221 }
222 $current_displays = file_displays_load($file_type, $view_mode, TRUE);
223 foreach ($current_displays as $name => $display) {
224 $current_displays[$name] = (array) $display;
225 }
226
227 // Formatter status.
228 $form['displays']['status'] = array(
229 '#type' => 'item',
230 '#title' => t('Enabled displays'),
231 '#prefix' => '<div id="file-displays-status-wrapper">',
232 '#suffix' => '</div>',
233 );
234 $i=0;
235 foreach ($formatters as $name => $formatter) {
236 $form['displays']['status'][$name] = array(
237 '#type' => 'checkbox',
238 '#title' => check_plain($formatter['label']),
239 '#default_value' => !empty($current_displays[$name]['status']),
240 '#description' => isset($formatter['description']) ? filter_xss($formatter['description']) : NULL,
241 '#parents' => array('displays', $name, 'status'),
242 '#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
243 );
244 $i++;
245 }
246
247 // Formatter order (tabledrag).
248 $form['displays']['order'] = array(
249 '#type' => 'item',
250 '#title' => t('Display precedence order'),
251 '#theme' => 'file_entity_file_display_order',
252 );
253 foreach ($formatters as $name => $formatter) {
254 $form['displays']['order'][$name]['label'] = array(
255 '#markup' => check_plain($formatter['label']),
256 );
257 $form['displays']['order'][$name]['weight'] = array(
258 '#type' => 'weight',
259 '#title' => t('Weight for @title', array('@title' => $formatter['label'])),
260 '#title_display' => 'invisible',
261 '#delta' => 50,
262 '#default_value' => isset($current_displays[$name]['weight']) ? $current_displays[$name]['weight'] : 0,
263 '#parents' => array('displays', $name, 'weight'),
264 );
265 $form['displays']['order'][$name]['#weight'] = $form['displays']['order'][$name]['weight']['#default_value'];
266 }
267
268 // Formatter settings.
269 $form['display_settings_title'] = array(
270 '#type' => 'item',
271 '#title' => t('Display settings'),
272 );
273 $form['display_settings'] = array(
274 '#type' => 'vertical_tabs',
275 );
276 $i=0;
277 foreach ($formatters as $name => $formatter) {
278 if (isset($formatter['settings callback']) && ($function = $formatter['settings callback']) && function_exists($function)) {
279 $defaults = !empty($formatter['default settings']) ? $formatter['default settings'] : array();
280 $settings = !empty($current_displays[$name]['settings']) ? $current_displays[$name]['settings'] : array();
281 $settings += $defaults;
282 $settings_form = $function($form, $form_state, $settings, $name, $file_type, $view_mode);
283 if (!empty($settings_form)) {
284 $form['displays']['settings'][$name] = array(
285 '#type' => 'fieldset',
286 '#title' => check_plain($formatter['label']),
287 '#parents' => array('displays', $name, 'settings'),
288 '#group' => 'display_settings',
289 '#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
290 ) + $settings_form;
291 }
292 }
293 $i++;
294 }
295
296 $form['actions'] = array('#type' => 'actions');
297 $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
298
299 return $form;
300 }
301
302 /**
303 * Process file display settings form submissions.
304 */
305 function file_entity_file_display_form_submit($form, &$form_state) {
306 $file_type = $form['#file_type'];
307 $view_mode = $form['#view_mode'];
308 $displays = isset($form_state['values']['displays']) ? $form_state['values']['displays'] : array();
309 $displays_original = file_displays_load($file_type, $view_mode, TRUE);
310 foreach ($displays as $formatter_name => $display) {
311 $display_original = isset($displays_original[$formatter_name]) ? $displays_original[$formatter_name] : file_display_new($file_type, $view_mode, $formatter_name);
312 $display += (array) $display_original;
313 file_display_save((object) $display);
314 }
315 drupal_set_message(t('Your settings have been saved.'));
316 }
317
318 /**
319 * Returns HTML for a file type label and description for the file type admin overview page.
320 */
321 function theme_file_entity_file_type_overview($variables) {
322 return check_plain($variables['label']) . '<div class="description">' . $variables['description'] . '</div>';
323 }
324
325 /**
326 * Returns HTML for a file display's display order table.
327 */
328 function theme_file_entity_file_display_order($variables) {
329 $element = $variables['element'];
330
331 $rows = array();
332 foreach (element_children($element, TRUE) as $name) {
333 $element[$name]['weight']['#attributes']['class'][] = 'file-display-order-weight';
334 $rows[] = array(
335 'data' => array(
336 drupal_render($element[$name]['label']),
337 drupal_render($element[$name]['weight']),
338 ),
339 'class' => array('draggable'),
340 );
341 }
342 $output = drupal_render_children($element);
343 $output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => 'file-displays-order')));
344 drupal_add_tabledrag('file-displays-order', 'order', 'sibling', 'file-display-order-weight', NULL, NULL, TRUE);
345
346 return $output;
347 }