| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | // Disable direct load |
|---|
| 4 | if ( ! defined( 'ABSPATH' ) ) { |
|---|
| 5 | die( '-1' ); |
|---|
| 6 | } |
|---|
| 7 | |
|---|
| 8 | final class Wicked_Folders_Ajax { |
|---|
| 9 | |
|---|
| 10 | private static $instance; |
|---|
| 11 | |
|---|
| 12 | private function __construct() { |
|---|
| 13 | |
|---|
| 14 | add_action( 'wp_ajax_wicked_folders_save_state', array( $this, 'ajax_save_state' ) ); |
|---|
| 15 | add_action( 'wp_ajax_wicked_folders_move_object', array( $this, 'ajax_move_object' ) ); |
|---|
| 16 | add_action( 'wp_ajax_wicked_folders_add_folder', array( $this, 'ajax_add_folder' ) ); |
|---|
| 17 | add_action( 'wp_ajax_wicked_folders_clone_folder', array( $this, 'ajax_clone_folder' ) ); |
|---|
| 18 | add_action( 'wp_ajax_wicked_folders_edit_folder', array( $this, 'ajax_edit_folder' ) ); |
|---|
| 19 | add_action( 'wp_ajax_wicked_folders_delete_folder', array( $this, 'ajax_delete_folder' ) ); |
|---|
| 20 | add_action( 'wp_ajax_wicked_folders_save_folder', array( $this, 'ajax_save_folder' ) ); |
|---|
| 21 | add_action( 'wp_ajax_wicked_folders_save_sort_order', array( $this, 'ajax_save_sort_order' ) ); |
|---|
| 22 | add_action( 'wp_ajax_wicked_folders_dismiss_message', array( $this, 'ajax_dismiss_message' ) ); |
|---|
| 23 | add_action( 'wp_ajax_wicked_folders_get_child_folders', array( $this, 'ajax_get_child_folders' ) ); |
|---|
| 24 | add_action( 'wp_ajax_wicked_folders_unassign_folders', array( $this, 'ajax_unassign_folders' ) ); |
|---|
| 25 | add_action( 'wp_ajax_wicked_folders_save_folder_order', array( $this, 'ajax_save_folder_order' ) ); |
|---|
| 26 | add_action( 'wp_ajax_wicked_folders_fetch_folders', array( $this, 'ajax_fetch_folders' ) ); |
|---|
| 27 | |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | public static function get_instance() { |
|---|
| 31 | if ( empty( self::$instance ) ) { |
|---|
| 32 | self::$instance = new Wicked_Folders_Ajax(); |
|---|
| 33 | } |
|---|
| 34 | return self::$instance; |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | /** |
|---|
| 38 | * Admin AJAX callback for moving an item to a new folder. |
|---|
| 39 | * |
|---|
| 40 | * @uses Wicked_Folders::move_object |
|---|
| 41 | * @see Wicked_Folders::move_object |
|---|
| 42 | */ |
|---|
| 43 | public function ajax_move_object() { |
|---|
| 44 | |
|---|
| 45 | $result = array( 'error' => false, 'items' => array(), 'folders' => array() ); |
|---|
| 46 | $nonce = isset( $_REQUEST['nonce'] ) ? sanitize_text_field( $_REQUEST['nonce'] ) : false; |
|---|
| 47 | $object_type = isset( $_REQUEST['object_type'] ) ? sanitize_text_field( $_REQUEST['object_type'] ) : false; |
|---|
| 48 | $object_id = isset( $_REQUEST['object_id'] ) ? array_map( 'absint', $_REQUEST['object_id'] ) : false; |
|---|
| 49 | $destination_object_id = isset( $_REQUEST['destination_object_id'] ) ? (int) $_REQUEST['destination_object_id'] : false; |
|---|
| 50 | $source_folder_id = isset( $_REQUEST['source_folder_id'] ) ? (int) $_REQUEST['source_folder_id'] : false; |
|---|
| 51 | $post_type = isset( $_REQUEST['post_type'] ) ? sanitize_text_field( $_REQUEST['post_type'] ) : false; |
|---|
| 52 | |
|---|
| 53 | /* |
|---|
| 54 | if ( ! wp_verify_nonce( $nonce, 'wicked_folders_move_object' ) ) { |
|---|
| 55 | $result['error'] = true; |
|---|
| 56 | } |
|---|
| 57 | */ |
|---|
| 58 | |
|---|
| 59 | if ( ! $object_type || ! false === $object_id || ! false === $destination_object_id ) { |
|---|
| 60 | $result['error'] = true; |
|---|
| 61 | } |
|---|
| 62 | |
|---|
| 63 | if ( ! $result['error'] ) { |
|---|
| 64 | foreach ( $object_id as $id ) { |
|---|
| 65 | Wicked_Folders::move_object( $object_type, ( int ) $id, $destination_object_id, $source_folder_id ); |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | // Folders are used in response to update item counts |
|---|
| 69 | $result['folders'] = Wicked_Folders::get_folders( $post_type ); |
|---|
| 70 | } |
|---|
| 71 | |
|---|
| 72 | echo json_encode( $result ); |
|---|
| 73 | |
|---|
| 74 | wp_die(); |
|---|
| 75 | |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | /** |
|---|
| 79 | * Admin AJAX callback that unassigns folders from an item. |
|---|
| 80 | * |
|---|
| 81 | */ |
|---|
| 82 | public function ajax_unassign_folders() { |
|---|
| 83 | |
|---|
| 84 | $result = array( 'error' => false, 'items' => array(), 'folders' => array() ); |
|---|
| 85 | $nonce = isset( $_REQUEST['nonce'] ) ? sanitize_text_field( $_REQUEST['nonce'] ) : false; |
|---|
| 86 | $taxonomy = isset( $_REQUEST['taxonomy'] ) ? sanitize_key( $_REQUEST['taxonomy'] ) : false; |
|---|
| 87 | $object_id = isset( $_REQUEST['object_id'] ) ? array_map( 'absint', $_REQUEST['object_id'] ) : false; |
|---|
| 88 | $post_type = Wicked_Folders::get_post_name_from_tax_name( $taxonomy ); |
|---|
| 89 | $policy = false; |
|---|
| 90 | $user_id = get_current_user_id(); |
|---|
| 91 | |
|---|
| 92 | if ( class_exists( 'Wicked_Folders_Folder_Collection_Policy' ) ) { |
|---|
| 93 | $policy = Wicked_Folders_Folder_Collection_Policy::get_taxonomy_policy( $taxonomy ); |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | /* |
|---|
| 97 | if ( ! wp_verify_nonce( $nonce, 'wicked_folders_move_object' ) ) { |
|---|
| 98 | $result['error'] = true; |
|---|
| 99 | } |
|---|
| 100 | */ |
|---|
| 101 | |
|---|
| 102 | if ( ! $taxonomy ) { |
|---|
| 103 | $result['error'] = true; |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| 106 | if ( ! $result['error'] ) { |
|---|
| 107 | foreach ( $object_id as $id ) { |
|---|
| 108 | $folder_ids = array(); |
|---|
| 109 | |
|---|
| 110 | // If a policy exists for the taxonomy, only unassign folders |
|---|
| 111 | // from the object that the user has assign permission for |
|---|
| 112 | if ( $policy ) { |
|---|
| 113 | $folder_ids = wp_get_object_terms( $id, $taxonomy, array( 'fields' => 'ids' ) ); |
|---|
| 114 | |
|---|
| 115 | for ( $i = count( $folder_ids ) - 1; $i > -1; $i-- ) { |
|---|
| 116 | if ( $policy->can_assign( $folder_ids[ $i ], $user_id ) ) { |
|---|
| 117 | unset( $folder_ids[ $i ] ); |
|---|
| 118 | } |
|---|
| 119 | } |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | $update_terms_result = wp_set_object_terms( ( int ) $id, $folder_ids, $taxonomy ); |
|---|
| 123 | |
|---|
| 124 | $result['items'][] = array( |
|---|
| 125 | 'objectId' => $id, |
|---|
| 126 | 'taxonomy' => $taxonomy, |
|---|
| 127 | 'result' => $update_terms_result, |
|---|
| 128 | ); |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | // Folders are used in response to update item counts |
|---|
| 132 | $result['folders'] = Wicked_Folders::get_folders( $post_type ); |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | echo json_encode( $result ); |
|---|
| 136 | |
|---|
| 137 | wp_die(); |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | public function ajax_save_state() { |
|---|
| 141 | |
|---|
| 142 | $result = array( 'error' => false ); |
|---|
| 143 | $data = json_decode( file_get_contents( 'php://input' ) ); |
|---|
| 144 | //$nonce = $data->nonce; |
|---|
| 145 | $screen = $data->screen; |
|---|
| 146 | $state = new Wicked_Folders_Screen_State( $screen, get_current_user_id(), $data->lang ); |
|---|
| 147 | |
|---|
| 148 | $state->folder = isset( $data->folder->id ) ? $data->folder->id : '0'; |
|---|
| 149 | $state->folder_type = isset( $data->folder->type ) ? $data->folder->type : 'Wicked_Folders_Folder'; |
|---|
| 150 | $state->expanded_folders = $data->expanded; |
|---|
| 151 | $state->tree_pane_width = $data->treePaneWidth; |
|---|
| 152 | $state->orderby = $data->orderby; |
|---|
| 153 | $state->order = $data->order; |
|---|
| 154 | $state->is_folder_pane_visible = $data->isFolderPaneVisible; |
|---|
| 155 | $state->sort_mode = $data->sortMode; |
|---|
| 156 | |
|---|
| 157 | if ( isset( $data->hideAssignedItems ) ) { |
|---|
| 158 | $state->hide_assigned_items = $data->hideAssignedItems; |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | $state->save(); |
|---|
| 162 | |
|---|
| 163 | echo json_encode( $result ); |
|---|
| 164 | |
|---|
| 165 | wp_die(); |
|---|
| 166 | |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | public function ajax_add_folder() { |
|---|
| 170 | |
|---|
| 171 | $this->ajax_edit_folder(); |
|---|
| 172 | |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | public function ajax_edit_folder() { |
|---|
| 176 | |
|---|
| 177 | $result = array( 'error' => false, 'message' => __( 'An error occurred. Please try again.', 'wicked-folders' ) ); |
|---|
| 178 | $nonce = isset( $_REQUEST['nounce'] ) ? sanitize_text_field( $_REQUEST['nounce'] ) : false; |
|---|
| 179 | $id = isset( $_REQUEST['id'] ) ? ( int ) $_REQUEST['id'] : false; |
|---|
| 180 | $name = isset( $_REQUEST['name'] ) ? sanitize_text_field( $_REQUEST['name'] ) : false; |
|---|
| 181 | $parent = isset( $_REQUEST['parent'] ) ? ( int ) $_REQUEST['parent'] : false; |
|---|
| 182 | $post_type = isset( $_REQUEST['post_type'] ) ? sanitize_key( $_REQUEST['post_type'] ) : false; |
|---|
| 183 | $tax_name = Wicked_Folders::get_tax_name( $post_type ); |
|---|
| 184 | $url = admin_url( 'edit.php?post_type=' . $post_type . '&page=' . $tax_name ); |
|---|
| 185 | |
|---|
| 186 | //if ( ! wp_verify_nonce( $nonce, 'wicked_folders_add_folder' ) ) { |
|---|
| 187 | // $result['error'] = true; |
|---|
| 188 | //} |
|---|
| 189 | |
|---|
| 190 | if ( ! $name || ! $post_type ) { |
|---|
| 191 | $result['message'] = __( 'Invalid name or post type.', 'wicked-folders' ); |
|---|
| 192 | $result['error'] = true; |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | if ( -1 == $parent || false === $parent ) { |
|---|
| 196 | $parent = 0; |
|---|
| 197 | } |
|---|
| 198 | |
|---|
| 199 | if ( ! $result['error'] ) { |
|---|
| 200 | if ( $id ) { |
|---|
| 201 | $existing_term = get_term_by( 'name', $name, $tax_name ); |
|---|
| 202 | // Don't allow terms with the same name at the same level |
|---|
| 203 | if ( $existing_term && $existing_term->parent == $parent ) { |
|---|
| 204 | $term = new WP_Error( 'term_exists' ); |
|---|
| 205 | } else { |
|---|
| 206 | $term = wp_update_term( $id, $tax_name, array( |
|---|
| 207 | 'name' => $name, |
|---|
| 208 | 'parent' => $parent, |
|---|
| 209 | ) ); |
|---|
| 210 | } |
|---|
| 211 | } else { |
|---|
| 212 | $term = wp_insert_term( $name, $tax_name, array( |
|---|
| 213 | 'parent' => $parent, |
|---|
| 214 | ) ); |
|---|
| 215 | } |
|---|
| 216 | if ( is_wp_error( $term ) ) { |
|---|
| 217 | if ( isset( $term->errors['term_exists'] ) ) { |
|---|
| 218 | $result['message'] = __( 'A folder with that name already exists in the selected parent folder. Please enter a different name or select a different parent folder.', 'wicked-folders' ); |
|---|
| 219 | } else { |
|---|
| 220 | $result['message'] = $term->get_error_message(); |
|---|
| 221 | } |
|---|
| 222 | $result['error'] = true; |
|---|
| 223 | } else { |
|---|
| 224 | $select = wp_dropdown_categories( array( |
|---|
| 225 | 'orderby' => 'name', |
|---|
| 226 | 'order' => 'ASC', |
|---|
| 227 | 'show_option_none' => '— ' . __( 'Parent Folder', 'wicked-folders' ) . ' —', |
|---|
| 228 | 'taxonomy' => $tax_name, |
|---|
| 229 | 'depth' => 0, |
|---|
| 230 | 'hierarchical' => true, |
|---|
| 231 | 'hide_empty' => false, |
|---|
| 232 | 'selected' => $parent, |
|---|
| 233 | 'echo' => false, |
|---|
| 234 | 'option_none_value' => 0, |
|---|
| 235 | ) ); |
|---|
| 236 | $result = array( |
|---|
| 237 | 'error' => false, |
|---|
| 238 | 'folderId' => $term['term_id'], |
|---|
| 239 | 'folderUrl' => add_query_arg( 'folder', $term['term_id'], $url ), |
|---|
| 240 | 'select' => $select, |
|---|
| 241 | ); |
|---|
| 242 | } |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | echo json_encode( $result ); |
|---|
| 246 | |
|---|
| 247 | wp_die(); |
|---|
| 248 | |
|---|
| 249 | } |
|---|
| 250 | |
|---|
| 251 | public function ajax_delete_folder() { |
|---|
| 252 | |
|---|
| 253 | // TODO: check nonce |
|---|
| 254 | $result = array( 'error' => false ); |
|---|
| 255 | $nonce = isset( $_REQUEST['nounce'] ) ? sanitize_text_field( $_REQUEST['nounce'] ) : false; |
|---|
| 256 | $id = isset( $_REQUEST['id'] ) ? ( int ) $_REQUEST['id'] : false; |
|---|
| 257 | $post_type = isset( $_REQUEST['post_type'] ) ? sanitize_key( $_REQUEST['post_type'] ) : false; |
|---|
| 258 | $taxonomy = isset( $_REQUEST['taxonomy'] ) ? sanitize_key( $_REQUEST['taxonomy'] ) : Wicked_Folders::get_tax_name( $post_type ); |
|---|
| 259 | |
|---|
| 260 | $delete_result = wp_delete_term( $id, $taxonomy ); |
|---|
| 261 | |
|---|
| 262 | if ( is_wp_error( $delete_result ) ) { |
|---|
| 263 | $result['error'] = true; |
|---|
| 264 | $result['message'] = $delete_result->get_error_message(); |
|---|
| 265 | } |
|---|
| 266 | |
|---|
| 267 | echo json_encode( $result ); |
|---|
| 268 | |
|---|
| 269 | wp_die(); |
|---|
| 270 | |
|---|
| 271 | } |
|---|
| 272 | |
|---|
| 273 | public function ajax_save_folder() { |
|---|
| 274 | |
|---|
| 275 | $response = array( 'error' => false ); |
|---|
| 276 | //$method = $_SERVER['REQUEST_METHOD']; |
|---|
| 277 | $method = isset( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ) ? $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] : 'POST'; |
|---|
| 278 | $method = isset( $_REQUEST['_method_override'] ) ? sanitize_text_field( $_REQUEST['_method_override'] ) : $method; |
|---|
| 279 | $folder = json_decode( file_get_contents( 'php://input' ) ); |
|---|
| 280 | $policy = false; |
|---|
| 281 | $user_id = get_current_user_id(); |
|---|
| 282 | |
|---|
| 283 | if ( 'DELETE' == $method ) { |
|---|
| 284 | $folder_id = ( int ) $_REQUEST['id']; |
|---|
| 285 | $taxonomy = sanitize_key( $_REQUEST['taxonomy'] ); |
|---|
| 286 | } else { |
|---|
| 287 | $folder_id = isset( $folder->id ) ? $folder->id : null; |
|---|
| 288 | $taxonomy = $folder->taxonomy; |
|---|
| 289 | } |
|---|
| 290 | |
|---|
| 291 | // The Polylang plugin uses the jQuery ajaxPrefilter function to alter |
|---|
| 292 | // AJAX requests which breaks the request (see polylang/js/media.js). |
|---|
| 293 | // The following code checks to see if the Polylang plugin is active and, |
|---|
| 294 | // if so, removes the string added by the Polylang plugin so the request |
|---|
| 295 | // can be processed properly. |
|---|
| 296 | if ( function_exists( 'is_plugin_active' ) && ( is_plugin_active( 'polylang/polylang.php' ) || is_plugin_active( 'polylang-pro/polylang.php' ) ) ) { |
|---|
| 297 | $data = file_get_contents( 'php://input' ); |
|---|
| 298 | $data = preg_replace( '/^pll_post_id=([0-9|undefined]*)?&/', '', $data ); |
|---|
| 299 | $data = preg_replace( '/&pll_ajax_backend=1/', '', $data ); |
|---|
| 300 | $folder = json_decode( $data ); |
|---|
| 301 | } |
|---|
| 302 | |
|---|
| 303 | // Similar issue with Anything Order by Terms plugin; adds a screen_id |
|---|
| 304 | // parameter (see anything-order-by-terms/modules/base/script.js) which |
|---|
| 305 | // breaks the request |
|---|
| 306 | if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'anything-order-by-terms/anything-order.php' ) ) { |
|---|
| 307 | $data = file_get_contents( 'php://input' ); |
|---|
| 308 | $data = preg_replace( '/&screen_id=([A-Z\-\_0-9]*)/i', '', $data ); |
|---|
| 309 | $folder = json_decode( $data ); |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | if ( class_exists( 'Wicked_Folders_Folder_Collection_Policy' ) ) { |
|---|
| 313 | $policy = Wicked_Folders_Folder_Collection_Policy::get_taxonomy_policy( $taxonomy ); |
|---|
| 314 | |
|---|
| 315 | // If there's a security policy, enforce it |
|---|
| 316 | if ( $policy ) { |
|---|
| 317 | if ( |
|---|
| 318 | ( 'POST' == $method && false == $policy->can_create( $user_id ) ) || |
|---|
| 319 | ( 'PUT' == $method && false == $policy->can_edit( $folder_id, $user_id ) ) || |
|---|
| 320 | ( 'DELETE' == $method && false == $policy->can_delete( $folder_id, $user_id ) ) |
|---|
| 321 | ) { |
|---|
| 322 | $response['message'] = __( 'Permission denied.', 'wicked-folders' ); |
|---|
| 323 | $response['error'] = true; |
|---|
| 324 | |
|---|
| 325 | status_header( 400 ); |
|---|
| 326 | |
|---|
| 327 | echo json_encode( $response ); |
|---|
| 328 | |
|---|
| 329 | die(); |
|---|
| 330 | } |
|---|
| 331 | } |
|---|
| 332 | } |
|---|
| 333 | |
|---|
| 334 | // Insert folder |
|---|
| 335 | if ( 'POST' == $method ) { |
|---|
| 336 | // TODO: Refactor. We should be working with a proper folder object |
|---|
| 337 | // that is initalized from the JSON in the request and then |
|---|
| 338 | // serialized as JSON |
|---|
| 339 | $term = wp_insert_term( $folder->name, $folder->taxonomy, array( |
|---|
| 340 | 'parent' => $folder->parent, |
|---|
| 341 | 'slug' => Wicked_Folders_Term_Folder::generate_unique_slug( $folder->name, $folder->taxonomy ), |
|---|
| 342 | ) ); |
|---|
| 343 | |
|---|
| 344 | if ( ! is_wp_error( $term ) ) { |
|---|
| 345 | $owner_data = get_userdata( $user_id ); |
|---|
| 346 | $folder->id = ( string ) $term['term_id']; |
|---|
| 347 | $folder->ownerId = $user_id; |
|---|
| 348 | $folder->ownerName = isset( $owner_data->data->display_name ) ? $owner_data->data->display_name : ''; |
|---|
| 349 | |
|---|
| 350 | add_term_meta( $term['term_id'], 'wf_owner_id', $user_id ); |
|---|
| 351 | } |
|---|
| 352 | } |
|---|
| 353 | |
|---|
| 354 | // Update folder |
|---|
| 355 | if ( 'PUT' == $method ) { |
|---|
| 356 | $term = wp_update_term( $folder->id, $folder->taxonomy, array( |
|---|
| 357 | 'name' => $folder->name, |
|---|
| 358 | 'parent' => $folder->parent, |
|---|
| 359 | ) ); |
|---|
| 360 | |
|---|
| 361 | update_term_meta( $folder->id, 'wf_owner_id', ( int ) $folder->ownerId ); |
|---|
| 362 | } |
|---|
| 363 | |
|---|
| 364 | // Delete folder |
|---|
| 365 | if ( 'DELETE' == $method ) { |
|---|
| 366 | $term = wp_delete_term( ( int ) $_REQUEST['id'], sanitize_key( $_REQUEST['taxonomy'] ) ); |
|---|
| 367 | // Delete the sort meta for the folder |
|---|
| 368 | delete_metadata( 'post', 0, '_wicked_folder_order__' . sanitize_key( $_REQUEST['taxonomy'] ) . '__' . sanitize_text_field( $_REQUEST['id'] ), false, true ); |
|---|
| 369 | } |
|---|
| 370 | |
|---|
| 371 | if ( is_wp_error( $term ) ) { |
|---|
| 372 | if ( isset( $term->errors['term_exists'] ) ) { |
|---|
| 373 | $response['message'] = __( 'A folder with that name already exists in the selected parent folder. Please enter a different name or select a different parent folder.', 'wicked-folders' ); |
|---|
| 374 | } else { |
|---|
| 375 | $response['message'] = $term->get_error_message(); |
|---|
| 376 | } |
|---|
| 377 | $response['error'] = true; |
|---|
| 378 | status_header( 400 ); |
|---|
| 379 | echo json_encode( $response ); |
|---|
| 380 | die(); |
|---|
| 381 | } else { |
|---|
| 382 | echo json_encode( $folder ); |
|---|
| 383 | } |
|---|
| 384 | |
|---|
| 385 | wp_die(); |
|---|
| 386 | |
|---|
| 387 | } |
|---|
| 388 | |
|---|
| 389 | public function ajax_clone_folder() { |
|---|
| 390 | $folders = array(); |
|---|
| 391 | $id = isset( $_REQUEST['id'] ) ? ( int ) $_REQUEST['id'] : false; |
|---|
| 392 | $post_type = isset( $_REQUEST['post_type'] ) ? sanitize_key( $_REQUEST['post_type'] ) : false; |
|---|
| 393 | $parent = isset( $_REQUEST['parent'] ) ? ( int ) $_REQUEST['parent'] : false; |
|---|
| 394 | $clone_children = isset( $_REQUEST['clone_children'] ) && 'true' == $_REQUEST['clone_children'] ? true : false; |
|---|
| 395 | $taxonomy = Wicked_Folders::get_tax_name( $post_type ); |
|---|
| 396 | $user_id = get_current_user_id(); |
|---|
| 397 | |
|---|
| 398 | try { |
|---|
| 399 | if ( class_exists( 'Wicked_Folders_Folder_Collection_Policy' ) ) { |
|---|
| 400 | $policy = Wicked_Folders_Folder_Collection_Policy::get_taxonomy_policy( $taxonomy ); |
|---|
| 401 | |
|---|
| 402 | // If there's a security policy, enforce it |
|---|
| 403 | if ( $policy ) { |
|---|
| 404 | // Require edit permission to clone folder |
|---|
| 405 | if ( ! $policy->can_edit( $id, $user_id ) ) { |
|---|
| 406 | throw new Exception( __( 'Permission denied.', 'wicked-folders' ) ); |
|---|
| 407 | } |
|---|
| 408 | } |
|---|
| 409 | } |
|---|
| 410 | |
|---|
| 411 | $folder = Wicked_Folders::get_folder( $id, $post_type ); |
|---|
| 412 | $folders = $folder->clone_folder( $clone_children, $parent ); |
|---|
| 413 | |
|---|
| 414 | echo json_encode( $folders ); |
|---|
| 415 | } catch ( Exception $e ) { |
|---|
| 416 | status_header( 400 ); |
|---|
| 417 | |
|---|
| 418 | echo esc_html( $e->getMessage() ); |
|---|
| 419 | |
|---|
| 420 | die(); |
|---|
| 421 | } |
|---|
| 422 | |
|---|
| 423 | wp_die(); |
|---|
| 424 | } |
|---|
| 425 | |
|---|
| 426 | public function ajax_save_sort_order() { |
|---|
| 427 | |
|---|
| 428 | global $wpdb; |
|---|
| 429 | |
|---|
| 430 | $new_order = array(); |
|---|
| 431 | $screen = sanitize_text_field( $_REQUEST['screen'] ); |
|---|
| 432 | $folder_id = sanitize_text_field( $_REQUEST['folder_id'] ); |
|---|
| 433 | $post_type = sanitize_text_field( $_REQUEST['post_type'] ); |
|---|
| 434 | $taxonomy = sanitize_text_field( $_REQUEST['taxonomy'] ); |
|---|
| 435 | $object_ids = array_map( 'absint', $_REQUEST['object_ids'] ); |
|---|
| 436 | $order = sanitize_text_field( $_REQUEST['order'] ); |
|---|
| 437 | $orderby = sanitize_text_field( $_REQUEST['orderby'] ); |
|---|
| 438 | $page_number = ( int ) $_REQUEST['page_number']; |
|---|
| 439 | $items_per_page = ( int ) $_REQUEST['items_per_page']; |
|---|
| 440 | $sort_key = '_wicked_folder_order__' . $taxonomy . '__' . $folder_id; |
|---|
| 441 | $before = $items_per_page * ( $page_number - 1 ); |
|---|
| 442 | $after = $before + $items_per_page; |
|---|
| 443 | |
|---|
| 444 | // Initialize folder order. This will ensure that every post in the folder |
|---|
| 445 | // has an order meta key so that we can update later |
|---|
| 446 | Wicked_Folders::initalize_folder_order( $folder_id, $taxonomy ); |
|---|
| 447 | |
|---|
| 448 | // Get IDs of posts assigned to the folder ordered the same way as they |
|---|
| 449 | // were prior to changing the sort order |
|---|
| 450 | $q = array( |
|---|
| 451 | 'post_type' => $post_type, |
|---|
| 452 | 'posts_per_page' => -1, |
|---|
| 453 | 'fields' => 'ids', |
|---|
| 454 | 'order' => $order, |
|---|
| 455 | 'orderby' => $orderby, |
|---|
| 456 | 'tax_query' => array( |
|---|
| 457 | array( |
|---|
| 458 | 'taxonomy' => $taxonomy, |
|---|
| 459 | 'field' => 'term_id', |
|---|
| 460 | 'terms' => ( int ) $folder_id, |
|---|
| 461 | ) |
|---|
| 462 | ) |
|---|
| 463 | ); |
|---|
| 464 | |
|---|
| 465 | if ( 'wicked_folder_order' == $orderby ) { |
|---|
| 466 | $q['orderby'] = array( |
|---|
| 467 | 'meta_value_num' => $order, |
|---|
| 468 | 'title' => 'ASC', |
|---|
| 469 | ); |
|---|
| 470 | $q['meta_key'] = $sort_key; |
|---|
| 471 | } |
|---|
| 472 | |
|---|
| 473 | $post_ids = get_posts( $q ); |
|---|
| 474 | |
|---|
| 475 | $n = count( $post_ids ); |
|---|
| 476 | |
|---|
| 477 | // Get the order of posts on previous pages |
|---|
| 478 | for ( $i = 0; $i < $before; $i++ ) { |
|---|
| 479 | $new_order[] = $post_ids[ $i ]; |
|---|
| 480 | } |
|---|
| 481 | |
|---|
| 482 | // Append the new order of posts for the current page |
|---|
| 483 | $new_order = array_merge( $new_order, $object_ids ); |
|---|
| 484 | |
|---|
| 485 | // Add posts from subsequent pages |
|---|
| 486 | for ( $i = $after; $i < $n; $i++ ) { |
|---|
| 487 | $new_order[] = $post_ids[ $i ]; |
|---|
| 488 | } |
|---|
| 489 | |
|---|
| 490 | // Get the current sort orders |
|---|
| 491 | $current_order = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_value FROM {$wpdb->prefix}postmeta WHERE meta_key = %s ORDER BY post_id", $sort_key ), OBJECT_K ); |
|---|
| 492 | |
|---|
| 493 | foreach ( $new_order as $index => $post_id ) { |
|---|
| 494 | $sort = ( $n - $index ) * -1; |
|---|
| 495 | // Only update posts where the sort order has changed |
|---|
| 496 | if ( $sort != $current_order[ $post_id ]->meta_value ) { |
|---|
| 497 | $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}postmeta SET meta_value = %s WHERE post_id = %d AND meta_key = %s", $sort, $post_id, $sort_key ) ); |
|---|
| 498 | } |
|---|
| 499 | } |
|---|
| 500 | |
|---|
| 501 | } |
|---|
| 502 | |
|---|
| 503 | public function ajax_dismiss_message() { |
|---|
| 504 | $result = array( 'error' => false ); |
|---|
| 505 | $dismissed_messages = ( array ) get_user_option( 'wicked_folders_dismissed_messages' ); |
|---|
| 506 | $dismissed_messages[] = $_POST['key']; |
|---|
| 507 | |
|---|
| 508 | update_user_meta( get_current_user_id(), 'wicked_folders_dismissed_messages', $dismissed_messages ); |
|---|
| 509 | |
|---|
| 510 | echo json_encode( $result ); |
|---|
| 511 | |
|---|
| 512 | wp_die(); |
|---|
| 513 | } |
|---|
| 514 | |
|---|
| 515 | public function ajax_get_child_folders() { |
|---|
| 516 | global $wpdb; |
|---|
| 517 | |
|---|
| 518 | $folders = array(); |
|---|
| 519 | $folder_type = sanitize_text_field( $_REQUEST['folder_type'] ); |
|---|
| 520 | $folder_id = sanitize_key( $_REQUEST['folder_id'] ); |
|---|
| 521 | $post_type = sanitize_key( $_REQUEST['post_type'] ); |
|---|
| 522 | |
|---|
| 523 | $folder = Wicked_Folders::get_dynamic_folder( $folder_type, $folder_id, $post_type ); |
|---|
| 524 | |
|---|
| 525 | if ( $folder ) { |
|---|
| 526 | $folder->fetch(); |
|---|
| 527 | $folders = $folder->get_child_folders(); |
|---|
| 528 | } |
|---|
| 529 | |
|---|
| 530 | echo json_encode( $folders ); |
|---|
| 531 | |
|---|
| 532 | wp_die(); |
|---|
| 533 | } |
|---|
| 534 | |
|---|
| 535 | public function ajax_save_folder_order() { |
|---|
| 536 | global $wpdb; |
|---|
| 537 | |
|---|
| 538 | $result = array( 'error' => false ); |
|---|
| 539 | $folders = isset( $_REQUEST['folders'] ) && is_array( $_REQUEST['folders' ] ) ? array_map( array( $this, 'sanitize_folder_order_param' ), $_REQUEST['folders'] ) : array(); |
|---|
| 540 | $order_field_exists = Wicked_Folders::get_instance()->term_order_field_exists(); |
|---|
| 541 | |
|---|
| 542 | foreach ( $folders as $folder ) { |
|---|
| 543 | update_term_meta( $folder['id'], 'wf_order', ( int ) $folder['order'] ); |
|---|
| 544 | |
|---|
| 545 | // Update wp_terms.term_order if the field exists. This field is |
|---|
| 546 | // used by the Category Order and Taxonomy Terms Order plugin so |
|---|
| 547 | // this should ensure that the folders appear in the expected order |
|---|
| 548 | // for users who use this plugin |
|---|
| 549 | if ( $order_field_exists ) { |
|---|
| 550 | $wpdb->update( |
|---|
| 551 | $wpdb->terms, |
|---|
| 552 | array( 'term_order' => $folder['order'] ), |
|---|
| 553 | array( 'term_id' => ( int ) $folder['id'] ), |
|---|
| 554 | array( '%d' ), |
|---|
| 555 | array( '%d' ) |
|---|
| 556 | ); |
|---|
| 557 | } |
|---|
| 558 | } |
|---|
| 559 | |
|---|
| 560 | echo json_encode( $result ); |
|---|
| 561 | |
|---|
| 562 | wp_die(); |
|---|
| 563 | } |
|---|
| 564 | |
|---|
| 565 | public function ajax_fetch_folders() { |
|---|
| 566 | $folders = array(); |
|---|
| 567 | $taxonomy = isset( $_GET['taxonomy'] ) ? sanitize_text_field( $_GET['taxonomy'] ) : false; |
|---|
| 568 | |
|---|
| 569 | if ( $taxonomy ) { |
|---|
| 570 | $post_type = Wicked_Folders::get_post_name_from_tax_name( $taxonomy ); |
|---|
| 571 | |
|---|
| 572 | $folders = Wicked_Folders::get_folders( $post_type, $taxonomy ); |
|---|
| 573 | } |
|---|
| 574 | |
|---|
| 575 | echo json_encode( $folders ); |
|---|
| 576 | |
|---|
| 577 | wp_die(); |
|---|
| 578 | } |
|---|
| 579 | |
|---|
| 580 | /** |
|---|
| 581 | * Sanitizes the value of an entry within a folder order array. |
|---|
| 582 | */ |
|---|
| 583 | public function sanitize_folder_order_param( $value ) { |
|---|
| 584 | return array( |
|---|
| 585 | 'id' => ( int ) $value['id'], |
|---|
| 586 | 'order' => ( int ) $value['order'], |
|---|
| 587 | ); |
|---|
| 588 | } |
|---|
| 589 | } |
|---|