media.pages.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <?php
  2. /**
  3. * @file
  4. * Common pages for the Media module.
  5. */
  6. /**
  7. * Menu callback; view a single file entity.
  8. */
  9. function media_view_page($file) {
  10. // @todo Implement granular editorial access: http://drupal.org/node/696970.
  11. // In the meantime, protect information about private files from being
  12. // discovered by unprivileged users. File IDs are autoincrement, so one can
  13. // attempt discovery by trying to access different media/ID paths. See also
  14. // media_browser_list(). This logic potentially belongs within
  15. // media_access(), but that would require extending that function's
  16. // signature to accept a $file paramter, and this is temporary code anyway.
  17. if (!user_access('administer media') && (file_uri_scheme($file->uri) === 'private')) {
  18. return MENU_ACCESS_DENIED;
  19. }
  20. drupal_set_title($file->filename);
  21. return file_view($file, 'media_original');
  22. }
  23. /**
  24. * Menu callback; presents the Media editing form.
  25. */
  26. function media_page_edit($file) {
  27. drupal_set_title(t('<em>Edit @type</em> @title', array('@type' => ($file->type != FILE_TYPE_NONE ? $file->type : ''), '@title' => $file->filename)), PASS_THROUGH);
  28. return drupal_get_form('media_edit', $file);
  29. }
  30. /**
  31. * Menu callback; presents the Media editing form for multiple file entities.
  32. */
  33. function media_page_multiedit($files) {
  34. if (!module_exists('multiform')) {
  35. drupal_set_message(t('To edit multiple media items, you must install the multiform module.'));
  36. }
  37. $i = 0;
  38. $forms = array();
  39. foreach ($files as $file) {
  40. // To maintain unique form_ids, increment this counter.
  41. // @see media_forms().
  42. $i++;
  43. $forms[] = array("media_edit_$i", $file);
  44. }
  45. $form = call_user_func_array('multiform_get_form', $forms);
  46. $form['#attributes']['class'][] = 'media-multiedit-form';
  47. unset($form['buttons']['Delete']);
  48. // Would be nice to add this to show a message, but not working.
  49. // Can debug.
  50. //$form['buttons']['Save']['#submit'][] = 'media_page_multiedit_submit';
  51. drupal_set_title(t('Editing multiple media files'));
  52. return $form;
  53. }
  54. /**
  55. * Menu callback; shows delete confirmation form.
  56. */
  57. function media_page_delete($file) {
  58. drupal_set_title(t('<em>Delete @type</em> @title', array('@type' => ($file->type != FILE_TYPE_NONE ? $file->type : ''), '@title' => $file->filename)), PASS_THROUGH);
  59. // Don't bother showing the form if the item is in use, since we won't allow
  60. // them to delete it anyway.
  61. $references = file_usage_list($file);
  62. if (!empty($references)) {
  63. return t('The file %title is in use and cannot be deleted.', array('%title' => $file->filename));
  64. }
  65. else {
  66. $files = array($file->fid => $file);
  67. return drupal_get_form('media_multiple_delete_confirm', $files, '<front>', 'media/' . $file->fid);
  68. }
  69. }
  70. /**
  71. * Confirm the request to delete files.
  72. */
  73. function media_multiple_delete_confirm($form, &$form_state, $files, $redirect_on_success = NULL, $redirect_on_cancel = NULL) {
  74. $form['files'] = array('#tree' => TRUE);
  75. $form['file_titles'] = array('#theme' => 'item_list');
  76. foreach ($files as $fid => $value) {
  77. $title = db_query('SELECT filename FROM {file_managed} WHERE fid = :fid', array(':fid' => $fid))->fetchField();
  78. $form['files'][$fid] = array(
  79. '#type' => 'value',
  80. '#value' => $fid,
  81. );
  82. $form['file_titles']['#items'][] = check_plain($title);
  83. }
  84. $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
  85. if (isset($redirect_on_success)) {
  86. $form['redirect_on_success'] = array(
  87. '#type' => 'value',
  88. '#value' => $redirect_on_success,
  89. );
  90. }
  91. $form['#submit'][] = 'media_multiple_delete_confirm_submit';
  92. $confirm_question = format_plural(count($files),
  93. 'Are you sure you want to delete this item?',
  94. 'Are you sure you want to delete these items?');
  95. return confirm_form($form,
  96. $confirm_question,
  97. isset($redirect_on_cancel) ? $redirect_on_cancel : current_path(),
  98. t('This action cannot be undone.'),
  99. t('Delete'),
  100. t('Cancel'));
  101. }
  102. /**
  103. * Attempt to delete files and notify the user of the result.
  104. */
  105. function media_multiple_delete_confirm_submit($form, &$form_state) {
  106. if ($form_state['values']['confirm']) {
  107. $results = array();
  108. $files = array_keys($form_state['values']['files']);
  109. foreach ($files as $fid) {
  110. $file = file_load($fid);
  111. $files[$fid] = $file;
  112. $results[$fid] = file_delete($file);
  113. }
  114. // The result of file_delete can be an array if the file is in use, or TRUE/FALSE.
  115. foreach ($results as $fid => $result) {
  116. if (is_array($result)) {
  117. drupal_set_message(t('The file @title is in use and cannot be deleted.', array('@title' => $files[$fid]->filename)), 'warning');
  118. }
  119. elseif (!$result) {
  120. drupal_set_message(t('The file @title was not deleted due to an error.', array('@title' => $files[$fid]->filename)), 'error');
  121. }
  122. else {
  123. $message = t('File @title was deleted', array('@title' => $files[$fid]->filename));
  124. watchdog('media', $message);
  125. drupal_set_message($message);
  126. }
  127. }
  128. if (isset($form_state['values']['redirect_on_success'])) {
  129. $form_state['redirect'] = $form_state['values']['redirect_on_success'];
  130. }
  131. }
  132. }
  133. /**
  134. * Form callback for adding media via an upload form.
  135. * @todo: should use the AJAX uploader
  136. */
  137. function media_add_upload($form, &$form_state, $params = array()) {
  138. // Set up file upload validators.
  139. $validators = array();
  140. // Validate file extensions. If there are no file extensions in $params and
  141. // there are no Media defaults, there is no file extension validation.
  142. if (!empty($params['file_extensions'])) {
  143. $validators['file_validate_extensions'] = array($params['file_extensions']);
  144. }
  145. elseif ($tmp = media_variable_get('file_extensions')) {
  146. $validators['file_validate_extensions'] = array($tmp);
  147. }
  148. // Validate file size but do not allow anything higher than file_upload_max_size().
  149. $max_filesize = file_upload_max_size();
  150. if (!empty($params['max_filesize']) && $params['max_filesize'] < $max_filesize) {
  151. $validators['file_validate_size'] = array(parse_size($params['max_filesize']));
  152. }
  153. elseif (($tmp = media_variable_get('max_filesize')) && $tmp < $max_filesize) {
  154. $validators['file_validate_size'] = array(parse_size($tmp));
  155. }
  156. else {
  157. $validators['file_validate_size'] = array($max_filesize);
  158. }
  159. // Add image validators.
  160. $params += array('min_resolution' => 0, 'max_resolution' => 0);
  161. if ($params['min_resolution'] || $params['max_resolution']) {
  162. $validators['file_validate_image_resolution'] = array($params['max_resolution'], $params['min_resolution']);
  163. }
  164. $form['#validators'] = $validators;
  165. $form['upload'] = array(
  166. '#type' => 'file',
  167. '#title' => t('Upload a new file'),
  168. '#description' => theme('file_upload_help', array('description' => '', 'upload_validators' => $validators)),
  169. '#upload_validators' => $validators,
  170. );
  171. $form['submit'] = array(
  172. '#type' => 'submit',
  173. '#value' => t('Submit'),
  174. );
  175. return $form;
  176. }
  177. /**
  178. * Validate the generic file upload with the global media settings.
  179. */
  180. function media_add_upload_validate($form, &$form_state) {
  181. // Save the file as a temporary file.
  182. $file = file_save_upload('upload', $form['#validators']);
  183. if ($file === NULL) {
  184. form_set_error('upload', t("No file appears to have been selected."));
  185. }
  186. elseif ($file === FALSE) {
  187. form_set_error('upload', t('File upload error.'));
  188. }
  189. else {
  190. $form_state['values']['upload'] = $file;
  191. }
  192. }
  193. /**
  194. * Upload a file.
  195. */
  196. function media_add_upload_submit($form, &$form_state) {
  197. $params = $form_state['build_info']['args'][0];
  198. $file = $form_state['values']['upload'];
  199. // The media browser widget does not use the 'display' field.
  200. $file->display = TRUE;
  201. // Change the file status from temporary to permanent.
  202. _media_save_file_permenently($file);
  203. // Determine what URI scheme this file should use.
  204. $scheme = !empty($params['uri_scheme']) && file_stream_wrapper_valid_scheme($params['uri_scheme']) ? $params['uri_scheme'] : file_default_scheme();
  205. $scheme .= '://';
  206. // Prepare the file's subdirectory path.
  207. $directory = '';
  208. if (!empty($params['file_directory'])) {
  209. $directory = token_replace($params['file_directory']) . '/';
  210. // If the directory isn't writable, or doesn't exist and can't be created,
  211. // the upload will fail.
  212. $prepare_directory = file_stream_wrapper_uri_normalize($scheme . $directory);
  213. if (!file_prepare_directory($prepare_directory, FILE_CREATE_DIRECTORY)) {
  214. drupal_set_message(t('The file directory @dir does not exist or is not writable. Please contact an administrator.', array('@dir' => $prepare_directory)), 'error');
  215. return;
  216. }
  217. }
  218. // Compose the file's permanent destination.
  219. $destination = file_stream_wrapper_uri_normalize($scheme . $directory . $file->filename);
  220. // Save the uploaded file to the permanent location.
  221. $file = file_move($file, $destination, FILE_EXISTS_RENAME);
  222. if ($file) {
  223. drupal_set_message(t('The file @name was uploaded', array('@name' => $file->filename)));
  224. }
  225. else {
  226. drupal_set_message(t('An error occurred and no file was uploaded.'), 'error');
  227. return;
  228. }
  229. $form_state['redirect'] = array('media/browser', array('query' => array('render' => 'media-popup', 'fid' => $file->fid)));
  230. }
  231. function media_add_upload_multiple($form, &$form_state, $params = array()) {
  232. $form = media_add_upload($form, $form_state, $params);
  233. unset($form['upload']['#title']);
  234. // The validators will be set from plupload anyway. This isn't pretty, but don't
  235. // it to show up twice.
  236. unset($form['upload']['#description']);
  237. $form['upload']['#type'] = 'plupload';
  238. $form['submit']['#value'] = t('Start upload');
  239. return $form;
  240. }
  241. function media_add_upload_multiple_submit($form, &$form_state) {
  242. $scheme = variable_get('file_default_scheme', 'public') . '://';
  243. $saved_files = array();
  244. // We can't use file_save_upload() because of http://www.jacobsingh.name/content/tight-coupling-no-not
  245. foreach ($form_state['values']['upload'] as $uploaded_file) {
  246. if ($uploaded_file['status'] == 'done') {
  247. $source = $uploaded_file['tmppath'];
  248. $destination = file_stream_wrapper_uri_normalize($scheme . $uploaded_file['name']);
  249. // Rename it to its original name, and put it in its final home.
  250. // Note - not using file_move here because if we call file_get_mime
  251. // (in file_uri_to_object) while it has a .tmp extension, it horks.
  252. $destination = file_unmanaged_move($source, $destination, FILE_EXISTS_RENAME);
  253. $file = file_uri_to_object($destination);
  254. file_save($file);
  255. _media_save_file_permenently($file);
  256. $saved_files[] = $file;
  257. }
  258. else {
  259. // @todo: move this to element validate or something.
  260. form_set_error('pud', t('The specified file %name could not be uploaded.', array('%name' => $uploaded_file['name'])));
  261. }
  262. }
  263. // Get a list of fids to pass back.
  264. $fids = array();
  265. foreach ($saved_files as $file) {
  266. $fids[] = $file->fid;
  267. }
  268. $form_state['redirect'] = array('media/browser', array('query' => array('render' => 'media-popup', 'fid' => $fids)));
  269. }
  270. /**
  271. * Form builder: Builds the edit file form.
  272. */
  273. function media_edit($form, $form_state, $file) {
  274. $form_state['file'] = $file;
  275. field_attach_form('file', $file, $form, $form_state);
  276. $form['#attached'] = array(
  277. 'css' => array(drupal_get_path('module', 'media') . '/css/media.css'),
  278. );
  279. // Not sure about this class name, seems to indicate the style.
  280. $form['#attributes']['class'][] = 'media-image-left';
  281. $form['#attributes']['class'][] = 'media-edit-form';
  282. $form['preview'] = file_view_file($file, 'media_preview');
  283. $form['preview']['#weight'] = -10;
  284. $form['preview']['#suffix'] = '<div class="no-overflow">';
  285. // Add the buttons.
  286. $form['actions'] = array('#type' => 'actions');
  287. $form['actions']['#prefix'] = '</div>';
  288. $form['actions']['delete'] = array(
  289. '#type' => 'submit',
  290. '#value' => t('Delete'),
  291. '#weight' => 15,
  292. '#submit' => array('media_edit_delete_submit'),
  293. );
  294. $form['actions']['submit'] = array(
  295. '#type' => 'submit',
  296. '#value' => t('Save'),
  297. '#weight' => 5,
  298. '#submit' => array('media_edit_submit'),
  299. );
  300. // Add internal file properties needed by media_edit_validate().
  301. foreach (array('fid', 'type') as $key) {
  302. $form[$key] = array('#type' => 'value', '#value' => $file->$key);
  303. }
  304. return $form;
  305. }
  306. /**
  307. * Form validation handler for the media edit form.
  308. */
  309. function media_edit_validate($form, &$form_state) {
  310. entity_form_field_validate('file', $form, $form_state);
  311. }
  312. /**
  313. * Form submit handler for the media submit form.
  314. */
  315. function media_edit_submit($form, &$form_state) {
  316. $file = $form_state['file'];
  317. entity_form_submit_build_entity('file', $file, $form, $form_state);
  318. file_save($file);
  319. $form_state['redirect'] = 'media/' . $file->fid;
  320. }
  321. /**
  322. * Form submit handler for the Delete button on the media edit form.
  323. */
  324. function media_edit_delete_submit($form, &$form_state) {
  325. $fid = $form_state['values']['fid'];
  326. $destination = array();
  327. if (isset($_GET['destination'])) {
  328. $destination = drupal_get_destination();
  329. unset($_GET['destination']);
  330. }
  331. $form_state['redirect'] = array('media/' . $fid . '/delete', array('query' => $destination));
  332. }
  333. function media_add_remote($form, &$form_state) {
  334. // Totally prototyping code to show designs.
  335. $form['sources'] = array(
  336. '#type' => 'vertical_tabs',
  337. '#title' => 'Sources',
  338. );
  339. $form['sources']['paste'] = array(
  340. '#type' => 'fieldset',
  341. '#title' => 'Paste URL or embed code',
  342. );
  343. $providers = '';
  344. $providers .= '<img style="height:50px; margin:20px" src="http://www.macuser.com/2008/10/09/top_youtube_logo_31_Dec_06.jpg">';
  345. $providers .= '<img style="height:50px; margin:20px" src="http://jasonhilldesign.com/FlikrLogo.jpg">';
  346. $form['sources']['paste']['code'] = array(
  347. '#type' => 'textarea',
  348. '#title' => t('URL or embed code'),
  349. '#description' => t('The following providers are supported: <br/>' . $providers),
  350. );
  351. $form['sources']['youtube'] = array(
  352. '#type' => 'fieldset',
  353. '#title' => 'YouTube',
  354. '#description' => t(''),
  355. '#attributes' => array('style' => 'height: 300px; overflow:auto'),
  356. );
  357. $form['sources']['flikr'] = array(
  358. '#type' => 'fieldset',
  359. '#title' => 'Flikr',
  360. );
  361. $box = '<div style="width:100px; height:100px; border:1px solid blue; padding:10px; float:left; margin:5px;"> Video </div>';
  362. $boxes = '';
  363. for ($i = 0; $i < 10; $i++) {
  364. $boxes .= $box;
  365. }
  366. $form['sources']['youtube']['stupid'] = array(
  367. '#markup' => $boxes,
  368. );
  369. $form['submit'] = array(
  370. '#type' => 'submit',
  371. '#value' => t('Import'),
  372. '#attributes' => array('style' => 'float:right'),
  373. '#suffix' => '<br style="clear:both" />',
  374. );
  375. return $form;
  376. }