/admin/manage/class-ngg-manager.php

  1. <?php 
  2.  
  3. include_once( NGGALLERY_ABSPATH . '/admin/interface-ngg-displayable.php' ); 
  4.  
  5. /** 
  6. * Class NGG_Manager 
  7. * 
  8. * Contains common JavaScript and other code for the managing pages. 
  9. */ 
  10. abstract class NGG_Manager implements NGG_Displayable { 
  11.  
  12. const BASE = 'admin.php?page=nggallery-manage'; 
  13.  
  14. /** 
  15. * Subclasses should override this method, but must call the parent function. 
  16. */ 
  17. public function display() { 
  18. /** 
  19. * Do a bulk action. 
  20. */ 
  21. if ( ( isset( $_POST['action'] ) || isset( $_POST['action2'] ) ) && isset ( $_POST['doaction'] ) ) { 
  22. $this->handle_bulk_actions(); 
  23.  
  24. /** 
  25. * Do the operations with a dialog. 
  26. */ 
  27. if ( isset( $_POST['TB_bulkaction'] ) && isset( $_POST['TB_action'] ) ) { 
  28. $this->handle_dialog_actions(); 
  29.  
  30. /** 
  31. * Print the HTML for the dialogs. 
  32. */ 
  33. protected function print_dialogs() { 
  34.  
  35. $options = get_option( 'ngg_options' ); 
  36.  
  37. ?> 
  38. <style> 
  39. .ngg-dialog-container { 
  40. display: none; 
  41. </style> 
  42. <div class="ngg-dialog-container"> 
  43. <!-- #resize_images --> 
  44. <form id="resize_images_dialog" method="POST" accept-charset="utf-8"> 
  45. <?php wp_nonce_field( 'ngg_thickbox_form' ) ?> 
  46. <input type="hidden" name="TB_type" class="TB_type" value=""> 
  47. <input type="hidden" id="resize_images_imagelist" name="TB_imagelist" value=""> 
  48. <input type="hidden" id="resize_images_bulkaction" name="TB_bulkaction" value=""> 
  49. <input type="hidden" name="TB_action" value="resize_images"> 
  50. <table width="100%"> 
  51. <tr valign="top"> 
  52. <td> 
  53. <strong><?php _e( 'Resize Images to', 'nggallery' ); ?>:</strong> 
  54. </td> 
  55. <td> 
  56. <label for="imgWidth"><?php _e( 'Width', 'nggallery' ) ?></label> 
  57. <input type="number" min="0" class="small-text" id="imgWidth" name="imgWidth" value="<?php echo $options['imgWidth']; ?>"> 
  58. <label for="imgHeight"><?php _e( 'Height', 'nggallery' ) ?></label> 
  59. <input type="number" min="0" size="5" name="imgHeight" id="imgHeight" class="small-text" value="<?php echo $options['imgHeight']; ?>"> 
  60.  
  61. <p class="description"><?php _e( 'Width and height (in pixels). NextCellent Gallery will keep the ratio size.',  
  62. 'nggallery' ) ?></p> 
  63. </td> 
  64. </tr> 
  65. </table> 
  66. </form> 
  67. <!-- /#resize_images --> 
  68. <!-- #new_thumbnail --> 
  69. <form id="new_thumbnail_dialog" method="POST" accept-charset="utf-8"> 
  70. <?php wp_nonce_field( 'ngg_thickbox_form' ) ?> 
  71. <input type="hidden" name="TB_type" class="TB_type" value=""> 
  72. <input type="hidden" id="new_thumbnail_imagelist" name="TB_imagelist" value=""> 
  73. <input type="hidden" id="new_thumbnail_bulkaction" name="TB_bulkaction" value=""> 
  74. <input type="hidden" name="TB_action" value="new_thumbnails"> 
  75. <table width="100%"> 
  76. <tr valign="top"> 
  77. <th align="left"><?php _e( 'Size', 'nggallery' ) ?></th> 
  78. <td> 
  79. <label for="thumbwidth"><?php _e( 'Width', 'nggallery' ) ?></label> 
  80. <input id="thumbwidth" class="small-text" type="number" min="0" name="thumbwidth" value="<?php echo $options['thumbwidth']; ?>"> 
  81. <label for="thumbheight"><?php _e( 'Height', 'nggallery' ) ?></label> 
  82. <input id="thumbheight" class="small-text" type="number" step="1" min="0" name="thumbheight" value="<?php echo $options['thumbheight']; ?>"> 
  83.  
  84. <p class="description"><?php _e( 'These values are maximum values ', 'nggallery' ) ?></p> 
  85. </td> 
  86. </tr> 
  87. <tr valign="top"> 
  88. <th align="left"> 
  89. <label for="thumb_fix"> 
  90. <?php _e( 'Fixed size', 'nggallery' ); ?> 
  91. </label> 
  92. </th> 
  93. <td> 
  94. <input id="thumb_fix" type="checkbox" name="thumb_fix" value="true" <?php checked( '1',  
  95. $options['thumbfix'] ); ?>> 
  96. <?php _e( 'This will ignore the aspect ratio, so no portrait thumbnails', 'nggallery' ) ?> 
  97. </td> 
  98. </tr> 
  99. </table> 
  100. </form> 
  101. <!-- /#new_thumbnail --> 
  102. <!-- #entertags --> 
  103. <form id="tags_dialog" method="POST" accept-charset="utf-8"> 
  104. <?php wp_nonce_field( 'ngg_thickbox_form' ) ?> 
  105. <input type="hidden" class="TB_type" name="TB_type" value=""> 
  106. <input type="hidden" id="tags_imagelist" name="TB_imagelist" value=""> 
  107. <input type="hidden" id="tags_bulkaction" name="TB_bulkaction" value=""> 
  108. <input type="hidden" name="TB_action" value=""> 
  109.  
  110. <div style="text-align: center"> 
  111. <label> 
  112. <?php _e( "Enter the tags", 'nggallery' ); ?><br> 
  113. <input name="taglist" type="text" value="" style="width: 90%"> 
  114. </label> 
  115. </div> 
  116. </form> 
  117. <!-- /#entertags --> 
  118. <!-- #selectgallery --> 
  119. <form id="select_gallery_dialog" method="POST" accept-charset="utf-8"> 
  120. <?php wp_nonce_field( 'ngg_thickbox_form' ) ?> 
  121. <input type="hidden" name="TB_type" class="TB_type" value=""> 
  122. <input type="hidden" id="select_gallery_imagelist" name="TB_imagelist" value=""> 
  123. <input type="hidden" id="select_gallery_bulkaction" name="TB_bulkaction" value=""> 
  124. <input type="hidden" name="TB_action" value=""> 
  125.  
  126. <div style="text-align: center"> 
  127. <label> 
  128. <?php _e( 'Select the destination gallery:', 'nggallery' ); ?><br> 
  129. <select id="dest_gid" name="dest_gid" style="width: 300px"> 
  130. <option value="0" selected="selected"><?php _e( "Select or search for a gallery",  
  131. 'nggallery' ); ?></option> 
  132. </select> 
  133. </label> 
  134. </div> 
  135. </form> 
  136. <!-- /#selectgallery --> 
  137. </div> 
  138. <?php 
  139.  
  140. /** 
  141. * Print the Javascript. 
  142. * 
  143. * @todo Maybe move this whole stuff to a seperate file and register it instead of inline? 
  144. */ 
  145. protected function print_scripts() { 
  146. ?> 
  147. <script type="text/javascript"> 
  148. jQuery(function() { 
  149. jQuery("[id^=doaction]").click(function(event) { 
  150. return handleBulkActions(event); 
  151. }); 
  152. jQuery("#dest_gid").nggAutocomplete({ 
  153. type: 'gallery',  
  154. domain: "<?php echo home_url('index.php', is_ssl() ? 'https' : 'http'); ?>" 
  155. }); 
  156. if (jQuery("#page_type").val() === 'gallery') { 
  157. jQuery('.TB_type').val('gallery'); 
  158. }); 
  159.  
  160. var doActionToSelector = { 
  161. doaction: "#bulk-action-selector-top",  
  162. doaction2: "#bulk-action-selector-bottom" 
  163. }; 
  164.  
  165. function handleBulkActions(event) { 
  166. var caller = event.target; 
  167. var $selector = jQuery(doActionToSelector[caller.id]); 
  168. var $selected = jQuery("input[name^=doaction]:checkbox:checked"); 
  169.  
  170. if ($selected.length < 1) { 
  171. alert('<?php echo esc_js(__('No images selected', 'nggallery')); ?>'); 
  172. return false; 
  173.  
  174. var cp = ''; 
  175. if (jQuery("#page_type").val() === 'gallery') { 
  176. cp = 'gallery_'; 
  177. console.log($selector.val()); 
  178. /** 
  179. * The options prepended with 'g' are the ones for the gallery page, the normal ones work with images. 
  180. */ 
  181. switch ($selector.val()) { 
  182. case "-1": 
  183. alert('<?php echo esc_js(__('No action selected.', 'nggallery')); ?>'); 
  184. break; 
  185. case 'resize_images': 
  186. bulkDialog('resize_images', '<?php echo esc_js(__('Resize images', 'nggallery')); ?>', $selected); 
  187. break; 
  188. case 'new_thumbnail': 
  189. bulkDialog('new_thumbnail', '<?php echo esc_js(__('Create new thumbnails', 'nggallery')); ?>', $selected); 
  190. break; 
  191. case 'import_meta': 
  192. ajaxOperation(cp + 'import_metadata', '<?php echo esc_js(__('Import metadata', 'nggallery')); ?>', $selected, true); 
  193. break; 
  194. case 'recover_images': 
  195. ajaxOperation(cp + 'recover_image', '<?php echo esc_js(__('Recover from backup', 'nggallery')); ?>', $selected, true); 
  196. break; 
  197. case 'set_watermark': 
  198. ajaxOperation(cp + 'set_watermark', '<?php echo esc_js(__('Set watermark', 'nggallery')); ?>', $selected, true); 
  199. break; 
  200. case "copy_to": 
  201. set_TB_command('select_gallery', 'copy_to'); 
  202. bulkDialog('select_gallery', '<?php echo esc_js(__('Copy image to...', 'nggallery')); ?>', $selected); 
  203. break; 
  204. case "move_to": 
  205. set_TB_command('select_gallery', 'move_to'); 
  206. bulkDialog('select_gallery', '<?php echo esc_js(__('Move image to...', 'nggallery')); ?>', $selected); 
  207. break; 
  208. case "add_tags": 
  209. set_TB_command('tags', 'add_tags'); 
  210. bulkDialog('tags', '<?php echo esc_js(__('Add new tags', 'nggallery')); ?>', $selected); 
  211. break; 
  212. case "delete_tags": 
  213. set_TB_command('tags', 'delete_tags'); 
  214. bulkDialog('tags', '<?php echo esc_js(__('Delete tags', 'nggallery')); ?>', $selected); 
  215. break; 
  216. case "overwrite_tags": 
  217. set_TB_command('tags', 'overwrite_tags'); 
  218. bulkDialog('tags', '<?php echo esc_js(__('Overwrite', 'nggallery')); ?>', $selected); 
  219. break; 
  220. case 'rotate_cw': 
  221. ajaxOperation('rotate_cw', '<?php echo esc_js(__('Rotate images', 'nggallery')); ?>', $selected); 
  222. break; 
  223. case 'rotate_ccw': 
  224. ajaxOperation('rotate_ccw', '<?php echo esc_js(__('Rotate images', 'nggallery')); ?>', $selected); 
  225. break; 
  226. default: 
  227. console.log($selected); 
  228. var images = $selected.map(function() { 
  229. return this.value; 
  230. }).get(); 
  231. var message = '<?php echo sprintf(esc_js(__("You are about to start bulk edits for %s galleries\n\n 'Cancel' to stop, 'OK' to proceed.", 'nggallery' )), "' + images.length + '") ?>'; 
  232. return confirm(message); 
  233. return false; 
  234.  
  235. function set_TB_command(id, command) { 
  236. jQuery('#' + id + "_dialog #TB_action").val(command); 
  237.  
  238. function ajaxOperation(command, title, $selected, warning) { 
  239.  
  240. var images = $selected.map(function() { 
  241. return this.value; 
  242. }).get(); 
  243.  
  244. if (warning) { 
  245. var message = '<?php echo sprintf(esc_js(__("You are about to start bulk edits for %s galleries\n\n 'Cancel' to stop, 'OK' to proceed.", 'nggallery' )), "' + images.length + '") ?>'; 
  246.  
  247. if (!confirm(message)) { 
  248. return false; 
  249.  
  250. var ajaxOptions = { 
  251. operation: command,  
  252. ids: images,  
  253. header: title,  
  254. maxStep: images.length 
  255. }; 
  256.  
  257. nggProgressBar.init(ajaxOptions); 
  258. nggAjax.init(ajaxOptions); 
  259.  
  260. function bulkDialog(id, title, $selected) { 
  261. jQuery('#' + id + "_bulkaction").val(id); 
  262. jQuery('#' + id + "_imagelist").val($selected.map(function() { 
  263. return this.value; 
  264. }).get().join(', ')); 
  265. showDialog('#' + id + "_dialog", title); 
  266.  
  267. function showDialog(id, title, onSubmit) { 
  268.  
  269. if (typeof onSubmit === 'undefined' || onSubmit === null) { 
  270. onSubmit = function(dialog) { 
  271. jQuery(dialog).submit(); 
  272.  
  273. jQuery(id).dialog({ 
  274. width: '50%',  
  275. resizable: true,  
  276. modal: true,  
  277. title: title,  
  278. close: function() { 
  279. jQuery(this).dialog('destroy').remove(); 
  280. },  
  281. buttons: [ 
  282. text: "<?php echo esc_js(__('Cancel', 'nggallery')); ?>",  
  283. 'class': "button dialog-cancel",  
  284. 'type': "reset",  
  285. click: function() { 
  286. jQuery(this).dialog('close'); 
  287. },  
  288. text: "<?php echo esc_js(__('OK', 'nggallery')); ?>",  
  289. 'class': "button-primary",  
  290. 'type': "submit",  
  291. click: function() { 
  292. onSubmit(this); 
  293. }); 
  294. </script> 
  295. <?php 
  296.  
  297. /** 
  298. * Handle the actions that require a dialog. 
  299. */ 
  300. protected function handle_dialog_actions() { 
  301.  
  302. $ngg_options = get_option( 'ngg_options' ); 
  303.  
  304. /** 
  305. * If the post type is 
  306. */ 
  307. if ( $_POST['TB_type'] === 'gallery' ) { 
  308. $mode = 'gallery'; 
  309. } else { 
  310. $mode = 'image'; 
  311.  
  312. check_admin_referer( 'ngg_thickbox_form' ); 
  313.  
  314. $list = explode( ', ', $_POST['TB_imagelist'] ); 
  315.  
  316. switch ( $_POST['TB_action'] ) { 
  317. case 'resize_images': 
  318. $data = array( 
  319. 'width' => (int) $_POST['imgWidth'],  
  320. 'height' => (int) $_POST['imgHeight'] 
  321. ); 
  322. $command = 'resize_image'; 
  323. $title = __( 'Resize images', 'nggallery' ); 
  324. nggAdmin::do_ajax_operation( $command, $list, $title, $mode, $data ); 
  325. return; 
  326. case 'new_thumbnails': 
  327. $data = array( 
  328. 'width' => (int) $_POST['thumbwidth'],  
  329. 'height' => (int) $_POST['thumbheight'],  
  330. 'fix' => isset( $_POST['thumb_fix'] ) ? true : false 
  331. ); 
  332. $command = 'create_thumbnail'; 
  333. $title = __( 'Create new thumbnails', 'nggallery' ); 
  334. nggAdmin::do_ajax_operation( $command, $list, $title, $mode, $data ); 
  335. return; 
  336. case 'copy_to': 
  337. $dest_gid = (int) $_POST['dest_gid']; 
  338. nggAdmin::copy_images( $list, $dest_gid ); 
  339.  
  340. return; 
  341. case 'move_to': 
  342. $dest_gid = (int) $_POST['dest_gid']; 
  343. nggAdmin::move_images( $list, $dest_gid ); 
  344.  
  345. return; 
  346. case 'add_tags': 
  347. $tag_list = explode( ', ', $_POST['taglist'] ); 
  348. $tag_list = array_map( 'trim', $tag_list ); 
  349. if ( is_array( $list ) ) { 
  350. foreach ( $list as $pic_id ) { 
  351. wp_set_object_terms( $pic_id, $tag_list, 'ngg_tag', true ); 
  352. nggGallery::show_message( __( 'Tags changed', 'nggallery' ) ); 
  353.  
  354. return; 
  355. case 'delete_tags': 
  356. $tag_list = explode( ', ', $_POST['taglist'] ); 
  357. $tag_list = array_map( 'trim', $tag_list ); 
  358. if ( is_array( $list ) ) { 
  359. foreach ( $list as $pic_id ) { 
  360. $old_tags = wp_get_object_terms( $pic_id, 'ngg_tag', 'fields=names' ); 
  361. // get the slugs, to vaoid case sensitive problems 
  362. $slug_array = array_map( 'sanitize_title', $tag_list ); 
  363. $old_tags = array_map( 'sanitize_title', $old_tags ); 
  364. // compare them and return the diff 
  365. $new_tags = array_diff( $old_tags, $slug_array ); 
  366. wp_set_object_terms( $pic_id, $new_tags, 'ngg_tag' ); 
  367. nggGallery::show_message( __( 'Tags changed', 'nggallery' ) ); 
  368.  
  369. return; 
  370. case 'overwrite_tags': 
  371. $tag_list = explode( ', ', $_POST['taglist'] ); 
  372. $tag_list = array_map( 'trim', $tag_list ); 
  373. if ( is_array( $list ) ) { 
  374. foreach ( $list as $pic_id ) { 
  375. wp_set_object_terms( $pic_id, $tag_list, 'ngg_tag' ); 
  376. nggGallery::show_message( __( 'Tags changed', 'nggallery' ) ); 
  377.  
  378. return; 
  379. default: 
  380. return; 
  381.  
  382. /** 
  383. * Handle the bulk actions. 
  384. */ 
  385. protected function handle_bulk_actions() { 
  386. //Check the nonce. 
  387. if ( wp_verify_nonce( $_POST['_wpnonce'], 'bulk-ngg-manager' ) === false ) { 
  388. nggGallery::show_error( __( 'You waited too long, or you cheated.', 'nggallery' ) ); 
  389.  
  390. return; 
  391.  
  392. global $wpdb, $ngg; 
  393.  
  394. if ( $_POST['action'] !== "-1" && $_POST['action2'] !== "-1" ) { 
  395. return; 
  396.  
  397. $a1 = $_POST['action']; 
  398. $a2 = $_POST['action2']; 
  399.  
  400. if ( $a1 === "delete_gallery" || $a2 === "delete_gallery" ) { 
  401. // Delete gallery 
  402. if ( is_array( $_POST['doaction'] ) ) { 
  403. $deleted = false; 
  404. foreach ( $_POST['doaction'] as $id ) { 
  405. // get the path to the gallery 
  406. $gallery = nggdb::find_gallery( $id ); 
  407. if ( $gallery ) { 
  408. //TODO:Remove also Tag reference, look here for ids instead filename 
  409. $imagelist = $wpdb->get_col( "SELECT filename FROM $wpdb->nggpictures WHERE galleryid = '$gallery->gid' " ); 
  410. if ( $ngg->options['deleteImg'] ) { 
  411. if ( is_array( $imagelist ) ) { 
  412. foreach ( $imagelist as $filename ) { 
  413. @unlink( WINABSPATH . $gallery->path . '/thumbs/thumbs_' . $filename ); 
  414. @unlink( WINABSPATH . $gallery->path . '/' . $filename ); 
  415. @unlink( WINABSPATH . $gallery->path . '/' . $filename . '_backup' ); 
  416. // delete folder 
  417. @rmdir( WINABSPATH . $gallery->path . '/thumbs' ); 
  418. @rmdir( WINABSPATH . $gallery->path ); 
  419. do_action( 'ngg_delete_gallery', $id ); 
  420. $deleted = nggdb::delete_gallery( $id ); 
  421.  
  422. if ( $deleted ) { 
  423. nggGallery::show_message( __( 'Gallery deleted successfully.', 'nggallery' ) ); 
  424. } else { 
  425. nggGallery::show_error( __( 'Something went wrong.', 'nggallery' ) ); 
  426.  
  427. } elseif ( $a1 === "delete_images" || $a2 === "delete_images" ) { 
  428. global $nggdb; 
  429. if ( is_array( $_POST['doaction'] ) ) { 
  430. foreach ( $_POST['doaction'] as $imageID ) { 
  431. $image = $nggdb->find_image( $imageID ); 
  432. if ( $image ) { 
  433. if ( $ngg->options['deleteImg'] ) { 
  434. @unlink( $image->imagePath ); 
  435. @unlink( $image->thumbPath ); 
  436. @unlink( $image->imagePath . "_backup" ); 
  437. do_action( 'ngg_delete_picture', $image->pid ); 
  438. $delete_pic = nggdb::delete_image( $image->pid ); 
  439. if ( $delete_pic ) { 
  440. nggGallery::show_message( __( 'Pictures deleted successfully ', 'nggallery' ) ); 
.