├── .gitignore ├── admin-settings.php ├── admin.php ├── assets ├── images │ ├── add.png │ ├── attention.png │ ├── close_advanced.png │ ├── inactive.png │ ├── information.png │ └── working.png ├── js │ ├── admin-edit.js │ ├── admin-options-validate.js │ ├── admin-options.js │ ├── admin-post.js │ └── jquery.validate.min.js └── scss │ ├── admin-options.scss │ └── admin-post.scss ├── composer.json ├── composer.lock ├── cpt-onomies.php ├── cpt-onomy.php ├── extend └── gravity-forms-custom-post-types.php ├── gulpfile.js ├── languages └── cpt-onomies.pot ├── manager.php ├── package.json ├── readme.txt ├── uninstall.php └── widgets.php /.gitignore: -------------------------------------------------------------------------------- 1 | assets/css 2 | assets/js/*.min.js 3 | vendor 4 | -------------------------------------------------------------------------------- /admin.php: -------------------------------------------------------------------------------- 1 | user_has_term_capabilities() 84 | * removes the ability access this page and throws up a 'Cheatin' uh?' message 85 | * but this function replaces that message with some helpful text on where to go 86 | * to edit the terms. 87 | * 88 | * @since 1.0 89 | * @uses $cpt_onomies_manager, $pagenow 90 | */ 91 | public function deny_edit_tags() { 92 | global $cpt_onomies_manager, $pagenow; 93 | 94 | // Only on the edit tags page. 95 | if ( 'edit-tags.php' == $pagenow ) { 96 | 97 | // Make sure we have a taxonomy. 98 | if ( ! empty( $_REQUEST['taxonomy'] ) 99 | && $cpt_onomies_manager->is_registered_cpt_onomy( $_REQUEST['taxonomy'] ) ) { 100 | 101 | // Get the taxonomy and post type info. 102 | $taxonomy = $_REQUEST['taxonomy']; 103 | $tax = get_taxonomy( $taxonomy ); 104 | $custom_post_type = get_post_type_object( $taxonomy ); 105 | 106 | /* 107 | * If the user is capable of editing the post to begin with. 108 | * 109 | * Otherwise, don't get their hopes up. 110 | */ 111 | if ( current_user_can( $custom_post_type->cap->edit_posts ) ) { 112 | wp_die( sprintf( __( 'Since "%1$s" is a registered %2$s, you manage it\'s "terms" by managing the posts created under the custom post type "%3$s". So go ahead... %4$smanage the posts%5$s.', 'cpt-onomies' ), $tax->labels->name, 'CPT-onomy', $tax->labels->name, '', '' ) ); 113 | } else { 114 | wp_die( sprintf( __( 'Since "%1$s" is a registered %2$s, you manage it\'s "terms" by managing the posts created under the custom post type "%3$s". Unfortunately, you don\'t have permission to edit these posts. Sorry. If this is a mistake, contact your administrator.', 'cpt-onomies' ), $tax->labels->name, 'CPT-onomy', $tax->labels->name ) . ' ' . __( 'Go to the dashboard', 'cpt-onomies' ) . '' ); 115 | } 116 | } 117 | } 118 | } 119 | 120 | /** 121 | * Bringing all of the styles and scripts into one function helps to 122 | * keep everything more organized and allows for easier sharing. 123 | * 124 | * @since 1.1 125 | * @uses $current_screen 126 | * @param string $page - the current page 127 | */ 128 | public function admin_register_styles_and_scripts( $page ) { 129 | global $current_screen; 130 | 131 | // Several pages in the admin need this script. 132 | wp_register_script( 'jquery-form-validation', plugins_url( 'assets/js/jquery.validate.min.js', __FILE__ ), array( 'jquery' ), null, true ); 133 | 134 | // Enqueue scripts depending on page. 135 | switch ( $page ) { 136 | 137 | case 'edit.php': 138 | wp_enqueue_script( 'custom-post-type-onomies-admin-edit', plugins_url( 'assets/js/admin-edit.min.js', __FILE__ ), array( 'jquery', 'inline-edit-post' ), null, true ); 139 | break; 140 | 141 | case 'post.php': 142 | case 'post-new.php': 143 | wp_enqueue_style( 'custom-post-type-onomies-admin-post', plugins_url( 'assets/css/admin-post.min.css', __FILE__ ), false, null ); 144 | wp_enqueue_script( 'custom-post-type-onomies-admin-post', plugins_url( 'assets/js/admin-post.min.js', __FILE__ ), array( 'jquery', 'post', 'jquery-ui-autocomplete' ), null, true ); 145 | 146 | // Our localized info. 147 | $cpt_onomies_admin_post_data = array(); 148 | $cpt_onomies_admin_post_translation = array( 149 | 'term_does_not_exist' => sprintf( __( 'The term you are trying to add does not exist. %s terms, a.k.a posts, must already exist to be available for selection.', 'cpt-onomies' ), 'CPT-onomy' ), 150 | 'add_a_term' => __( 'Add a term', 'cpt-onomies' ), 151 | 'add_the_term' => __( 'Add the term', 'cpt-onomies' ), 152 | 'no_self_relationship' => __( 'Kind of silly to create a relationship between a post and itself, eh?', 'cpt-onomies' ), 153 | 'relationship_already_exists' => __( 'This relationship already exists.', 'cpt-onomies' ), 154 | 'close' => __( 'Close', 'cpt-onomies' ), 155 | ); 156 | 157 | /* 158 | * We need to know if the user has permission to edit specific 159 | * taxonomies AND we'll get the label name while we're at it. 160 | */ 161 | foreach ( get_object_taxonomies( $current_screen->post_type, 'objects' ) as $taxonomy => $tax ) { 162 | 163 | // Get the permission. 164 | $cpt_onomies_admin_post_data['can_assign_terms'][ $taxonomy ] = current_user_can( $tax->cap->assign_terms ); 165 | 166 | // Get the label name. 167 | $cpt_onomies_admin_post_translation['no_terms_selected'][ $taxonomy ] = sprintf( __( 'There are no %s selected.', 'cpt-onomies' ), strtolower( $tax->labels->name ) ); 168 | 169 | } 170 | 171 | // Add our info to the scripts. 172 | wp_localize_script( 'custom-post-type-onomies-admin-post', 'cpt_onomies_admin_post_data', $cpt_onomies_admin_post_data ); 173 | wp_localize_script( 'custom-post-type-onomies-admin-post', 'cpt_onomies_admin_post_L10n', $cpt_onomies_admin_post_translation ); 174 | 175 | break; 176 | 177 | } 178 | } 179 | 180 | /** 181 | * Allows ajax to invoke the get_cpt_onomy_terms_include_term_ids() function. 182 | * 183 | * Prints an array of term ids. 184 | * 185 | * @since 1.3 186 | */ 187 | public function ajax_get_cpt_onomy_terms_include_term_ids() { 188 | 189 | // Get the taxonomy and post type info. 190 | $taxonomy = ( isset( $_POST['custom_post_type_onomies_taxonomy'] ) && ! empty( $_POST['custom_post_type_onomies_taxonomy'] ) ) ? $_POST['custom_post_type_onomies_taxonomy'] : array(); 191 | $post_type = ( isset( $_POST['custom_post_type_onomies_post_type'] ) && ! empty( $_POST['custom_post_type_onomies_post_type'] ) ) ? $_POST['custom_post_type_onomies_post_type'] : null; 192 | $post_id = ( isset( $_POST['custom_post_type_onomies_post_id'] ) && ! empty( $_POST['custom_post_type_onomies_post_id'] ) ) ? $_POST['custom_post_type_onomies_post_id'] : 0; 193 | $include_term_ids = array(); 194 | 195 | // If we have a taxonomy... 196 | if ( ! empty( $taxonomy ) ) { 197 | 198 | // Get the include IDs. 199 | $taxonomy_include_term_ids = $this->get_cpt_onomy_terms_include_term_ids( $taxonomy, $post_type, $post_id ); 200 | if ( ! empty( $taxonomy_include_term_ids ) ) { 201 | $include_term_ids = array_merge( $include_term_ids, $taxonomy_include_term_ids ); 202 | } 203 | } 204 | 205 | // Print terms. 206 | echo json_encode( $include_term_ids ); 207 | 208 | die(); 209 | } 210 | 211 | /** 212 | * The 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids' filter 213 | * allows you to designate that you only want to include/print specific terms, and therefore 214 | * only want those specific terms to be able to be assigned, in the admin by returning their 215 | * term IDs. This function invokes that filter when needed, cleans up the data, stores the 216 | * data in a global class variable and returns the data. 217 | * 218 | * The data returned to the filter can be an array, space-separated or comma separated string. 219 | * The filter passes three parameters: the $taxonomy, the $post_type and the $post_id. 220 | * 221 | * @since 1.3 222 | * @param string $taxonomy - the name of the CPT-onomy 223 | * @param string $post_type - the name of the post type the CPT-onomy is being assigned to 224 | * @param int $post_id - the ID for the post the CPT-onomy is being assigned to 225 | * @return array - the ids for the included cpt_onomy terms 226 | * @filters 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids' - $taxonomy, $post_type, $post_id 227 | */ 228 | public function get_cpt_onomy_terms_include_term_ids( $taxonomy = null, $post_type = null, $post_id = 0 ) { 229 | 230 | $include_term_ids = apply_filters( 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids', array(), $taxonomy, $post_type, $post_id ); 231 | 232 | // Make sure its an array. 233 | if ( ! is_array( $include_term_ids ) ) { 234 | $include_term_ids = str_replace( ' ', ',', str_replace( ', ', ',', $include_term_ids ) ); 235 | $include_term_ids = explode( ',', $include_term_ids ); 236 | } 237 | 238 | // Make sure the 'include' does not include the current post ID. 239 | if ( in_array( $post_id, $include_term_ids ) ) { 240 | foreach ( $include_term_ids as $term_id_index => $term_id ) { 241 | if ( $post_id == $term_id ) { 242 | unset( $include_term_ids[ $term_id_index ] ); 243 | } 244 | } 245 | } 246 | 247 | // Store and return the include term data. 248 | return $this->assigning_terms_include_term_ids[ $taxonomy ][ $post_type ][ $post_id ] = array_unique( $include_term_ids ); 249 | } 250 | 251 | /** 252 | * Allows ajax to invoke the get_cpt_onomy_terms_exclude_term_ids() function. 253 | * 254 | * Prints an array of term ids. 255 | * 256 | * @since 1.2.1 257 | */ 258 | public function ajax_get_cpt_onomy_terms_exclude_term_ids() { 259 | 260 | // Get taxonomy and post type info 261 | $taxonomies = ( isset( $_POST['custom_post_type_onomies_taxonomies'] ) && ! empty( $_POST['custom_post_type_onomies_taxonomies'] ) ) ? $_POST['custom_post_type_onomies_taxonomies'] : array(); 262 | $post_type = ( isset( $_POST['custom_post_type_onomies_post_type'] ) && ! empty( $_POST['custom_post_type_onomies_post_type'] ) ) ? $_POST['custom_post_type_onomies_post_type'] : null; 263 | $post_id = ( isset( $_POST['custom_post_type_onomies_post_id'] ) && ! empty( $_POST['custom_post_type_onomies_post_id'] ) ) ? $_POST['custom_post_type_onomies_post_id'] : 0; 264 | $exclude_term_ids = array(); 265 | 266 | foreach ( $taxonomies as $taxonomy ) { 267 | $taxonomy_exclude_term_ids = $this->get_cpt_onomy_terms_exclude_term_ids( $taxonomy, $post_type, $post_id ); 268 | if ( ! empty( $taxonomy_exclude_term_ids ) ) { 269 | $exclude_term_ids = array_merge( $exclude_term_ids, $taxonomy_exclude_term_ids ); 270 | } 271 | } 272 | 273 | // Print terms 274 | echo json_encode( $exclude_term_ids ); 275 | 276 | die(); 277 | } 278 | 279 | /** 280 | * The 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids' filter 281 | * allows you to exclude specific terms from being printed, and therefore assigned, 282 | * in the admin by returning their term IDs. This function invokes that filter when 283 | * needed, cleans up the data, stores the data in a global class variable and returns the data. 284 | * 285 | * The data returned to the filter can be an array, space-separated or comma separated string. 286 | * The filter passes three parameters: the $taxonomy, the $post_type and the $post_id. 287 | * 288 | * @since 1.2.1 289 | * @param string $taxonomy - the name of the CPT-onomy 290 | * @param string $post_type - the name of the post type the CPT-onomy is being assigned to 291 | * @param int $post_id - the ID for the post the CPT-onomy is being assigned to 292 | * @return array - the ids for the excluded cpt_onomy terms 293 | * @filters 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids' - $taxonomy, $post_type, $post_id 294 | */ 295 | public function get_cpt_onomy_terms_exclude_term_ids( $taxonomy = null, $post_type = null, $post_id = 0 ) { 296 | 297 | $exclude_term_ids = apply_filters( 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids', array(), $taxonomy, $post_type, $post_id ); 298 | 299 | // Make sure its an array. 300 | if ( ! is_array( $exclude_term_ids ) ) { 301 | $exclude_term_ids = str_replace( ' ', ',', str_replace( ', ', ',', $exclude_term_ids ) ); 302 | $exclude_term_ids = explode( ',', $exclude_term_ids ); 303 | } 304 | 305 | // Make sure the 'excludes' includes the current post ID. 306 | if ( ! in_array( $post_id, $exclude_term_ids ) ) { 307 | $exclude_term_ids[] = $post_id; 308 | } 309 | 310 | // Store and return the excluded term data. 311 | return $this->assigning_terms_exclude_term_ids[ $taxonomy ][ $post_type ][ $post_id ] = array_unique( $exclude_term_ids ); 312 | } 313 | 314 | /** 315 | * Used in collaboration with the CPT-onomy autocomplete term selection, 316 | * if the CPT-onomy is hierarchical, in order to display a term's parents 317 | * in the autocomplete dropdown and in the selected terms' checklist. 318 | * 319 | * @since 1.1 320 | * @param int $term_parent - the term's parent term id 321 | * @return string the complete parent title 322 | */ 323 | public function build_term_parent_title_with_csv( $term_parent ) { 324 | 325 | if ( $term_parent > 0 ) { 326 | 327 | $post_parent_id = $term_parent; 328 | $term_parent = ''; 329 | 330 | do { 331 | 332 | $post_parent = get_post( $post_parent_id ); 333 | $post_parent_id = $post_parent->post_parent; 334 | 335 | if ( $term_parent ) { 336 | $term_parent .= ','; 337 | } 338 | 339 | $term_parent .= $post_parent->post_title; 340 | 341 | } while ( $post_parent_id > 0 ); 342 | 343 | return $term_parent; 344 | } else { 345 | return null; 346 | } 347 | } 348 | 349 | /** 350 | * Returns an object's term info to an AJAX call. 351 | * 352 | * Allows you to designate if you want the parent titles 353 | * instead of term id. This comes in handy with the autcomplete 354 | * term selection for hierarchical CPT-onomies so we can show 355 | * the parent title along with the term name. 356 | * 357 | * This function replaced populate_bulk_quick_edit(). 358 | * 359 | * @since 1.1 360 | */ 361 | public function ajax_get_wp_object_terms() { 362 | 363 | $post_ids = ( isset( $_POST['custom_post_type_onomies_post_ids'] ) && ! empty( $_POST['custom_post_type_onomies_post_ids'] ) ) ? $_POST['custom_post_type_onomies_post_ids'] : array(); 364 | $taxonomies = ( isset( $_POST['custom_post_type_onomies_taxonomies'] ) && ! empty( $_POST['custom_post_type_onomies_taxonomies'] ) ) ? $_POST['custom_post_type_onomies_taxonomies'] : array(); 365 | $get_parent_title = ( isset( $_POST['custom_post_type_onomies_get_parent_title'] ) && ! empty( $_POST['custom_post_type_onomies_get_parent_title'] ) ) ? true : false; 366 | $terms_fields = ( isset( $_POST['custom_post_type_onomies_wp_get_object_terms_fields'] ) && ! empty( $_POST['custom_post_type_onomies_wp_get_object_terms_fields'] ) && in_array( $_POST['custom_post_type_onomies_wp_get_object_terms_fields'], array( 'ids' ) ) ) ? $_POST['custom_post_type_onomies_wp_get_object_terms_fields'] : null; 367 | 368 | if ( ! empty( $post_ids ) && ! empty( $taxonomies ) ) { 369 | 370 | if ( ! is_array( $post_ids ) ) { 371 | $post_ids = array( $post_ids ); 372 | } 373 | 374 | if ( ! is_array( $taxonomies ) ) { 375 | $taxonomies = array( $taxonomies ); 376 | } 377 | 378 | // Set any arguments. 379 | $args = array(); 380 | 381 | // If we want specific fields. 382 | if ( $terms_fields ) { 383 | $args = array( 'fields' => $terms_fields ); 384 | } 385 | 386 | // Get terms. 387 | $terms = wp_get_object_terms( $post_ids, $taxonomies, $args ); 388 | 389 | // Get parent title, if desired AND if post type is hierarchical. 390 | if ( $get_parent_title ) { 391 | foreach ( $terms as $term_index => $term ) { 392 | $terms[ $term_index ]->parent = ( is_post_type_hierarchical( $term->taxonomy ) ) ? $this->build_term_parent_title_with_csv( $term->parent ) : ''; 393 | } 394 | } 395 | 396 | // Print terms. 397 | echo json_encode( $terms ); 398 | 399 | } 400 | 401 | die(); 402 | } 403 | 404 | /** 405 | * Allows us to check if a term exists via AJAX. 406 | * Returns an object of term info. 407 | * 408 | * Also allows you to designate that you want the parent's 409 | * name instead of the parent's term id. 410 | * 411 | * @since 1.1 412 | * @uses $cpt_onomy 413 | */ 414 | public function ajax_check_if_term_exists() { 415 | global $cpt_onomy; 416 | 417 | $term = ( isset( $_POST['custom_post_type_onomies_term'] ) && ! empty( $_POST['custom_post_type_onomies_term'] ) ) ? $_POST['custom_post_type_onomies_term'] : ''; 418 | $term_id = ( isset( $_POST['custom_post_type_onomies_term_id'] ) && ! empty( $_POST['custom_post_type_onomies_term_id'] ) && (int) $_POST['custom_post_type_onomies_term_id'] > 0 ) ? (int) $_POST['custom_post_type_onomies_term_id'] : 0; 419 | $taxonomy = ( isset( $_POST['custom_post_type_onomies_taxonomy'] ) && ! empty( $_POST['custom_post_type_onomies_taxonomy'] ) ) ? $_POST['custom_post_type_onomies_taxonomy'] : ''; 420 | $get_parent_title = ( isset( $_POST['custom_post_type_onomies_get_parent_title'] ) && ! empty( $_POST['custom_post_type_onomies_get_parent_title'] ) ) ? true : false; 421 | 422 | if ( ( $term || $term_id > 0 ) && $taxonomy ) { 423 | $term_exists = false; 424 | 425 | if ( $term_id > 0 ) { 426 | $term_exists = $cpt_onomy->term_exists( $term_id, $taxonomy ); 427 | } 428 | 429 | if ( ! $term_exists && $term ) { 430 | $term_exists = $cpt_onomy->term_exists( $term, $taxonomy ); 431 | } 432 | 433 | if ( ! $term_exists ) { 434 | echo json_encode( array() ); 435 | } elseif ( is_numeric( $term_exists ) ) { 436 | echo json_encode( (object) array( 'term_id' => $term_exists ) ); 437 | } elseif ( is_object( $term_exists ) || is_array( $term_exists ) ) { 438 | 439 | // Get parent title, if desired. 440 | if ( $get_parent_title ) { 441 | $term_exists->parent = $this->build_term_parent_title_with_csv( $term_exists->parent ); 442 | } 443 | 444 | echo json_encode( $term_exists ); 445 | 446 | } else { 447 | echo json_encode( array() ); 448 | } 449 | } else { 450 | echo json_encode( array() ); 451 | } 452 | 453 | die(); 454 | } 455 | 456 | /** 457 | * The jQuery field autocomplete callback 458 | * 459 | * This function returns results for the CPT-onomy autocomplete term selection. 460 | * 461 | * You can designate that you only want to include specific terms in the results by returning 462 | * their term IDs using the 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids' 463 | * filter which passes three parameters: the $taxonomy, the $post_type and the $post_id. 464 | * The "include" filter overwrites the "exclude" filter. 465 | * 466 | * You can disable specific terms from being listed in the results by returning their 467 | * term IDs using the 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids' 468 | * filter which passes three parameters: the $taxonomy, the $post_type and the $post_id. 469 | * While the "include" filter overwrites the "exclude" filter, if exclude terms are in the 470 | * include terms, they will be removed. 471 | * 472 | * @since 1.1 473 | * @uses $wpdb 474 | */ 475 | public function ajax_meta_box_autocomplete_callback() { 476 | global $wpdb; 477 | 478 | // Get the taxonomy and post type info. 479 | $taxonomy = ( isset( $_POST['custom_post_type_onomies_taxonomy'] ) && ! empty( $_POST['custom_post_type_onomies_taxonomy'] ) ) ? $_POST['custom_post_type_onomies_taxonomy'] : null; 480 | $term = ( isset( $_POST['custom_post_type_onomies_term'] ) && ! empty( $_POST['custom_post_type_onomies_term'] ) ) ? $_POST['custom_post_type_onomies_term'] : null; 481 | $post_type = ( isset( $_POST['custom_post_type_onomies_post_type'] ) && ! empty( $_POST['custom_post_type_onomies_post_type'] ) ) ? $_POST['custom_post_type_onomies_post_type'] : 0; 482 | $post_id = ( isset( $_POST['custom_post_type_onomies_post_id'] ) && ! empty( $_POST['custom_post_type_onomies_post_id'] ) ) ? $_POST['custom_post_type_onomies_post_id'] : 0; 483 | 484 | if ( $taxonomy && $term ) { 485 | 486 | // Get available terms. 487 | $available_terms = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_title AS label, post_parent AS parent FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'publish' ORDER BY post_title ASC", $taxonomy ) ); 488 | if ( $available_terms ) { 489 | 490 | /* 491 | * Allows you to use the 492 | * 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids' 493 | * filter to designate that you only want specific terms to be 494 | * printed and therefore assigned. The term ids are stored 495 | * in an array that is used to customize each printed format. 496 | * 'Include' overwrites 'exclude'. 497 | */ 498 | $include_term_ids = $this->get_cpt_onomy_terms_include_term_ids( $taxonomy, $post_type, $post_id ); 499 | 500 | /* 501 | * Allows you to use the 502 | * 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids' 503 | * filter to exclude specific terms from being printed 504 | * and therefore assigned. The term ids are stored in an 505 | * array that is used to customize each printed format. 506 | * While 'include' overwrites 'exclude', if exclude terms 507 | * are in the include array, they will be removed. 508 | */ 509 | $exclude_term_ids = $this->get_cpt_onomy_terms_exclude_term_ids( $taxonomy, $post_type, $post_id ); 510 | 511 | $results = array(); 512 | foreach ( $available_terms as $this_term ) { 513 | 514 | // Whether or not we want the element displayed. 515 | $add_term_to_results = true; 516 | 517 | // Test against 'include' and 'exclude'. 518 | if ( $include_term_ids && ! in_array( $this_term->ID, $include_term_ids ) ) { 519 | $add_term_to_results = false; 520 | } 521 | 522 | if ( $exclude_term_ids && in_array( $this_term->ID, $exclude_term_ids ) ) { 523 | $add_term_to_results = false; 524 | } 525 | 526 | // We don't want to display children of terms we filtered out. 527 | if ( $this_term->parent ) { 528 | foreach ( get_post_ancestors( $this_term->ID ) as $ancestor ) { 529 | if ( in_array( $ancestor, $exclude_term_ids ) ) { 530 | $add_term_to_results = false; 531 | break; 532 | } 533 | } 534 | } 535 | 536 | if ( $add_term_to_results ) { 537 | 538 | // Go ahead and apply the filter before it's "searched". 539 | $this_term->label = apply_filters( 'the_title', $this_term->label, $this_term->ID ); 540 | 541 | /* 542 | * We don't want to display the current post. 543 | * If a match was found, add it to the suggestions. 544 | */ 545 | if ( stripos( $this_term->label, $term ) !== false ) { 546 | 547 | $results[] = array( 548 | 'value' => $this_term->ID, 549 | 'label' => $this_term->label, 550 | 'parent' => ( is_post_type_hierarchical( $taxonomy ) ) ? $this->build_term_parent_title_with_csv( $this_term->parent ) : '', 551 | ); 552 | 553 | } 554 | } 555 | } 556 | 557 | // Print terms. 558 | echo json_encode( $results ); 559 | 560 | } 561 | } 562 | 563 | die(); 564 | } 565 | 566 | /** 567 | * If a CPT-onomy is attached to a post type, the plugin adds a meta box to 568 | * the post edit screen so the user can assign/manage the taxonomy's terms. 569 | * 570 | * You can remove the box by returning false to the 571 | * 'custom_post_type_onomies_add_cpt_onomy_admin_meta_box' filter, which passes 572 | * two parameters: the $taxonomy and the $post_type. 573 | * 574 | * This function is invoked by the action 'add_meta_boxes'. 575 | * 576 | * @since 1.0 577 | * @uses $cpt_onomies_manager 578 | * @param string $post_type - the current post's post type 579 | * @param object $post - the current post's information 580 | * @filters 'custom_post_type_onomies_add_cpt_onomy_admin_meta_box' - $taxonomy, $post_type 581 | */ 582 | public function add_cpt_onomy_meta_boxes( $post_type, $post ) { 583 | global $cpt_onomies_manager; 584 | 585 | // Loop through all the taxonomies tied to this post type. 586 | foreach ( get_object_taxonomies( $post_type, 'objects' ) as $taxonomy => $tax ) { 587 | 588 | // Make sure its a registered CPT-onomy. 589 | if ( $cpt_onomies_manager->is_registered_cpt_onomy( $taxonomy ) ) { 590 | 591 | /* 592 | * This filter allows you to remove the meta box by returning false. 593 | * 594 | * If 'show_ui' is false, do not add meta box. 595 | */ 596 | if ( apply_filters( 'custom_post_type_onomies_add_cpt_onomy_admin_meta_box', ( post_type_exists( $taxonomy ) ? get_post_type_object( $taxonomy )->show_ui : true ), $taxonomy, $post_type ) ) { 597 | 598 | // What's the meta box title? - default is taxonomy label. 599 | $meta_box_title = isset( $tax->meta_box_title ) && ! empty( $tax->meta_box_title ) ? $tax->meta_box_title : $tax->label; 600 | 601 | // Add the meta box. 602 | add_meta_box( 'custom-post-type-onomies-' . $taxonomy, apply_filters( 'custom_post_type_onomies_meta_box_title', $meta_box_title, $taxonomy, $post_type ), array( $this, 'print_cpt_onomy_meta_box' ), $post_type, 'side', 'core', array( 'taxonomy' => $taxonomy ) ); 603 | 604 | } 605 | } 606 | } 607 | } 608 | 609 | /** 610 | * This function is invoked when a CPT-onomy meta box is attached to a post type's edit post screen. 611 | * This 'callback' function prints the html for the meta box. 612 | * 613 | * The meta box consists of a checklist that allows the user to assign/manage the taxonomy's terms. 614 | * This function mimics a meta box for an ordinary custom taxonomy. 615 | * 616 | * Version 1.1 brought support for 'autocomplete' and 'dropdown' selection format, 617 | * on top of the already existent 'checklist'. 618 | * 619 | * CPT-onomies follows default WordPress behavior, providing a checklist for hierarchical 620 | * CPT-onomies and the autocomplete box for non-hierarchical CPT-onomies. You can change the 621 | * format by hooking into the 'custom_post_type_onomies_meta_box_format' filter, which passes 622 | * two parameters: the $taxonomy and the $post_type. 623 | * 624 | * You can designate that you only want specific terms listed in the results by returning their 625 | * term IDs using the 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids' 626 | * filter which passes three parameters: the $taxonomy, the $post_type and the $post_id. 627 | * 628 | * You can disable specific terms from being listed in the results by returning their 629 | * term IDs using the 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids' 630 | * filter which passes three parameters: the $taxonomy, the $post_type and the $post_id. 631 | * 632 | * This code mimics the WordPress function post_categories_meta_box(). 633 | * 634 | * This function is invoked by the action 'add_meta_boxes'. 635 | * 636 | * @since 1.0 637 | * @param object $post - the current post's information 638 | * @param array $box - information about the metabox 639 | * @filters 'custom_post_type_onomies_meta_box_format' - $taxonomy, $post_type 640 | */ 641 | public function print_cpt_onomy_meta_box( $post, $metabox ) { 642 | 643 | // Add nonce. 644 | wp_nonce_field( 'assigning_custom_post_type_onomies_taxonomy_relationships', 'custom_post_type_onomies_nonce' ); 645 | 646 | // Define variables. 647 | $post_type = ( isset( $post->post_type ) && ! empty( $post->post_type ) && post_type_exists( $post->post_type ) ) ? $post->post_type : null; 648 | $taxonomy = ( isset( $metabox['args']['taxonomy'] ) && ! empty( $metabox['args']['taxonomy'] ) && taxonomy_exists( $metabox['args']['taxonomy'] ) ) ? $metabox['args']['taxonomy'] : null; 649 | 650 | if ( $post_type && $taxonomy ) { 651 | 652 | // Get taxonomy info 653 | $tax = get_taxonomy( $taxonomy ); 654 | 655 | // If 'meta_box_format' is not defined, use default WordPress setting 656 | if ( ! ( $format = ( isset( $tax->meta_box_format ) && ! empty( $tax->meta_box_format ) ) ? $tax->meta_box_format : null ) ) { 657 | $format = is_post_type_hierarchical( $taxonomy ) ? 'checklist' : 'autocomplete'; 658 | } 659 | 660 | // Allow the user to change the format - 'autocomplete', 'dropdown', 'checklist' - default 661 | $format = apply_filters( 'custom_post_type_onomies_meta_box_format', $format, $taxonomy, $post_type ); 662 | 663 | // Does the user have permission to assign terms? 664 | $disabled = ! current_user_can( $tax->cap->assign_terms ) ? ' disabled="disabled"' : ''; 665 | 666 | /* 667 | * Allows you to use the 668 | * 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids' 669 | * filter to designate that you only want specific terms 670 | * to be printed and therefore assigned. The term ids are 671 | * stored in an array that is used to customize each printed 672 | * format. 'Include' overwrites 'exclude'. 673 | */ 674 | $include_term_ids = $this->get_cpt_onomy_terms_include_term_ids( $taxonomy, $post_type, $post->ID ); 675 | 676 | /* 677 | * Allows you to use the 678 | * 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids' 679 | * filter to exclude specific terms from being printed 680 | * and therefore assigned. The term ids are stored in an 681 | * array that is used to customize each printed format. 682 | * While 'include' overwrites 'exclude', if exclude terms 683 | * are in the include array, they will be removed. 684 | */ 685 | $exclude_term_ids = $this->get_cpt_onomy_terms_exclude_term_ids( $taxonomy, $post_type, $post->ID ); 686 | 687 | // Add field for testing "editability" when we save the information. 688 | ?> 689 | 690 | 697 |
698 |
699 |
700 |

labels->add_or_remove_items; ?>

701 | 702 |
703 | cap->assign_terms ) ) : 706 | 707 | ?> 708 |
709 | 710 |
labels->add_new_item; ?>
711 |

712 | 713 | 714 |

715 |
716 | 721 |
722 |
723 |
724 | cap->assign_terms ) ) : 727 | 728 | ?> 729 |

labels->choose_from_most_used; ?>

730 | ID, $taxonomy ); 740 | 741 | // We only need the first term for a dropdown. 742 | $selected_term = $selected_terms ? array_shift( $selected_terms )->term_id : 0; 743 | 744 | /* 745 | * Because the dropdown function only has 'exclude', if 'include' is set, 746 | * we have to get all of the terms and exclude everything but what's in 'include' 747 | */ 748 | $dropdown_exclude_term_ids = array(); 749 | if ( $include_term_ids ) { 750 | 751 | // Get all terms for this taxonomy that are not in 'include'. 752 | foreach ( get_terms( $taxonomy, array( 'hide_empty' => false, 'fields' => 'ids' ) ) as $term_id ) { 753 | if ( ! in_array( $term_id, $include_term_ids ) ) { 754 | $dropdown_exclude_term_ids[] = $term_id; 755 | } 756 | } 757 | } 758 | 759 | // Make sure 'exclude' term ids are included. 760 | if ( $exclude_term_ids ) { 761 | $dropdown_exclude_term_ids = array_unique( array_merge( $dropdown_exclude_term_ids, $exclude_term_ids ) ); 762 | } 763 | 764 | $dropdown = wp_dropdown_categories( array( 765 | 'show_option_none' => sprintf( __( 'No %s are selected', 'cpt-onomies' ), $tax->labels->all_items ), 766 | 'orderby' => 'name', 767 | 'order' => 'ASC', 768 | 'show_count' => false, 769 | 'hide_empty' => false, 770 | 'exclude' => $dropdown_exclude_term_ids, 771 | 'echo' => false, 772 | 'selected' => $selected_term, 773 | 'hierarchical' => is_post_type_hierarchical( $taxonomy ), 774 | 'name' => CPT_ONOMIES_POSTMETA_KEY . '[' . $taxonomy . '][]', 775 | 'id' => 'taxonomy-' . $taxonomy, 776 | 'class' => 'category cpt_onomies', 777 | 'taxonomy' => $taxonomy, 778 | 'hide_if_empty' => false, 779 | )); 780 | 781 | /* 782 | * Need to add disabled to select element 783 | * as a backup, this attribute is also checked in admin-post.js 784 | */ 785 | if ( $disabled ) { 786 | $dropdown = preg_replace( '/^\ 958 | " value="true" /> 959 | 960 | 961 | cap->assign_terms ) ) { 989 | foreach ( $post_ids as $post_id ) { 990 | 991 | /* 992 | * Set object terms. 993 | * 994 | * "append" is set to true so it doesn't 995 | * delete relationships, only creates. 996 | */ 997 | if ( ! empty( $checked_ids ) ) { 998 | $cpt_onomy->wp_set_object_terms( $post_id, $checked_ids, $taxonomy, true ); 999 | } 1000 | } 1001 | } 1002 | } 1003 | die(); 1004 | } 1005 | 1006 | /** 1007 | * This ajax function is run on the "Edit Posts" screen when a "Quick Edit" is saved. 1008 | * 1009 | * If the post type is not 'post' or 'page', the custom columns are NOT added back to 1010 | * the row so CPT-onomies takes care of this for you. After CPT-onomies adds the column, 1011 | * this function is run to populate the column. 1012 | * 1013 | * @since 1.0.3 1014 | */ 1015 | public function ajax_quick_edit_populate_custom_columns() { 1016 | global $post; 1017 | 1018 | // Get taxonomy and post type info. 1019 | $post_id = ( isset( $_POST['custom_post_type_onomies_post_id'] ) && ! empty( $_POST['custom_post_type_onomies_post_id'] ) && is_numeric( $_POST['custom_post_type_onomies_post_id'] ) ) ? $_POST['custom_post_type_onomies_post_id'] : 0; 1020 | $post_type = ( isset( $_POST['custom_post_type_onomies_post_type'] ) && ! empty( $_POST['custom_post_type_onomies_post_type'] ) ) ? $_POST['custom_post_type_onomies_post_type'] : null; 1021 | $column_name = ( isset( $_POST['custom_post_type_onomies_column_name'] ) && ! empty( $_POST['custom_post_type_onomies_column_name'] ) ) ? $_POST['custom_post_type_onomies_column_name'] : null; 1022 | 1023 | if ( $post_id && ! empty( $post_type ) && ! empty( $column_name ) ) { 1024 | 1025 | /* 1026 | * Since the ajax will not retrieve comment info. 1027 | * 1028 | * Otherwise, the ajax will retrieve column info 1029 | * for posts and pages only. 1030 | */ 1031 | if ( 'comments' == $column_name ) : 1032 | 1033 | ?> 1034 |
1035 | ID = $post_id; 1039 | $wp_list_table = _get_list_table( 'WP_Posts_List_Table' ); 1040 | $pending_comments = isset( $wp_list_table->comment_pending_count[ $post_id ] ) ? $wp_list_table->comment_pending_count[ $post_id ] : 0; 1041 | $wp_list_table->comments_bubble( $post_id, $pending_comments ); 1042 | 1043 | ?> 1044 |
1045 | get_column_info(); 1080 | foreach ( $columns as $column_name => $column_display_name ) { 1081 | 1082 | /* 1083 | * The filter drop down is added if you have the column added 1084 | * but you still have the capability to remove the dropdown 1085 | * via filter, if desired. 1086 | */ 1087 | 1088 | // Get the taxonomy name from the column name. 1089 | $taxonomy = strtolower( str_replace( 'taxonomy-', '', $column_name ) ); 1090 | 1091 | // Make sure its a registered CPT-onomy. 1092 | if ( $taxonomy && $cpt_onomies_manager->is_registered_cpt_onomy( $taxonomy ) ) { 1093 | 1094 | // Get taxonomy information. 1095 | $tax = get_taxonomy( $taxonomy ); 1096 | 1097 | // This filter allows you to remove the dropdown by returning false. 1098 | if ( apply_filters( 'custom_post_type_onomies_add_cpt_onomy_admin_dropdown_filter', ( isset( $tax->show_admin_column ) && ! $tax->show_admin_column ) ? false : true, $taxonomy, $post_type ) ) { 1099 | 1100 | // Get post type info. 1101 | $post_type_object = get_post_type_object( $taxonomy ); 1102 | 1103 | // Get selected term. 1104 | $selected = ( isset( $_REQUEST[ $taxonomy ] ) ) ? $_REQUEST[ $taxonomy ] : null; 1105 | 1106 | // If slug, then get term id. 1107 | if ( ! is_numeric( $selected ) ) { 1108 | $term = $cpt_onomy->get_term_by( 'slug', $selected, $taxonomy ); 1109 | if ( $term ) { 1110 | $selected = $term->term_id; 1111 | } 1112 | } 1113 | 1114 | // Print dropdown. 1115 | wp_dropdown_categories( array( 1116 | 'show_option_all' => sprintf( __( 'View all %s', 'cpt-onomies' ), $post_type_object->labels->all_items ), 1117 | 'hierarchical' => true, 1118 | 'show_count' => false, 1119 | 'orderby' => 'name', 1120 | 'selected' => $selected, 1121 | 'name' => $taxonomy, 1122 | 'id' => 'dropdown_custom_post_type_onomies_' . $taxonomy, 1123 | 'class' => 'postform ' . ( ( in_array( $column_name, $hidden ) ) ? ' hide-all' : '' ), 1124 | 'taxonomy' => $taxonomy, 1125 | 'hide_if_empty' => true, 1126 | )); 1127 | 1128 | } 1129 | } 1130 | } 1131 | } 1132 | 1133 | /** 1134 | * 1135 | * If a CPT-onomy is attached to a post type, the plugin adds a column 1136 | * to the post type's edit screen which lists each post's assigned terms. 1137 | * 1138 | * As of version 1.3.5, removed the backwards compatibility 1139 | * but keeping this function so we can keep the filters in action. 1140 | * 1141 | * You can remove the column by returning false to the 1142 | * 'custom_post_type_onomies_add_cpt_onomy_admin_column' filter, which passes 1143 | * two parameters: the $taxonomy and the $post_type. 1144 | * 1145 | * This function adds the columns to the screen. 1146 | * $this->edit_cpt_onomy_admin_column() adds the assigned terms to each column. 1147 | * 1148 | * This function is applied to the filter 'manage_pages_columns' and 'manage_posts_columns'. 1149 | * The 'posts' filter sends 2 parameters ($columns and $post_type) 1150 | * but the 'pages' only send $columns so I define $post_type to cover 'pages'. 1151 | * 1152 | * @since 1.0 1153 | * @uses $cpt_onomies_manager 1154 | * @param array $columns - the column info already created by WordPress 1155 | * @param string $post_type - the name of the post type being managed/edited 1156 | * @return array - the columns info after it has been filtered 1157 | * @filters custom_post_type_onomies_add_cpt_onomy_admin_column - $taxonomy, $post_type 1158 | */ 1159 | public function add_cpt_onomy_admin_column( $columns, $post_type = 'page' ) { 1160 | global $cpt_onomies_manager; 1161 | 1162 | // Process each taxonomy assigned to the current post type. 1163 | foreach ( get_object_taxonomies( $post_type, 'objects' ) as $taxonomy => $tax ) { 1164 | 1165 | // Make sure its a registered CPT-onomy. 1166 | if ( $cpt_onomies_manager->is_registered_cpt_onomy( $taxonomy ) ) { 1167 | 1168 | // If the column already exists, i.e. added by WordPress... 1169 | if ( array_key_exists( 'taxonomy-' . $taxonomy, $columns ) ) { 1170 | 1171 | // Define the column key. 1172 | $column_key = "taxonomy-{$taxonomy}"; 1173 | 1174 | /* 1175 | * This filter allows you to remove the column by returning false. 1176 | * 1177 | * Otherwise, if we're keeping the column, we can customize the title. 1178 | */ 1179 | if ( ! apply_filters( 'custom_post_type_onomies_add_cpt_onomy_admin_column', true, $taxonomy, $post_type ) ) { 1180 | 1181 | // Remove the column. 1182 | unset( $columns[ $column_key ] ); 1183 | 1184 | } else { 1185 | 1186 | // Get the new column title/header - defaults to taxonomy's label. 1187 | if ( $new_column_title = apply_filters( 'custom_post_type_onomies_cpt_onomy_admin_column_title', ( isset( $tax->admin_column_title ) && ! empty( $tax->admin_column_title ) ? $tax->admin_column_title : $tax->label ), $taxonomy, $post_type ) ) { 1188 | 1189 | // Set the new column title. 1190 | $columns[ $column_key ] = $new_column_title; 1191 | 1192 | } 1193 | } 1194 | } 1195 | } 1196 | } 1197 | return $columns; 1198 | } 1199 | 1200 | /** 1201 | * Adds the filter for adding/managing sortable 1202 | * CPT-onomy admin columns. 1203 | * 1204 | * I deprecated the ability to make the CPT-onomy admin 1205 | * columns sortable in version 1.3 to align with new, 1206 | * default WP taxonomy admin column functionality. 1207 | * Re-instated the sortable columns in version 1.3.2 1208 | * due to its popularity. 1209 | * 1210 | * This function is invoked by the action 'load-edit.php'. 1211 | * 1212 | * @reinstated in 1.3.2, first introduced in 1.0.3, deprecated in 1.3 1213 | * @uses $current_screen 1214 | */ 1215 | public function add_cpt_onomy_admin_sortable_columns_filter() { 1216 | global $current_screen; 1217 | if ( $current_screen && isset( $current_screen->id ) ) { 1218 | add_filter( "manage_{$current_screen->id}_sortable_columns", array( $this, 'add_cpt_onomy_admin_sortable_columns' ) ); 1219 | } 1220 | } 1221 | 1222 | /** 1223 | * Tells WordPress to make our CPT-onomy admin columns sortable. 1224 | * 1225 | * You can disable the columns from being sortable by returning false to the 1226 | * 'custom_post_type_onomies_add_cpt_onomy_admin_sortable_column' filter, which 1227 | * passes two parameters: the $taxonomy and the $post_type. 1228 | * 1229 | * If you want to remove the column altogether, set "Show Admin Column" 1230 | * to false in your CPT-onomy settings, or return false to the 1231 | * 'custom_post_type_onomies_add_cpt_onomy_admin_column' filter, which 1232 | * passes the same two parameters: $taxonomy and $post_type. 1233 | * 1234 | * This function is invoked by the filter "manage_{$current_screen->id}_sortable_columns". 1235 | * 1236 | * @reinstated in 1.3.2, first introduced in 1.0.3, deprecated in 1.3 1237 | * @uses $cpt_onomies_manager, $current_screen 1238 | * @param array $sortable_columns - the sortable columns info already created by WordPress 1239 | * @return array - the sortable columns info after it has been filtered 1240 | * @filters 'custom_post_type_onomies_add_cpt_onomy_admin_sortable_column' - $taxonomy, $post_type 1241 | */ 1242 | public function add_cpt_onomy_admin_sortable_columns( $sortable_columns ) { 1243 | global $cpt_onomies_manager, $current_screen; 1244 | 1245 | // Get the current post type. 1246 | if ( $post_type = isset( $current_screen->post_type ) ? $current_screen->post_type : null ) { 1247 | 1248 | // Process each taxonomy assigned to the current post type. 1249 | foreach ( get_object_taxonomies( $post_type, 'objects' ) as $taxonomy => $tax ) { 1250 | 1251 | // Make sure its a registered CPT-onomy and get the taxonomy's query variable 1252 | if ( $cpt_onomies_manager->is_registered_cpt_onomy( $taxonomy ) 1253 | && ( $query_var = isset( $tax->query_var ) ? $tax->query_var : null ) ) { 1254 | 1255 | /* 1256 | * This filter allows you to remove the column by returning false. 1257 | * All CPT-onomy admin columns are default-ly added as sortable. 1258 | */ 1259 | if ( apply_filters( 'custom_post_type_onomies_add_cpt_onomy_admin_sortable_column', true, $taxonomy, $post_type ) ) { 1260 | $column_key = "taxonomy-{$taxonomy}"; 1261 | $sortable_columns[ $column_key ] = $query_var; 1262 | } 1263 | } 1264 | } 1265 | } 1266 | return $sortable_columns; 1267 | } 1268 | 1269 | } 1270 | 1271 | /** 1272 | * Custom walker used for wp_terms_checklist() so we can edit the input name. 1273 | * 1274 | * @since 1.0 1275 | */ 1276 | class CPTonomy_Walker_Terms_Checklist extends Walker { 1277 | var $tree_type = 'category'; 1278 | var $db_fields = array( 'parent' => 'parent', 'id' => 'term_id' ); 1279 | 1280 | /** 1281 | * Added this function in version 1.2 in order to allow 1282 | * users to exclude term ids from the checklist. 1283 | * 1284 | * @uses $cpt_onomies_admin, $post_type, $post 1285 | * @param object $element Data object 1286 | * @param array $children_elements List of elements to continue traversing. 1287 | * @param int $max_depth Max depth to traverse. 1288 | * @param int $depth Depth of current element. 1289 | * @param array $args 1290 | * @param string $output Passed by reference. Used to append additional content. 1291 | * @return null Null on failure with no changes to parameters. 1292 | */ 1293 | function display_element( $element, &$children_elements, $max_depth, $depth = 0, $args, &$output ) { 1294 | global $cpt_onomies_admin, $post_type, $post; 1295 | 1296 | // Make sure we have an element. 1297 | if ( ! $element ) { 1298 | return; 1299 | } 1300 | 1301 | $id_field = $this->db_fields['id']; 1302 | 1303 | /* 1304 | * This data was retrieved from the filter 1305 | * 'custom_post_type_onomies_assigning_cpt_onomy_terms_include_term_ids' 1306 | * when we printed the CPT-onomy meta boxes. 1307 | */ 1308 | $include_term_ids = isset( $cpt_onomies_admin->assigning_terms_include_term_ids[ $element->taxonomy ][ $post_type ][ $post->ID ] ) ? $cpt_onomies_admin->assigning_terms_include_term_ids[ $element->taxonomy ][ $post_type ][ $post->ID ] : array(); 1309 | 1310 | /* 1311 | * This data was retrieved from the filter 1312 | * 'custom_post_type_onomies_assigning_cpt_onomy_terms_exclude_term_ids' 1313 | * when we printed the CPT-onomy meta boxes. 1314 | */ 1315 | $exclude_term_ids = isset( $cpt_onomies_admin->assigning_terms_exclude_term_ids[ $element->taxonomy ][ $post_type ][ $post->ID ] ) ? $cpt_onomies_admin->assigning_terms_exclude_term_ids[ $element->taxonomy ][ $post_type ][ $post->ID ] : array(); 1316 | 1317 | // Whether or not we want the element displayed. 1318 | $display_element = true; 1319 | if ( $include_term_ids && ! in_array( $element->$id_field, $include_term_ids ) ) { 1320 | $display_element = false; 1321 | } 1322 | 1323 | if ( $exclude_term_ids && in_array( $element->$id_field, $exclude_term_ids ) ) { 1324 | $display_element = false; 1325 | } 1326 | 1327 | if ( $display_element ) { 1328 | 1329 | // Display this element. 1330 | if ( is_array( $args[0] ) ) { 1331 | $args[0]['has_children'] = ! empty( $children_elements[ $element->$id_field ] ); 1332 | } 1333 | 1334 | $cb_args = array_merge( array( &$output, $element, $depth ), $args ); 1335 | call_user_func_array( array( $this, 'start_el' ), $cb_args ); 1336 | 1337 | $id = $element->$id_field; 1338 | 1339 | // Descend only when the depth is right and there are childrens for this element. 1340 | if ( ( 0 == $max_depth || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) { 1341 | 1342 | foreach ( $children_elements[ $id ] as $child ) { 1343 | 1344 | if ( ! isset( $newlevel ) ) { 1345 | $newlevel = true; 1346 | 1347 | // Start the child delimiter. 1348 | $cb_args = array_merge( array( &$output, $depth ), $args ); 1349 | call_user_func_array( array( $this, 'start_lvl' ), $cb_args ); 1350 | 1351 | } 1352 | 1353 | $this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output ); 1354 | 1355 | } 1356 | unset( $children_elements[ $id ] ); 1357 | } 1358 | 1359 | if ( isset( $newlevel ) && $newlevel ) { 1360 | 1361 | // End the child delimiter. 1362 | $cb_args = array_merge( array( &$output, $depth ), $args ); 1363 | call_user_func_array( array( $this, 'end_lvl' ), $cb_args ); 1364 | 1365 | } 1366 | 1367 | // End this element. 1368 | $cb_args = array_merge( array( &$output, $element, $depth ), $args ); 1369 | call_user_func_array( array( $this, 'end_el' ), $cb_args ); 1370 | 1371 | } 1372 | } 1373 | 1374 | function start_lvl( &$output, $depth = 0, $args = array() ) { 1375 | $indent = str_repeat( "\t", $depth ); 1376 | $output .= "$indent\n"; 1382 | } 1383 | 1384 | function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) { 1385 | if ( ! empty( $args['taxonomy'] ) ) { 1386 | $class = in_array( $object->term_id, $args['popular_cats'] ) ? ' class="popular-category"' : ''; 1387 | $output .= "\n
  • term_id}'{$class}>" . ''; 1388 | } 1389 | } 1390 | 1391 | function end_el( &$output, $category, $depth = 0, $args = array() ) { 1392 | $output .= "
  • \n"; 1393 | } 1394 | } 1395 | -------------------------------------------------------------------------------- /assets/images/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bamadesigner/cpt-onomies/94f162acd2808c83b64e5c6e7bc0c5dc62f91bba/assets/images/add.png -------------------------------------------------------------------------------- /assets/images/attention.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bamadesigner/cpt-onomies/94f162acd2808c83b64e5c6e7bc0c5dc62f91bba/assets/images/attention.png -------------------------------------------------------------------------------- /assets/images/close_advanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bamadesigner/cpt-onomies/94f162acd2808c83b64e5c6e7bc0c5dc62f91bba/assets/images/close_advanced.png -------------------------------------------------------------------------------- /assets/images/inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bamadesigner/cpt-onomies/94f162acd2808c83b64e5c6e7bc0c5dc62f91bba/assets/images/inactive.png -------------------------------------------------------------------------------- /assets/images/information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bamadesigner/cpt-onomies/94f162acd2808c83b64e5c6e7bc0c5dc62f91bba/assets/images/information.png -------------------------------------------------------------------------------- /assets/images/working.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bamadesigner/cpt-onomies/94f162acd2808c83b64e5c6e7bc0c5dc62f91bba/assets/images/working.png -------------------------------------------------------------------------------- /assets/js/admin-edit.js: -------------------------------------------------------------------------------- 1 | jQuery.noConflict()(function(){ 2 | 3 | // Hide/show dropdowns if hiding/showing column 4 | jQuery( '.hide-column-tog' ).live( 'click', function() { 5 | var $t = jQuery( this ), $column = $t.val(); 6 | var $dropdown = 'dropdown_' + $column; 7 | if ( $t.prop( 'checked' ) ) { 8 | jQuery( '#'+$dropdown ).show(); 9 | } else { 10 | jQuery( '#'+$dropdown ).hide(); 11 | } 12 | }); 13 | 14 | }); 15 | 16 | (function($) { 17 | 18 | function cpt_onomy_populate_quick_edit() { 19 | 20 | // We create a copy of the original inline edit post, overwrite and then "call" the copy 21 | var $wp_inline_edit = inlineEditPost.edit; 22 | inlineEditPost.edit = function( id ) { 23 | 24 | // "Call" the original edit function 25 | $wp_inline_edit.apply( this, arguments ); 26 | 27 | // Get the post ID 28 | var $id = 0; 29 | if ( typeof( id ) == 'object' ) { 30 | $id = parseInt( this.getId( id ) ); 31 | } 32 | 33 | if ( $id > 0 ) { 34 | 35 | // Define the edit row 36 | var $quick_edit_row = $( '#edit-'+$id ); 37 | if ( $quick_edit_row.size() > 0 ) { 38 | 39 | // Get the post type 40 | var $post_type = jQuery( 'input[name="post_type"]' ).val(); 41 | 42 | // Get the taxonomies 43 | var $taxonomies = $quick_edit_row.cpt_onomy_bulk_quick_edit_get_taxonomies(); 44 | 45 | /** 46 | * Get this object's taxonomies "include" term IDs 47 | * with "include", we have to iterate through each taxonomy. 48 | */ 49 | $.each( $taxonomies, function( $index, $taxonomy ) { 50 | $.ajax({ 51 | url: ajaxurl, 52 | type: 'POST', 53 | dataType: 'json', 54 | async: true, 55 | cache: false, 56 | data: { 57 | action: 'custom_post_type_onomy_get_cpt_onomy_terms_include_term_ids', 58 | custom_post_type_onomies_taxonomy: $taxonomy, 59 | custom_post_type_onomies_post_type: $post_type, 60 | custom_post_type_onomies_post_id: $id 61 | }, 62 | success: function( $term_ids ) { 63 | 64 | // If $term_ids is array and not empty 65 | if ( $.isArray( $term_ids ) && $term_ids.length > 0 ) { 66 | 67 | // Remove from checklists 68 | $quick_edit_row.find( 'ul.cpt-onomy-checklist.cpt-onomy-' + $taxonomy ).each( function() { 69 | $( this ).cpt_onomy_remove_from_quick_edit_checklist( $term_ids, true ); 70 | }); 71 | 72 | } 73 | 74 | } 75 | }); 76 | }); 77 | 78 | // Get this object's taxonomies "exclude" term IDs 79 | $.ajax({ 80 | url: ajaxurl, 81 | type: 'POST', 82 | dataType: 'json', 83 | async: true, 84 | cache: false, 85 | data: { 86 | action: 'custom_post_type_onomy_get_cpt_onomy_terms_exclude_term_ids', 87 | custom_post_type_onomies_taxonomies: $taxonomies, 88 | custom_post_type_onomies_post_type: $post_type, 89 | custom_post_type_onomies_post_id: $id 90 | }, 91 | success: function( $term_ids ) { 92 | 93 | // If $term_ids is array and not empty 94 | if ( $.isArray( $term_ids ) && $term_ids.length > 0 ) { 95 | 96 | // Remove from checklists 97 | $quick_edit_row.find( 'ul.cpt-onomy-checklist' ).each( function() { 98 | $( this ).cpt_onomy_remove_from_quick_edit_checklist( $term_ids, false ); 99 | }); 100 | 101 | } 102 | 103 | } 104 | }); 105 | 106 | // Get this object's term IDs 107 | $.ajax({ 108 | url: ajaxurl, 109 | type: 'POST', 110 | dataType: 'json', 111 | async: true, 112 | cache: false, 113 | data: { 114 | action: 'custom_post_type_onomy_populate_bulk_quick_edit', 115 | custom_post_type_onomies_post_ids: $id, 116 | custom_post_type_onomies_taxonomies: $taxonomies, 117 | custom_post_type_onomies_wp_get_object_terms_fields: 'ids' 118 | }, 119 | success: function( $term_ids ) { 120 | 121 | // If $term_ids is array and not empty 122 | if ( $.isArray( $term_ids ) && $term_ids.length > 0 ) { 123 | 124 | // Populate the checklists 125 | $quick_edit_row.find( 'ul.cpt-onomy-checklist' ).each( function() { 126 | $( this ).cpt_onomy_populate_quick_edit_checklist( $term_ids ); 127 | }); 128 | 129 | } 130 | 131 | } 132 | }); 133 | 134 | } 135 | 136 | } 137 | 138 | }; 139 | } 140 | 141 | function cpt_onomy_save_quick_edit() { 142 | 143 | // We create a copy of the original inline edit post, overwrite and then "call" the copy 144 | var $wp_inline_edit_save = inlineEditPost.save; 145 | inlineEditPost.save = function( id ) { 146 | 147 | // "Call" the original save function 148 | $wp_inline_edit_save.apply( this, arguments ); 149 | 150 | // Get the post type 151 | var $post_type = $( 'input[name="post_type"]' ).val(); 152 | 153 | // Get the post ID 154 | var $id = 0; 155 | if ( typeof( id ) == 'object' ) { 156 | $id = parseInt( this.getId( id ) ); 157 | } 158 | 159 | // We don't have to do this stuff for 'post' or 'page' 160 | if ( ! ( $post_type == 'post' || $post_type == 'page' ) && $id > 0 ) { 161 | 162 | // Get the table's column info 163 | var $table_columns = new Array(); 164 | $( 'table.wp-list-table thead th' ).each( function() { 165 | $.each( $( this ).attr( 'class' ).split( ' ' ), function( $index, $value ) { 166 | if ( $value.match( /^(column\-)/i ) ) { 167 | $table_columns.push( $value ); 168 | } 169 | }); 170 | }); 171 | 172 | // When WordPress ajax is complete 173 | $( 'table.wp-list-table' ).ajaxComplete( function() { 174 | 175 | // Define the post row 176 | var $post_row = $( inlineEditPost.what + $id ); 177 | 178 | // Store which columns need to be populated later 179 | var $populate_columns = new Array(); 180 | 181 | /** 182 | * WordPress adds "default" columns that might have 183 | * been removed so remove columns that shouldn't be here. 184 | */ 185 | $post_row.children( 'td' ).each( function() { 186 | var $column_td = $( this ); 187 | $.each( $column_td.attr( 'class' ).split( ' ' ), function( $index, $value ) { 188 | if ( $value.match( /^(column\-)/i ) ) { 189 | if ( $.inArray( $value, $table_columns ) < 0 ) { 190 | $column_td.remove(); 191 | } 192 | } 193 | }); 194 | }); 195 | 196 | var $loop_test = false; 197 | do { 198 | $loop_test = false; 199 | var $column_index = 1; 200 | $post_row.children( 'td' ).each( function() { 201 | var $column_td = $( this ); 202 | $.each( $column_td.attr( 'class' ).split( ' ' ), function( $index, $value ) { 203 | if ( $value.match( /^(column\-)/i ) ) { 204 | if ( $value != $table_columns[ $column_index ] ) { 205 | 206 | // Save column info so it can be populated later 207 | $populate_columns.push( $table_columns[ $column_index ] ); 208 | 209 | // Get column name 210 | var $column_name = $table_columns[ $column_index ].replace( /^(column\-)/i, '' ); 211 | 212 | // Add column 213 | var $new_column = ' '; 214 | 215 | // Add before 216 | $new_column = $( $new_column ).insertBefore( $column_td ); 217 | 218 | // Hide, if necessary 219 | if ( $( 'table.wp-list-table thead th.'+$table_columns[ $column_index ] ).is( ':hidden' ) ) { 220 | $new_column.hide(); 221 | } 222 | 223 | $loop_test = true; 224 | 225 | } 226 | } 227 | }); 228 | $column_index++; 229 | }); 230 | } 231 | while ( $loop_test ); 232 | 233 | // Populate columns 234 | $.each( $populate_columns, function( $index, $value ) { 235 | 236 | // Get the column info 237 | $.ajax({ 238 | url: ajaxurl, 239 | type: 'POST', 240 | async: true, 241 | cache: false, 242 | data: { 243 | action: 'custom_post_type_onomy_quick_edit_populate_custom_columns', 244 | custom_post_type_onomies_post_id: $id, 245 | custom_post_type_onomies_post_type: $post_type, 246 | custom_post_type_onomies_column_name: $value.replace( /^(column\-)/i, '' ) 247 | }, 248 | success: function( $column_text ) { 249 | 250 | // If not blank, add column info 251 | if ( $column_text != '' ) { 252 | $post_row.children( 'td.'+$value ).html( $column_text ); 253 | } 254 | 255 | } 256 | }); 257 | 258 | }); 259 | 260 | }); 261 | 262 | } 263 | 264 | } 265 | 266 | } 267 | 268 | function cpt_onomy_exclude_from_bulk_edit() { 269 | 270 | // We create a copy of the original inline edit post, overwrite and then "call" the copy 271 | var $wp_inline_set_bulk = inlineEditPost.setBulk; 272 | inlineEditPost.setBulk = function() { 273 | 274 | // "Call" the original function 275 | $wp_inline_set_bulk.apply( this, arguments ); 276 | 277 | // Define the bulk edit row 278 | var $bulk_edit_row = $( '#bulk-edit' ); 279 | if ( $bulk_edit_row.size() > 0 ) { 280 | 281 | // Get the post type 282 | var $post_type = jQuery( 'input[name="post_type"]' ).val(); 283 | 284 | // Get the taxonomies 285 | var $taxonomies = $bulk_edit_row.cpt_onomy_bulk_quick_edit_get_taxonomies(); 286 | 287 | /** 288 | * Get the "include" term IDs with "include", 289 | * we have to iterate through each taxonomy. 290 | */ 291 | $.each( $taxonomies, function( $index, $taxonomy ) { 292 | $.ajax({ 293 | url: ajaxurl, 294 | type: 'POST', 295 | dataType: 'json', 296 | async: true, 297 | cache: false, 298 | data: { 299 | action: 'custom_post_type_onomy_get_cpt_onomy_terms_include_term_ids', 300 | custom_post_type_onomies_taxonomy: $taxonomy, 301 | custom_post_type_onomies_post_type: $post_type 302 | }, 303 | success: function( $term_ids ) { 304 | 305 | // If $term_ids is array and not empty 306 | if ( $.isArray( $term_ids ) && $term_ids.length > 0 ) { 307 | 308 | // Remove from checklists 309 | $bulk_edit_row.find( 'ul.cpt-onomy-checklist.cpt-onomy-' + $taxonomy ).each( function() { 310 | $( this ).cpt_onomy_remove_from_quick_edit_checklist( $term_ids, true ); 311 | }); 312 | 313 | } 314 | 315 | } 316 | }); 317 | }); 318 | 319 | // Get the "exclude" term IDs 320 | $.ajax({ 321 | url: ajaxurl, 322 | type: 'POST', 323 | dataType: 'json', 324 | async: true, 325 | cache: false, 326 | data: { 327 | action: 'custom_post_type_onomy_get_cpt_onomy_terms_exclude_term_ids', 328 | custom_post_type_onomies_taxonomies: $taxonomies, 329 | custom_post_type_onomies_post_type: $post_type 330 | }, 331 | success: function( $term_ids ) { 332 | 333 | // If $term_ids is array and not empty 334 | if ( $.isArray( $term_ids ) && $term_ids.length > 0 ) { 335 | 336 | // Remove from checklists 337 | $bulk_edit_row.find( 'ul.cpt-onomy-checklist' ).each( function() { 338 | $( this ).cpt_onomy_remove_from_quick_edit_checklist( $term_ids, false ); 339 | }); 340 | 341 | } 342 | 343 | } 344 | }); 345 | 346 | } 347 | 348 | }; 349 | } 350 | 351 | function cpt_onomy_save_bulk_edit() { 352 | 353 | $( '#bulk_edit' ).live( 'click', function() { 354 | 355 | // Define the bulk edit row 356 | var $bulk_row = $( '#bulk-edit' ); 357 | 358 | // Get the selected post ids 359 | var $post_ids = new Array(); 360 | $bulk_row.find( '#bulk-titles' ).children().each( function() { 361 | $post_ids.push( $( this ).attr( 'id' ).replace( /^(ttle)/i, '' ) ); 362 | }); 363 | 364 | // Find each CPT-onomy checklist and get the checked IDs 365 | $bulk_row.find( 'ul.cpt-onomy-checklist' ).each( function() { 366 | 367 | // Get CPT-onomy name 368 | var $taxonomy = ''; 369 | $.each( $( this ).attr( 'class' ).split( ' ' ), function( $index, $value ) { 370 | if ( $value != 'cpt-onomy-checklist' && $value.match( /^(cpt\-onomy\-)/i ) ) { 371 | $taxonomy = $value.replace( /^(cpt\-onomy\-)/i, '' ); 372 | } 373 | }); 374 | 375 | if ( $taxonomy != '' ) { 376 | 377 | // Get the checked IDs 378 | var $checked_ids = new Array(); 379 | $( this ).find( 'input:checked' ).each( function() { 380 | $checked_ids.push( $( this ).attr( 'value' ) ); 381 | }); 382 | 383 | // Save the data 384 | $.ajax({ 385 | url: ajaxurl, 386 | type: 'POST', 387 | async: false, 388 | cache: false, 389 | data: { 390 | action: 'custom_post_type_onomy_save_bulk_edit', 391 | custom_post_type_onomies_post_ids: $post_ids, 392 | custom_post_type_onomies_taxonomy: $taxonomy, 393 | custom_post_type_onomies_checked_ids: $checked_ids 394 | } 395 | }); 396 | 397 | } 398 | }); 399 | 400 | }); 401 | 402 | } 403 | 404 | // Quick edit 405 | if ( inlineEditPost ) { 406 | cpt_onomy_populate_quick_edit(); 407 | cpt_onomy_save_quick_edit(); 408 | cpt_onomy_exclude_from_bulk_edit(); 409 | } else { 410 | jQuery( cpt_onomy_populate_quick_edit ); 411 | jQuery( cpt_onomy_save_quick_edit ); 412 | } 413 | 414 | // Bulk edit 415 | cpt_onomy_save_bulk_edit(); 416 | 417 | })(jQuery); 418 | 419 | jQuery.fn.cpt_onomy_bulk_quick_edit_get_taxonomies = function() { 420 | var $taxonomies = new Array(); 421 | jQuery( this ).find( 'ul.cpt-onomy-checklist' ).each( function() { 422 | jQuery.each( jQuery( this ).attr( 'class' ).split( ' ' ), function( index, value ) { 423 | if ( value != 'cpt-onomy-checklist' && value.match( /^(cpt\-onomy\-)/i ) ) { 424 | $taxonomies.push( value.replace( /^(cpt\-onomy\-)/i, '' ) ); 425 | } 426 | }); 427 | }); 428 | return $taxonomies; 429 | } 430 | 431 | jQuery.fn.cpt_onomy_remove_from_quick_edit_checklist = function( $term_ids, $include ) { 432 | jQuery( this ).children( 'li' ).each( function() { 433 | 434 | // Retrieve item info 435 | var $list_item = jQuery( this ); 436 | var $list_item_id = parseInt( $list_item.attr( 'id' ).match( /[0-9]+/ ) ); 437 | 438 | /** 439 | * Remove item. 440 | * 441 | * If $include is true, we're removing everything 442 | * NOT in $term_ids. 443 | * 444 | * Otherwise, remove if in $term_ids. 445 | */ 446 | if ( ( $include && jQuery.inArray( $list_item_id, $term_ids ) == -1 ) 447 | || ( ! $include && jQuery.inArray( $list_item_id, $term_ids ) > -1 ) ) { 448 | $list_item.remove(); 449 | } 450 | 451 | }); 452 | } 453 | 454 | jQuery.fn.cpt_onomy_populate_quick_edit_checklist = function( $term_ids ) { 455 | jQuery( this ).children( 'li' ).each( function() { 456 | 457 | var $list_item = jQuery( this ); 458 | var $input = $list_item.find( 'input#in-'+$list_item.attr( 'id' ) ); 459 | 460 | // Check the checkbox 461 | if ( jQuery.inArray( $input.attr( 'value' ), $term_ids ) > -1 ) { 462 | $input.attr( 'checked', 'checked' ); 463 | } 464 | 465 | // Take care of the children 466 | if ( $list_item.children( 'ul' ).size() > 0 ) { 467 | $list_item.children( 'ul' ).cpt_onomy_populate_quick_edit_checklist( $term_ids ); 468 | } 469 | 470 | }); 471 | } -------------------------------------------------------------------------------- /assets/js/admin-options-validate.js: -------------------------------------------------------------------------------- 1 | jQuery.noConflict()(function(){ 2 | 3 | // Validate form 4 | jQuery( 'form#custom-post-type-onomies-edit-cpt' ).validate({ 5 | onkeyup: false, 6 | ignore: [] 7 | }); 8 | 9 | // Create invalid post type name message 10 | $invalid_post_type_name = null 11 | if ( cpt_onomies_admin_options_L10n.invalid_post_type_name != '' ) { 12 | $invalid_post_type_name = cpt_onomies_admin_options_L10n.invalid_post_type_name; 13 | } else { 14 | $invalid_post_type_name = 'Your post type name is invalid.'; 15 | } 16 | 17 | // Validate custom post type name to make sure it contains valid characters 18 | jQuery.validator.addMethod( 'custom_post_type_onomies_validate_post_type_name_characters', function( value, element ) { 19 | return this.optional( element ) || ( value.length <= 20 && ! value.match( /([^a-z0-9\_\-])/ ) ); 20 | }, $invalid_post_type_name ); 21 | 22 | // Create post type name exists message 23 | $post_type_name_exists = null; 24 | if ( cpt_onomies_admin_options_L10n.post_type_name_exists != '' ) { 25 | $post_type_name_exists = cpt_onomies_admin_options_L10n.post_type_name_exists; 26 | } else { 27 | $post_type_name_exists = 'That post type name already exists. Please choose another name.'; 28 | } 29 | 30 | // Validate custom post type name to make sure post type doesnt already exist 31 | jQuery.validator.addMethod( 'custom_post_type_onomies_validate_post_type_name', function( value, element ) { 32 | var validator = this, response; 33 | jQuery.ajax({ 34 | url: ajaxurl, 35 | type: 'POST', 36 | async: false, 37 | cache: false, 38 | data: { 39 | action: 'custom_post_type_onomy_validate_if_post_type_exists', 40 | custom_post_type_onomies_is_network_admin: jQuery( "#custom-post-type-onomies-is-network-admin" ).val(), 41 | original_custom_post_type_onomies_cpt_name: jQuery( "#custom-post-type-onomies-custom-post-type-original-name" ).val(), 42 | custom_post_type_onomies_cpt_name: value 43 | }, 44 | success: function( data ) { 45 | response = ( data == 'true' ) ? true : false; 46 | }, 47 | complete: function() { 48 | response = ( response == null ) ? true : response; 49 | } 50 | }); 51 | return response; 52 | }, $post_type_name_exists ); 53 | 54 | }); -------------------------------------------------------------------------------- /assets/js/admin-options.js: -------------------------------------------------------------------------------- 1 | var $cpt_onomies_changed_form = 0; 2 | jQuery.noConflict()(function(){ 3 | 4 | // Count how many times the form is changed 5 | jQuery( 'form#custom-post-type-onomies-edit-cpt' ).change( function() { 6 | $cpt_onomies_changed_form++; 7 | }); 8 | 9 | // Check to make sure info is saved before continuing 10 | jQuery( 'a:not(.delete_cpt_onomy_custom_post_type):not(.thickbox):not([target="_blank"])' ).live( 'click', function( $event ) { 11 | 12 | // If the form has been changed... 13 | if ( $cpt_onomies_changed_form ) { 14 | 15 | // Build the message 16 | var $message = null; 17 | 18 | if ( cpt_onomies_admin_options_L10n.unsaved_message1 != '' ) { 19 | $message = cpt_onomies_admin_options_L10n.unsaved_message1 20 | } else { 21 | $message = 'It looks like you might have some unsaved changes.'; 22 | } 23 | 24 | if ( cpt_onomies_admin_options_L10n.unsaved_message2 != '' ) { 25 | $message += '\n' + cpt_onomies_admin_options_L10n.unsaved_message2 26 | } else { 27 | $message += '\nAre you sure you want to leave?'; 28 | } 29 | 30 | // Ask the user to confirm 31 | var $confirm = confirm( $message ); 32 | 33 | // If they confirmed, stop the event from happening 34 | if ( $confirm != true ) { 35 | $event.preventDefault(); 36 | } 37 | 38 | } 39 | 40 | }); 41 | 42 | // Show message 43 | jQuery( '.show_cpt_message' ).live( 'click', function( $event ) { 44 | 45 | // Stop the event from happening 46 | $event.preventDefault(); 47 | 48 | // Show the message 49 | alert( jQuery( this ).attr( 'alt' ) ); 50 | 51 | }); 52 | 53 | // Show "delete conflicting terms" confirmation 54 | jQuery( '.delete-conflicting-tax-terms.button' ).on( 'click', function( $event ) { 55 | 56 | // Build the message 57 | var $message = null; 58 | 59 | if ( cpt_onomies_admin_options_L10n.delete_conflicting_terms_message1 != '' ) { 60 | $message = cpt_onomies_admin_options_L10n.delete_conflicting_terms_message1; 61 | } else { 62 | $message = 'Are you sure you want to delete the conflicting taxonomy terms?'; 63 | } 64 | 65 | if ( cpt_onomies_admin_options_L10n.delete_conflicting_terms_message2 != '' ) { 66 | $message += '\n\n' + cpt_onomies_admin_options_L10n.delete_conflicting_terms_message2; 67 | } else { 68 | $message += '\n\nThere is NO undo and once you click "OK", all of the terms will be deleted and cannot be restored.'; 69 | } 70 | 71 | // Ask the user to confirm 72 | var $confirm = confirm( $message ); 73 | 74 | // If they confirmed, stop the event from happening 75 | if ( $confirm != true ) { 76 | $event.preventDefault(); 77 | } 78 | 79 | }); 80 | 81 | // Show delete confirmation 82 | jQuery( '.delete_cpt_onomy_custom_post_type' ).live( 'click', function( $event ) { 83 | 84 | // Build the message 85 | var $message = null; 86 | 87 | if ( cpt_onomies_admin_options_L10n.delete_message1 != '' ) { 88 | $message = cpt_onomies_admin_options_L10n.delete_message1; 89 | } else { 90 | $message = 'Are you sure you want to delete this custom post type?'; 91 | } 92 | 93 | if ( cpt_onomies_admin_options_L10n.delete_message2 != '' ) { 94 | $message += '\n\n' + cpt_onomies_admin_options_L10n.delete_message2; 95 | } else { 96 | $message += '\n\nThere is NO undo and once you click "OK", all of your settings will be gone.'; 97 | } 98 | 99 | if ( cpt_onomies_admin_options_L10n.delete_message3 != '' ) { 100 | $message += '\n\n' + cpt_onomies_admin_options_L10n.delete_message3; 101 | } else { 102 | $message += '\n\nDeleting your custom post type DOES NOT delete the actual posts.'; 103 | } 104 | 105 | if ( cpt_onomies_admin_options_L10n.delete_message4 != '' ) { 106 | $message += ' ' + cpt_onomies_admin_options_L10n.delete_message4; 107 | } else { 108 | $message += ' They\'ll be waiting for you if you decide to register this post type again.'; 109 | } 110 | 111 | if ( cpt_onomies_admin_options_L10n.delete_message5 != '' ) { 112 | $message += ' ' + cpt_onomies_admin_options_L10n.delete_message5; 113 | } else { 114 | $message += ' Just make sure you use the same name.'; 115 | } 116 | 117 | // Ask the user to confirm 118 | var $confirm = confirm( $message ); 119 | 120 | // If they confirmed, stop the event from happening 121 | if ( $confirm != true ) { 122 | $event.preventDefault(); 123 | } 124 | 125 | }); 126 | 127 | // Change the header label 128 | var $default_header_label = jQuery( '#custom-post-type-onomies-edit-header .label' ).html(); 129 | var $cpt_label = jQuery( '#custom-post-type-onomies-custom-post-type-label' ); 130 | 131 | // Make sure the label is checked out the gate 132 | $cpt_label.custom_post_type_onomies_change_header_label( $default_header_label ); 133 | $cpt_label.keyup( function() { 134 | jQuery( this ).custom_post_type_onomies_change_header_label( $default_header_label ); 135 | }); 136 | $cpt_label.change( function() { 137 | jQuery( this ).custom_post_type_onomies_change_header_label( $default_header_label ); 138 | }); 139 | 140 | $cpt_label.blur( function() { 141 | jQuery( this ).custom_post_type_onomies_change_header_label( $default_header_label ); 142 | }); 143 | 144 | // Create a field name 145 | var $cpt_name = jQuery( 'input#custom-post-type-onomies-custom-post-type-name' ); 146 | 147 | // Make sure the name is created out the gate, if need be 148 | $cpt_name.custom_post_type_onomies_create_name( $cpt_label.val() ); 149 | $cpt_label.change( function() { 150 | $cpt_name.custom_post_type_onomies_create_name( jQuery( this ).val() ); 151 | }); 152 | 153 | // Dim post type name when not "active" 154 | $cpt_name.addClass( 'inactive' ); 155 | $cpt_name.focus( function() { 156 | jQuery( this ).removeClass( 'inactive' ); 157 | }); 158 | $cpt_name.blur( function() { 159 | jQuery( this ).addClass( 'inactive' ); 160 | }); 161 | 162 | // Reset properties 163 | jQuery( '#custom-post-type-onomies-edit-table .reset_property' ).live( 'click', function() { 164 | jQuery( this ).closest( 'table' ).find( 'input[type="radio"]:checked' ).removeAttr( 'checked' ); 165 | }); 166 | 167 | // Take care of any dismiss messages 168 | jQuery( '.dismiss' ).each( function() { 169 | jQuery( this ).custom_post_type_onomies_setup_dismiss(); 170 | }); 171 | 172 | // Take care of the advanced open-close and messages 173 | jQuery( '#custom-post-type-onomies-edit-table td.advanced' ).each( function() { 174 | jQuery( this ).children( 'table' ).custom_post_type_onomies_setup_advanced_table(); 175 | }); 176 | 177 | // Open the help tab 178 | jQuery( '.custom_post_type_onomies_show_help_tab' ).live( 'click', function( $event ) { 179 | 180 | // Stop the event from happening 181 | $event.preventDefault(); 182 | 183 | // Define the help tab 184 | var $panel = jQuery( '#contextual-help-wrap' ); 185 | if ( ! $panel.length ) { 186 | return; 187 | } 188 | 189 | // Open help tab 190 | if ( ! $panel.is( ':visible' ) ) { 191 | 192 | // Scroll to top of page 193 | jQuery( 'html,body' ).scrollTop( 0 ); 194 | 195 | // Define the "Help" tab link 196 | var $link = jQuery( '#contextual-help-link' ); 197 | 198 | // Hide any other tab links 199 | jQuery( '.screen-meta-toggle' ).not( $link.parent() ).css( 'visibility', 'hidden' ); 200 | 201 | // Show the help tab 202 | $panel.parent().show(); 203 | $panel.slideDown( 'fast', function() { 204 | 205 | // Make the tab link active 206 | $link.addClass('screen-meta-active'); 207 | 208 | }); 209 | 210 | } 211 | 212 | }); 213 | 214 | }); 215 | 216 | jQuery.fn.custom_post_type_onomies_change_header_label = function( $default_header_label ) { 217 | 218 | if ( jQuery( this ).val() != '' ) { 219 | jQuery( '#custom-post-type-onomies-edit-header .label' ).html( jQuery( this ).val() ); 220 | } else if ( $default_header_label != '' ) { 221 | jQuery( '#custom-post-type-onomies-edit-header .label' ).html( $default_header_label ); 222 | } 223 | 224 | } 225 | 226 | jQuery.fn.custom_post_type_onomies_create_name = function( $label_value ) { 227 | 228 | // If name is blank, convert label value to name 229 | if ( jQuery( this ).val() == '' ) { 230 | jQuery( this ).val( $label_value.replace( /[^a-zA-Z0-9\_\s]/i, '' ).replace( /\s/, '_' ).toLowerCase() ); 231 | } 232 | 233 | } 234 | 235 | jQuery.fn.custom_post_type_onomies_setup_dismiss = function() { 236 | 237 | var $dismiss = jQuery( this ); 238 | var $dismiss_id = jQuery( this ).attr( 'id' ); 239 | var $close = jQuery( 'x' ); 240 | 241 | $close.click( function() { 242 | 243 | // Remove message 244 | jQuery( this ).parent( '.dismiss' ).remove(); 245 | 246 | // Update user options 247 | jQuery.ajax({ 248 | url: ajaxurl, 249 | type: 'POST', 250 | async: false, 251 | cache: false, 252 | data: { 253 | action: 'custom_post_type_onomy_update_edit_custom_post_type_dismiss', 254 | custom_post_type_onomies_dismiss_id: $dismiss_id 255 | } 256 | }); 257 | 258 | }); 259 | 260 | $dismiss.append( $close ); 261 | 262 | } 263 | 264 | jQuery.fn.custom_post_type_onomies_setup_advanced_table = function() { 265 | 266 | var $advanced = jQuery( this ); 267 | 268 | if ( $advanced.closest( '#custom-post-type-onomies-edit-table' ).hasClass( 'show' ) ) { 269 | $advanced.custom_post_type_onomies_show_advanced_table(); 270 | } else { 271 | $advanced.custom_post_type_onomies_hide_advanced_table(); 272 | } 273 | 274 | } 275 | 276 | jQuery.fn.custom_post_type_onomies_show_advanced_table = function() { 277 | 278 | // Set the "advanced" table 279 | var $advanced = jQuery( this ); 280 | 281 | // "Show" the table 282 | $advanced.removeClass( 'hide' ); 283 | 284 | // Get edit table 285 | var $edit_table = null; 286 | 287 | if ( $advanced.closest( '#custom-post-type-onomies-edit-table' ).hasClass( 'site_registration' ) ) { 288 | $edit_table = 'site_registration'; 289 | } else if ( $advanced.closest( '#custom-post-type-onomies-edit-table' ).hasClass( 'labels' ) ) { 290 | $edit_table = 'labels'; 291 | } else { 292 | $edit_table = 'options'; 293 | } 294 | 295 | // Create close message 296 | var $close_message = null; 297 | 298 | if ( $edit_table == 'site_registration' ) { 299 | 300 | if ( cpt_onomies_admin_options_L10n.close_site_registration != '' ) { 301 | $close_message = cpt_onomies_admin_options_L10n.close_site_registration; 302 | } else { 303 | $close_message = 'Close Site Registration'; 304 | } 305 | 306 | } else if ( $edit_table == 'labels' ) { 307 | 308 | if ( cpt_onomies_admin_options_L10n.close_labels != '' ) { 309 | $close_message = cpt_onomies_admin_options_L10n.close_labels; 310 | } else { 311 | $close_message = 'Close Labels'; 312 | } 313 | 314 | } else if ( $edit_table == 'options' ) { 315 | 316 | if ( cpt_onomies_admin_options_L10n.close_advanced_options != '' ) { 317 | $close_message = cpt_onomies_admin_options_L10n.close_advanced_options; 318 | } else { 319 | $close_message = 'Close Advanced Options'; 320 | } 321 | 322 | } else { 323 | 324 | $close_message = 'Close'; 325 | 326 | } 327 | 328 | $close_message = '' + $close_message + ''; 329 | 330 | // Add close message 331 | if ( $advanced.parent( '.advanced_message' ).size() > 0 ) { 332 | $advanced.parent( '.advanced_message' ).remove(); 333 | } 334 | $advanced.closest( 'td' ).prepend( '' + $close_message + '' ); 335 | 336 | // If they click "close" 337 | $advanced.closest( 'td' ).children( '.advanced_message' ).children( '.close_advanced' ).click( function() { 338 | 339 | // Remove advanced message and close table 340 | jQuery( this ).parent( '.advanced_message' ).remove(); 341 | $advanced.custom_post_type_onomies_hide_advanced_table(); 342 | 343 | // Update user options 344 | jQuery.ajax({ 345 | url: ajaxurl, 346 | type: 'POST', 347 | async: false, 348 | cache: false, 349 | data: { 350 | action: 'custom_post_type_onomy_update_edit_custom_post_type_closed_edit_tables', 351 | custom_post_type_onomies_edit_table: $edit_table, 352 | custom_post_type_onomies_edit_table_show: 'false' 353 | } 354 | }); 355 | 356 | }); 357 | 358 | } 359 | 360 | jQuery.fn.custom_post_type_onomies_hide_advanced_table = function() { 361 | 362 | // Set the "advanced" table 363 | var $advanced = jQuery( this ); 364 | 365 | // "Hide" the table 366 | $advanced.addClass( 'hide' ); 367 | 368 | // Get edit table 369 | var $edit_table = null; 370 | if ( $advanced.closest( '#custom-post-type-onomies-edit-table' ).hasClass( 'site_registration' ) ) { 371 | $edit_table = 'site_registration'; 372 | } else if ( $advanced.closest( '#custom-post-type-onomies-edit-table' ).hasClass( 'labels' ) ) { 373 | $edit_table = 'labels'; 374 | } else { 375 | $edit_table = 'options'; 376 | } 377 | 378 | // Create message 379 | var $message = null; 380 | 381 | // Add message 1 for the site registration table 382 | if ( $edit_table == 'site_registration' ) { 383 | 384 | if ( cpt_onomies_admin_options_L10n.site_registration_message1 != '' ) { 385 | $message = cpt_onomies_admin_options_L10n.site_registration_message1; 386 | } else { 387 | $message = 'If you want to register your custom post type on multiple sites, but not the entire network, this section is for you. However, your list of sites is kind of long so we hid it away as to not clog up your screen.'; 388 | } 389 | 390 | } 391 | 392 | // Add message 1 for the labels table 393 | else if ( $edit_table == 'labels' ) { 394 | 395 | if ( cpt_onomies_admin_options_L10n.labels_message1 != '' ) { 396 | $message = cpt_onomies_admin_options_L10n.labels_message1; 397 | } else { 398 | $message = 'Instead of sticking with the boring defaults, why don\'t you customize the labels used for your custom post type. They can really add a nice touch.'; 399 | } 400 | 401 | } 402 | 403 | // Add message 1 for the advanced options table 404 | else if ( $edit_table == 'options' ) { 405 | 406 | if ( cpt_onomies_admin_options_L10n.advanced_options_message1 != '' ) { 407 | $message = cpt_onomies_admin_options_L10n.advanced_options_message1; 408 | } else { 409 | $message = 'You can make your custom post type as "advanced" as you like but, beware, some of these options can get tricky. Visit the "Help" tab if you get stuck.'; 410 | } 411 | 412 | } 413 | 414 | // Add links to message 415 | $message += ' '; 416 | 417 | if ( $edit_table == 'site_registration' ) { 418 | 419 | if ( cpt_onomies_admin_options_L10n.site_registration_message2 != '' ) { 420 | $message += cpt_onomies_admin_options_L10n.site_registration_message2; 421 | } else { 422 | $message += 'Customize the Sites'; 423 | } 424 | 425 | } else if ( $edit_table == 'labels' ) { 426 | 427 | if ( cpt_onomies_admin_options_L10n.labels_message2 != '' ) { 428 | $message += cpt_onomies_admin_options_L10n.labels_message2; 429 | } else { 430 | $message += 'Customize the Labels'; 431 | } 432 | 433 | } else if ( $edit_table == 'options' ) { 434 | 435 | if ( cpt_onomies_admin_options_L10n.advanced_options_message2 != '' ) { 436 | $message += cpt_onomies_admin_options_L10n.advanced_options_message2; 437 | } else { 438 | $message += 'Edit the Advanced Options'; 439 | } 440 | 441 | } 442 | 443 | $message += ''; 444 | 445 | // Add message 446 | if ( $advanced.parent( '.advanced_message' ).size() > 0 ) { 447 | $advanced.parent( '.advanced_message' ).remove(); 448 | } 449 | $advanced.closest( 'td' ).prepend( '' + $message + '' ); 450 | 451 | // If they click "show" 452 | $advanced.closest( 'td' ).children( '.advanced_message' ).children( '.show_advanced' ).click( function() { 453 | 454 | // Remove advanced message and show table 455 | jQuery( this ).parent( '.advanced_message' ).remove(); 456 | $advanced.custom_post_type_onomies_show_advanced_table(); 457 | 458 | // Update user options 459 | jQuery.ajax({ 460 | url: ajaxurl, 461 | type: 'POST', 462 | async: false, 463 | cache: false, 464 | data: { 465 | action: 'custom_post_type_onomy_update_edit_custom_post_type_closed_edit_tables', 466 | custom_post_type_onomies_edit_table: $edit_table, 467 | custom_post_type_onomies_edit_table_show: 'true' 468 | } 469 | }); 470 | 471 | }); 472 | 473 | } -------------------------------------------------------------------------------- /assets/js/admin-post.js: -------------------------------------------------------------------------------- 1 | (function($){ 2 | 3 | // "Most used" tag cloud 4 | $( '.cpt_onomies_tag_cloud' ).click( function( $event ) { 5 | $event.preventDefault(); 6 | 7 | // Code taken from tagBox.get 8 | var $id = $( this ).attr( 'id' ); 9 | var $taxonomy = $id.replace( /^([a-z]+)-/i, '' ); 10 | 11 | $.post( ajaxurl, { 'action':'get-tagcloud', 'tax':$taxonomy }, function( $r, $stat ) { 12 | 13 | if ( 0 == $r || 'success' != $stat ) { 14 | $r = wpAjax.broken; 15 | } 16 | 17 | // Get the tag cloud 18 | $r = $( '

    ' + $r + '

    ' ); 19 | 20 | // Setup click term event 21 | $( 'a', $r ).click( function( $term_event ) { 22 | $term_event.preventDefault(); 23 | 24 | // Add tag (tag cloud doesn't show for hierarchical so we don't need parent this go 'round) 25 | var $term = $( this ).html(); 26 | var $term_id = $( this ).attr( 'class' ).replace( /[^0-9]/g, '' ); 27 | 28 | if ( $term && $term_id ) { 29 | 30 | // Find tag checklist 31 | var $tag_checklist = $( this ).closest( '.inside' ).find( '.cpt_onomies_tags_div' ).find( '.cpt_onomies_tag_checklist' ); 32 | $tag_checklist.custom_post_type_onomies_tag_checklist_add_tag_term( $taxonomy, $term, $term_id, '' ); 33 | 34 | } 35 | 36 | return false; 37 | }); 38 | 39 | // Add tag cloud 40 | $( '#' + $id ).after( $r ); 41 | 42 | }); 43 | 44 | // Toggle tag cloud link 45 | $(this).unbind().click( function() { 46 | $(this).siblings( '.the-tagcloud' ).toggle(); 47 | return false; 48 | }); 49 | 50 | return false; 51 | }); 52 | 53 | })(jQuery); 54 | 55 | jQuery.noConflict()(function(){ 56 | 57 | /** 58 | * Make sure "disabled" dropdowns are actually disabled 59 | * this attribute is supposed to already be in place but this is a backup check. 60 | */ 61 | jQuery( 'select.category.cpt_onomies' ).each( function() { 62 | 63 | // Get the taxonomy name 64 | var $taxonomy = jQuery( this ).attr( 'id' ).replace( /^taxonomy-/i, '' ); 65 | 66 | // If user cannot assign terms 67 | if ( ! cpt_onomies_admin_post_data.can_assign_terms[ $taxonomy ] ) { 68 | jQuery( this ).attr( 'disabled', 'disabled' ); 69 | } 70 | 71 | }); 72 | 73 | // Handle autocomplete for CPT-onomies tags 74 | jQuery( '.cpt_onomies_tags_div' ).each( function() { 75 | 76 | var $post_id = jQuery( '#post_ID' ).val(); 77 | var $post_type = jQuery( '#post_type' ).val(); 78 | var $taxonomy = jQuery( this ).attr( 'id' ).replace( /^taxonomy-/i, '' ); 79 | 80 | // These elements wont "exist" if user does not have capability to assign terms 81 | var $new_tag_input = jQuery( this ).find( 'input.cpt_onomies_new_tag' ); 82 | var $add_tag_button = jQuery( this ).find( 'input.cpt_onomies_tag_add' ); 83 | 84 | // This hidden element is used to save the tag id for terms added to the new tag input 85 | var $hidden_tag_id = 'custom_post_type_onomy_' + $taxonomy + '_selected_term_id'; 86 | var $hidden_tag_parent = 'custom_post_type_onomy_' + $taxonomy + '_selected_term_parent'; 87 | 88 | // This element stores our list of tags and shows up no matter what 89 | var $tag_checklist = jQuery( this ).find( '.cpt_onomies_tag_checklist' ); 90 | 91 | // Remove the hidden textarea to remove any $_POST confusion 92 | jQuery( this ).find( '.nojs-tags' ).remove(); 93 | 94 | // Autocomplete new tags 95 | if ( $new_tag_input.size() > 0 ) { 96 | 97 | $new_tag_input.autocomplete({ 98 | delay: 200, 99 | source: function( $request, $response ){ 100 | jQuery.ajax({ 101 | url: ajaxurl, 102 | type: 'POST', 103 | async: true, 104 | cache: false, 105 | dataType: 'json', 106 | data: { 107 | action: 'custom_post_type_onomy_meta_box_autocomplete_callback', 108 | custom_post_type_onomies_taxonomy: $taxonomy, 109 | custom_post_type_onomies_term: $request.term, 110 | custom_post_type_onomies_post_type: $post_type, 111 | custom_post_type_onomies_post_id: $post_id 112 | }, 113 | success: function( $data ){ 114 | $response( jQuery.map( $data, function( $item ) { 115 | return { 116 | value: $item.value, 117 | label: $item.label, 118 | parent: $item.parent 119 | }; 120 | })); 121 | } 122 | }); 123 | }, 124 | focus: function( $event, $ui ) { 125 | 126 | /** 127 | * Change the input value. 128 | * 129 | * This approach allows us "html entity decode" the label. 130 | */ 131 | $new_tag_input.val( jQuery( '
    ' ).html( $ui.item.label ).text() ); 132 | 133 | return false; 134 | 135 | }, 136 | select: function( $event, $ui ) { 137 | 138 | /** 139 | * Change the input value. 140 | * 141 | * This approach allows us "html entity decode" the label. 142 | */ 143 | $new_tag_input.val( jQuery( '
    ' ).html( $ui.item.label ).text() ); 144 | 145 | // Store the ID 146 | if ( jQuery( '#' + $hidden_tag_id ).size() == 0 ) { 147 | $new_tag_input.after( '' ); 148 | } else { 149 | jQuery( '#' + $hidden_tag_id ).val( $ui.item.value ); 150 | } 151 | 152 | // If parent, then store parent 153 | if ( $ui.item.parent != '' && $ui.item.parent != null && $ui.item.parent != undefined ) { 154 | 155 | if ( jQuery( '#' + $hidden_tag_parent ).size() == 0 ) { 156 | $new_tag_input.after( '' ); 157 | } else { 158 | jQuery( '#' + $hidden_tag_parent ).val( $ui.item.parent ); 159 | } 160 | 161 | } 162 | 163 | // Otherwise, remove the hidden input 164 | else { 165 | jQuery( '#' + $hidden_tag_parent ).remove(); 166 | } 167 | 168 | return false; 169 | } 170 | }).data( 'ui-autocomplete' )._renderItem = function( $ul, $item ) { 171 | 172 | // Add our class to the ul 173 | $ul.addClass( 'cpt_onomies' ); 174 | 175 | // If parent, add parent 176 | $parent = ''; 177 | if ( $item.parent != '' && $item.parent != null && $item.parent != undefined ) { 178 | $parent = '' + $item.parent.replace( ',', '/ ' ) + '/'; 179 | } 180 | 181 | // Return item 182 | return jQuery( '
  • ' ) 183 | .data( 'item.autocomplete', $item ) 184 | .append( '' + $parent + $item.label + '' ) 185 | .appendTo( $ul ); 186 | 187 | }; 188 | } 189 | 190 | // If typing, remove the error message 191 | $new_tag_input.click( function() { 192 | 193 | // Remove the error message 194 | jQuery( '#cpt-onomies-add-tag-error-message-' + $taxonomy ).remove(); 195 | 196 | }); 197 | 198 | $new_tag_input.change( function() { 199 | 200 | // Remove the error message 201 | jQuery( '#cpt-onomies-add-tag-error-message-' + $taxonomy ).remove(); 202 | 203 | }); 204 | 205 | $new_tag_input.keyup( function() { 206 | 207 | // Remove the error message 208 | jQuery( '#cpt-onomies-add-tag-error-message-' + $taxonomy ).remove(); 209 | 210 | }); 211 | 212 | // Add new tags 213 | $add_tag_button.click( function() { 214 | 215 | var $term = $new_tag_input.val(); 216 | var $term_id = jQuery( '#' + $hidden_tag_id ).val(); 217 | var $term_parent = jQuery( '#' + $hidden_tag_parent ).val(); 218 | var $cpt_onomies_add_tag_error_message = ''; 219 | 220 | // Remove the error message 221 | jQuery( '#cpt-onomies-add-tag-error-message-' + $taxonomy ).remove(); 222 | 223 | // Remove the hidden tag id 224 | jQuery( '#' + $hidden_tag_id ).remove(); 225 | 226 | // Remove the hidden tag parent 227 | jQuery( '#' + $hidden_tag_parent ).remove(); 228 | 229 | /** 230 | * Check to see if term exists if they typed in a term on their own. 231 | * 232 | * This will retrieve term id AND also get term name if they typed in a slug. 233 | */ 234 | if ( $term == '' || ( ! $term_id || $term_id == 0 || $term_id == '' ) ) { 235 | jQuery.ajax({ 236 | url: ajaxurl, 237 | type: 'POST', 238 | dataType: 'json', 239 | async: false, 240 | cache: false, 241 | data: { 242 | action: 'custom_post_type_onomy_check_if_term_exists', 243 | custom_post_type_onomies_term: $term, 244 | custom_post_type_onomies_term_id: $term_id, 245 | custom_post_type_onomies_taxonomy: $taxonomy, 246 | custom_post_type_onomies_get_parent_title: 'true' 247 | }, 248 | success: function( $term_exists ) { 249 | jQuery.each( $term_exists, function( $index, $value ) { 250 | 251 | if ( $index == 'name' ) { 252 | $term = $value; 253 | } else if ( $index == 'term_id' ) { 254 | $term_id = $value; 255 | } else if ( $index == 'parent' ) { 256 | $term_parent = $value; 257 | } 258 | 259 | }); 260 | } 261 | }); 262 | } 263 | 264 | if ( $term && $term_id ) { 265 | 266 | // Clear out the "new tags" input 267 | $new_tag_input.val( '' ); 268 | 269 | // We don't let posts create relationships with themselves 270 | if ( $post_id == $term_id ) { 271 | $cpt_onomies_add_tag_error_message = cpt_onomies_admin_post_L10n.no_self_relationship; 272 | } 273 | 274 | // This relationship already exists 275 | else if ( jQuery.inArray( $term_id, $tag_checklist.data( 'selected_term_ids' ) ) >= 0 ) { 276 | $cpt_onomies_add_tag_error_message = cpt_onomies_admin_post_L10n.relationship_already_exists; 277 | } 278 | 279 | // Add tag 280 | else { 281 | $tag_checklist.custom_post_type_onomies_tag_checklist_add_tag_term( $taxonomy, $term, $term_id, $term_parent ); 282 | } 283 | 284 | } 285 | 286 | // The term doesn't exist, so add message 287 | else { 288 | 289 | // Set error message 290 | $cpt_onomies_add_tag_error_message = cpt_onomies_admin_post_L10n.term_does_not_exist + ' ' + cpt_onomies_admin_post_L10n.add_the_term + ''; 291 | 292 | } 293 | 294 | // Add error message 295 | if ( $cpt_onomies_add_tag_error_message != '' ) { 296 | 297 | $cpt_onomies_add_tag_error_message = jQuery( '
    ' + $cpt_onomies_add_tag_error_message + ' ' + cpt_onomies_admin_post_L10n.close + '
    ' ); 298 | 299 | $cpt_onomies_add_tag_error_message.click( function() { 300 | jQuery( this ).remove(); 301 | }); 302 | jQuery( this ).after( $cpt_onomies_add_tag_error_message ); 303 | 304 | } 305 | 306 | }); 307 | 308 | // Going to store the selected terms 309 | $tag_checklist.data( 'selected_term_ids', [] ); 310 | 311 | // Show loading while we're getting the terms 312 | $tag_checklist.addClass( 'loading' ); 313 | 314 | // Add already selected terms 315 | jQuery.ajax({ 316 | url: ajaxurl, 317 | type: 'POST', 318 | dataType: 'json', 319 | async: true, 320 | cache: false, 321 | data: { 322 | action: 'custom_post_type_onomy_get_wp_object_terms', 323 | custom_post_type_onomies_post_ids: $post_id, 324 | custom_post_type_onomies_taxonomies: $taxonomy, 325 | custom_post_type_onomies_get_parent_title: 'true' 326 | }, 327 | success: function( $terms ) { 328 | 329 | // Make sure we get rid of the loading icon 330 | $tag_checklist.removeClass( 'loading' ); 331 | 332 | // If $terms is array and not empty 333 | if ( jQuery.isArray( $terms ) && $terms.length > 0 ) { 334 | jQuery.each( $terms, function( $term_index, $term_info ) { 335 | 336 | var $term = ''; 337 | var $term_id = ''; 338 | var $term_parent = ''; 339 | 340 | // Get the term information 341 | jQuery.each( $term_info, function( $name, $value ) { 342 | if ( $term == '' || $term_id == '' || $term_parent == '' ) { 343 | 344 | if ( $term == '' && $name == 'name' ) { 345 | $term = $value; 346 | } else if ( $term_id == '' && $name == 'term_id' ) { 347 | $term_id = $value; 348 | } else if ( $term_parent == '' && $name == 'parent' ) { 349 | $term_parent = $value; 350 | } 351 | 352 | } 353 | }); 354 | 355 | // Add to cpt_onomies_tag_checklist 356 | if ( $term != '' && $term_id != '' ) { 357 | $tag_checklist.custom_post_type_onomies_tag_checklist_add_tag_term( $taxonomy, $term, $term_id, $term_parent ); 358 | } 359 | 360 | }); 361 | } 362 | 363 | // There are no terms and the user cant assign terms so let's put some text here so it isn't just blank 364 | else if ( ! cpt_onomies_admin_post_data.can_assign_terms[ $taxonomy ] ) { 365 | 366 | if ( cpt_onomies_admin_post_L10n.no_terms_selected[ $taxonomy ] != '' ) { 367 | $no_terms_selected = cpt_onomies_admin_post_L10n.no_terms_selected[ $taxonomy ]; 368 | } else { 369 | $no_terms_selected = 'There are no terms selected.'; 370 | } 371 | 372 | $tag_checklist.append( '' + $no_terms_selected + ' ' ); 373 | 374 | } 375 | 376 | }, 377 | error: function() { 378 | 379 | // Make sure it gets removed no matter what 380 | $tag_checklist.removeClass( 'loading' ); 381 | 382 | }, 383 | complete: function() { 384 | 385 | // Make sure it gets removed no matter what 386 | $tag_checklist.removeClass( 'loading' ); 387 | 388 | } 389 | }); 390 | 391 | }); 392 | 393 | }); 394 | 395 | // Function invoked by tag checklist 396 | jQuery.fn.custom_post_type_onomies_tag_checklist_add_tag_term = function( $taxonomy, $term, $term_id, $term_parent ) { 397 | 398 | // Assign checklist 399 | var $tag_checklist = jQuery( this ); 400 | 401 | // If not, then this term is already selected/added 402 | if ( jQuery.inArray( $term_id, $tag_checklist.data( 'selected_term_ids' ) ) < 0 ) { 403 | 404 | // Add this term id to selected term ids 405 | $tag_checklist.data( 'selected_term_ids' ).push( $term_id ); 406 | 407 | // Create tag 408 | var $tag = jQuery( '' ); 409 | 410 | // Add field info 411 | $tag.append( '' ); 412 | 413 | // If the user has permission to assign terms 414 | var $tag_delete = null; 415 | if ( cpt_onomies_admin_post_data.can_assign_terms[ $taxonomy ] ) { 416 | 417 | // Add delete button 418 | $tag_delete = jQuery( 'X' ); 419 | $tag.append( $tag_delete ); 420 | 421 | // Assign tag delete event 422 | $tag.find( '.delbutton' ).click( function() { 423 | var $parent_tag = jQuery( this ).closest( 'span.tag' ); 424 | 425 | // Remove from data 426 | $tag_checklist.data( 'selected_term_ids' ).splice( jQuery.inArray( $parent_tag.find( 'input.term_id' ).val(), $tag_checklist.data( 'selected_term_ids' ) ), 1 ); 427 | 428 | // Remove tag 429 | $parent_tag.remove(); 430 | 431 | // Remove the error message 432 | jQuery( '#cpt-onomies-add-tag-error-message-' + $taxonomy ).remove(); 433 | 434 | }); 435 | 436 | } 437 | 438 | // Add term 439 | var $tag_term = jQuery( '' + $term + '' ); 440 | 441 | // Add parent 442 | if ( $term_parent != '' && $term_parent != null && $term_parent != undefined ) { 443 | $tag_term.prepend( '' + $term_parent.replace( ',', '/ ' ) + '/' ); 444 | } 445 | $tag.append( $tag_term ); 446 | 447 | // Add tag 448 | $tag_checklist.append( $tag ); 449 | 450 | // Make sure tag fits 451 | var $tag_elements_width = $tag_term.width(); 452 | var $tag_delete_width = 0; 453 | if ( $tag_delete ) { 454 | $tag_delete_width = $tag_delete.width() + parseInt( $tag_delete.css( 'margin-right' ) ); 455 | $tag_elements_width += $tag_delete_width; 456 | } 457 | 458 | /** 459 | * If term is too big, adjust term width. 460 | * 461 | * 5 is for a little breathing room. 462 | */ 463 | if ( $tag_elements_width > ( $tag.width() - 5 ) ) { 464 | $tag_term.css({ 'width': ( $tag.width() - $tag_delete_width - 5 ) + 'px' }); 465 | } 466 | 467 | /** 468 | * If the term is STILL too long, 469 | * i.e. one word and very long, 470 | * then break the word-wrap. 471 | * 472 | * 5 is for a little breathing room. 473 | */ 474 | if ( $tag_elements_width > ( $tag.width() - 5 ) ) { 475 | $tag_term.css({ 'width': ( $tag.width() - $tag_delete_width - 5 ) + 'px', 'word-wrap': 'break-word' }); 476 | } 477 | 478 | } 479 | 480 | } -------------------------------------------------------------------------------- /assets/js/jquery.validate.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.13.1 - 10/14/2014 2 | * http://jqueryvalidation.org/ 3 | * Copyright (c) 2014 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.validateDelegate(":submit","click",function(b){c.settings.submitHandler&&(c.submitButton=b.target),a(b.target).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(b.target).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.submit(function(b){function d(){var d,e;return c.settings.submitHandler?(c.submitButton&&(d=a("").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),e=c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),void 0!==e?e:!1):!0}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c;return a(this[0]).is("form")?b=this.validate().form():(b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b})),b},removeAttrs:function(b){var c={},d=this;return a.each(b.split(/\s/),function(a,b){c[b]=d.attr(b),d.removeAttr(b)}),c},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){return!!a.trim(""+a(b).val())},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(a,b){(9!==b.which||""!==this.elementValue(a))&&(a.name in this.submitted||a===this.lastElement)&&this.element(a)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date ( ISO ).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c=a.data(this[0].form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!this.is(e.ignore)&&e[d].call(c,this[0],b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox']","focusin focusout keyup",b).validateDelegate("select, option, [type='radio'], [type='checkbox']","click",b),this.settings.invalidHandler&&a(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c=this.clean(b),d=this.validationTargetFor(c),e=!0;return this.lastElement=d,void 0===d?delete this.invalid[c.name]:(this.prepareElement(d),this.currentElements=a(d),e=this.check(d)!==!1,e?delete this.invalid[d.name]:this.invalid[d.name]=!0),a(b).attr("aria-invalid",!e),this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),e},showErrors:function(b){if(b){a.extend(this.errorMap,b),this.errorList=[];for(var c in b)this.errorList.push({message:b[c],element:this.findByName(c)[0]});this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue").removeAttr("aria-invalid")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled], [readonly]").not(this.settings.ignore).filter(function(){return!this.name&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in c||!b.objectLength(a(this).rules())?!1:(c[this.name]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([]),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d=a(b),e=b.type;return"radio"===e||"checkbox"===e?a("input[name='"+b.name+"']:checked").val():"number"===e&&"undefined"!=typeof b.validity?b.validity.badInput?!1:d.val():(c=d.val(),"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(j){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",j),j}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+"")},formatAndAdd:function(b,c){var d=this.defaultMessage(b,c.method),e=/\$?\{(\d+)\}/g;"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),this.errorList.push({message:d,element:b,method:c.method}),this.errorMap[b.name]=d,this.submitted[b.name]=d},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g=this.errorsFor(b),h=this.idOrName(b),i=a(b).attr("aria-describedby");g.length?(g.removeClass(this.settings.validClass).addClass(this.settings.errorClass),g.html(c)):(g=a("<"+this.settings.errorElement+">").attr("id",h+"-error").addClass(this.settings.errorClass).html(c||""),d=g,this.settings.wrapper&&(d=g.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement(d,a(b)):d.insertAfter(b),g.is("label")?g.attr("for",h):0===g.parents("label[for='"+h+"']").length&&(f=g.attr("id").replace(/(:|\.|\[|\])/g,"\\$1"),i?i.match(new RegExp("\\b"+f+"\\b"))||(i+=" "+f):i=f,a(b).attr("aria-describedby",i),e=this.groups[b.name],e&&a.each(this.groups,function(b,c){c===e&&a("[name='"+b+"']",this.currentForm).attr("aria-describedby",g.attr("id"))}))),!c&&this.settings.success&&(g.text(""),"string"==typeof this.settings.success?g.addClass(this.settings.success):this.settings.success(g,b)),this.toShow=this.toShow.add(g)},errorsFor:function(b){var c=this.idOrName(b),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+d.replace(/\s+/g,", #")),this.errors().filter(e)},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+b+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return this.dependTypes[typeof a]?this.dependTypes[typeof a](a,b):!0},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(a){this.pending[a.name]||(this.pendingRequest++,this.pending[a.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b){return a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),/min|max/.test(c)&&(null===g||/number|range|text/.test(g))&&(d=Number(d)),d||0===d?e[c]=d:g===c&&"range"!==g&&(e[c]=!0);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b);for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),void 0!==d&&(e[c]=d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0!==e.param?e.param:!0:delete b[d]}}),a.each(b,function(d,e){b[d]=a.isFunction(e)?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:a.trim(b).length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},creditcard:function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||d>=e},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||c>=a},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d){if(this.optional(c))return"dependency-mismatch";var e,f,g=this.previousValue(c);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),g.originalMessage=this.settings.messages[c.name].remote,this.settings.messages[c.name].remote=g.message,d="string"==typeof d&&{url:d}||d,g.old===b?g.valid:(g.old=b,e=this,this.startRequest(c),f={},f[c.name]=b,a.ajax(a.extend(!0,{url:d,mode:"abort",port:"validate"+c.name,dataType:"json",data:f,context:e.currentForm,success:function(d){var f,h,i,j=d===!0||"true"===d;e.settings.messages[c.name].remote=g.originalMessage,j?(i=e.formSubmitted,e.prepareElement(c),e.formSubmitted=i,e.successList.push(c),delete e.invalid[c.name],e.showErrors()):(f={},h=d||e.defaultMessage(c,"remote"),f[c.name]=g.message=a.isFunction(h)?h(b):h,e.invalid[c.name]=!0,e.showErrors(f)),g.valid=j,e.stopRequest(c,j)}},d)),"pending")}}}),a.format=function(){throw"$.format has been deprecated. Please use $.validator.format instead."};var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a.extend(a.fn,{validateDelegate:function(b,c,d){return this.bind(c,function(c){var e=a(c.target);return e.is(b)?d.apply(e,arguments):void 0})}})}); -------------------------------------------------------------------------------- /assets/scss/admin-options.scss: -------------------------------------------------------------------------------- 1 | .hide { 2 | display: none!important; 3 | visibility: hidden!important; 4 | } 5 | 6 | .underline { text-decoration: underline!important; } 7 | .not-bold { font-weight: normal; } 8 | 9 | .gray, .gray a { color: gray; } 10 | .red, .red a { color: red; } 11 | .green, .green a { color: green; } 12 | 13 | #message, #setting-error-settings_updated { margin: 11px 0 6px 0; } 14 | 15 | #custom-post-type-onomies { 16 | 17 | .nav-tab-wrapper { 18 | overflow: visible; 19 | margin-bottom: 5px; 20 | line-height: 25px; 21 | 22 | .label { 23 | font-size: 13px; 24 | line-height: 28px; 25 | margin-left: 10px; 26 | } 27 | 28 | // Ensures that the border bottom shows up on inactive tabs 29 | .nav-tab { 30 | border-width: 1px; 31 | } 32 | 33 | .etc { 34 | float: right; 35 | font-size: 12px; 36 | line-height: 30px; 37 | 38 | a { 39 | display: inline-block; 40 | text-decoration: none; 41 | overflow: visible; 42 | position: relative; 43 | padding: 0 0 0 10px; 44 | 45 | &:before { 46 | content: ''; 47 | width: 1px; 48 | height: 10px; 49 | background: #0074a2; 50 | position: absolute; 51 | left: 3px; 52 | top: 50%; 53 | margin-top: -5px; 54 | } 55 | 56 | &:first-child { 57 | padding-left: 0; 58 | 59 | &:before { 60 | display: none; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | #tab-panel-custom_post_type_onomies_help_getting_started h3 { margin-bottom: 5px; } 69 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings h3, 70 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages h3, 71 | #tab-panel-custom_post_type_onomies_help_troubleshooting h3 { margin-bottom: 0; } 72 | 73 | #tab-panel-custom_post_type_onomies_help_getting_started h4, 74 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings h4, 75 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages h4, 76 | #tab-panel-custom_post_type_onomies_help_troubleshooting h4 { 77 | font-size: 1.2em; 78 | line-height: normal; 79 | text-transform: uppercase; 80 | color: #777; 81 | margin-top: 0; 82 | margin-bottom: 0; 83 | } 84 | #tab-panel-custom_post_type_onomies_help_getting_started h5, 85 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings h5, 86 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages h5, 87 | #tab-panel-custom_post_type_onomies_help_troubleshooting h5 { 88 | margin-top: 10px; 89 | margin-bottom: 2px; 90 | font-size: 1.1em; 91 | line-height: normal; 92 | } 93 | #tab-panel-custom_post_type_onomies_help_getting_started p, 94 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings p, 95 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages p, 96 | #tab-panel-custom_post_type_onomies_help_troubleshooting p { 97 | margin-top: 0; 98 | line-height: 1.5em; 99 | } 100 | 101 | #tab-panel-custom_post_type_onomies_help_getting_started pre, 102 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings pre, 103 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages pre, 104 | #tab-panel-custom_post_type_onomies_help_troubleshooting pre { margin-left: 20px; } 105 | 106 | #tab-panel-custom_post_type_onomies_help_getting_started li, 107 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings li, 108 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages li, 109 | #tab-panel-custom_post_type_onomies_help_troubleshooting li { margin: 0 0 0 26px; } 110 | 111 | #tab-panel-custom_post_type_onomies_help_getting_started li li, 112 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings li li, 113 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages li li, 114 | #tab-panel-custom_post_type_onomies_help_troubleshooting li li { margin-left: 0; } 115 | 116 | #tab-panel-custom_post_type_onomies_help_getting_started table, 117 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings table, 118 | #tab-panel-custom_post_type_onomies_help_custom_cpt_onomy_archive_pages table, 119 | #tab-panel-custom_post_type_onomies_help_troubleshooting table { width: 100%; } 120 | 121 | #tab-panel-custom_post_type_onomies_help_managing_editing_your_cpt_settings table.menu_position { 122 | width: 55%; 123 | margin-left: 26px; 124 | } 125 | 126 | // Edit meta boxes 127 | .custom-post-type-onomies-edit-postbox { 128 | padding: 5px 0 1px 0; 129 | } 130 | 131 | // Button meta boxes 132 | .custom-post-type-onomies-button-postbox { 133 | margin: 12px 0 0 0; 134 | } 135 | 136 | // Add new custom post type buttons 137 | .add_new_cpt_onomies_custom_post_type, 138 | #custom-post-type-onomies-save-changes, 139 | #custom-post-type-onomies-save-changes-bottom, 140 | .delete_cpt_onomy_custom_post_type.button { 141 | display: block; 142 | background-color: #0074a2 !important; 143 | width: 100%; 144 | height: auto; 145 | -moz-box-sizing: border-box; 146 | -webkit-box-sizing: border-box; 147 | box-sizing: border-box; 148 | background-repeat: no-repeat; 149 | padding: 8px 12px !important; 150 | border: 0; 151 | margin: 0; 152 | -webkit-border-radius: 5px; 153 | -moz-border-radius: 5px; 154 | border-radius: 5px; 155 | color: #fff !important; 156 | text-align: center; 157 | font-weight: bold; 158 | text-decoration: none; 159 | cursor: pointer; 160 | font-size: 1.1em; 161 | line-height: 1.3em; 162 | box-shadow: none !important; 163 | vertical-align: middle; 164 | } 165 | 166 | .add_new_cpt_onomies_custom_post_type { 167 | background-image: url(../images/add.png); 168 | background-position: 10px center; 169 | padding-left: 30px !important; 170 | text-align: left; 171 | } 172 | 173 | .delete_cpt_onomy_custom_post_type.button { 174 | background-color: #a90329 !important; 175 | } 176 | 177 | .add_new_cpt_onomies_custom_post_type:hover, 178 | #custom-post-type-onomies-save-changes:hover, 179 | #custom-post-type-onomies-save-changes-bottom:hover, 180 | .delete_cpt_onomy_custom_post_type.button:hover { 181 | background-color: #145f82 !important; 182 | color: #fff !important; 183 | } 184 | 185 | .delete_cpt_onomy_custom_post_type.button:hover { 186 | background-color: #81021f !important; 187 | } 188 | 189 | // Button in "Manage Custom Post Types" table 190 | table.manage_custom_post_type_onomies .add_new_cpt_onomies_custom_post_type { 191 | float: left; 192 | width: auto; 193 | } 194 | 195 | // Save changes button at bottom of screen 196 | #custom-post-type-onomies-save-changes-bottom { 197 | margin-top: -5px; 198 | } 199 | 200 | // Key meta box 201 | #custom-post-type-onomies-key-mb { 202 | 203 | p { 204 | margin: 8px 0; 205 | } 206 | 207 | img { 208 | margin: 0 6px 2px 0; 209 | vertical-align: middle; 210 | } 211 | 212 | .rating img { margin-right: 8px; } 213 | 214 | .inactive { color: #333; margin-top: 9px; } 215 | .attention { color: #d54e21; } 216 | .working { color: #457800; } 217 | } 218 | 219 | // Promote meta box 220 | #custom-post-type-onomies-promote-mb { 221 | 222 | p { 223 | margin: 10px 0; 224 | } 225 | 226 | a { 227 | text-decoration: none; 228 | } 229 | 230 | .promote-text { 231 | text-decoration: underline; 232 | } 233 | 234 | .dashicons { 235 | text-decoration: none; 236 | } 237 | 238 | .donate img { 239 | margin: 0 4px 2px 0; 240 | vertical-align: middle; 241 | } 242 | 243 | } 244 | 245 | // Manage meta boxes 246 | .custom-post-type-onomies-manage-postbox p { 247 | margin: 10px 0 7px 0; 248 | } 249 | 250 | table.manage_custom_post_type_onomies { 251 | width: 100%; 252 | height: auto; 253 | background: none; 254 | margin: 0 0 3px 0; 255 | padding: 0; 256 | border: 0; 257 | text-align: left; 258 | } 259 | 260 | table.manage_custom_post_type_onomies .row-actions { 261 | display: block; 262 | visibility: visible; 263 | font-size: 0.8em; 264 | line-height: 1.2em; 265 | font-weight: normal; 266 | padding: 1px 0 3px 0; 267 | } 268 | table.manage_custom_post_type_onomies .row-actions .message { 269 | display: block; 270 | color: #457800; 271 | font-weight: bold; 272 | padding: 3px 0 0 0; 273 | } 274 | table.manage_custom_post_type_onomies .row-actions .message a { 275 | color: #457800; 276 | text-decoration: underline; 277 | } 278 | 279 | table.manage_custom_post_type_onomies th, 280 | table.manage_custom_post_type_onomies td { 281 | width: auto; 282 | height: auto; 283 | margin: 0; 284 | padding: 7px 5px 8px 10px; 285 | border: 0; 286 | border-bottom: 1px solid #ddd; 287 | color: #000; 288 | } 289 | 290 | table.manage_custom_post_type_onomies tr th:last-child, 291 | table.manage_custom_post_type_onomies tr td:last-child { padding-right: 10px; } 292 | 293 | table.manage_custom_post_type_onomies tr:last-child td { border-bottom: 0; } 294 | table.manage_custom_post_type_onomies tr:nth-child(even) td { background: #eee; } 295 | 296 | table.manage_custom_post_type_onomies th { 297 | background: #333; 298 | font-weight: bold; 299 | color: #fff; 300 | font-size: 1em; 301 | line-height: normal; 302 | padding-top: 15px; 303 | padding-bottom: 10px; 304 | border: 0; 305 | } 306 | 307 | table.manage_custom_post_type_onomies .name { width: 12%; } 308 | table.manage_custom_post_type_onomies .public { width: 10%; } 309 | 310 | table.manage_custom_post_type_onomies .registered_custom_post_type_onomy, 311 | table.manage_custom_post_type_onomies .attached_to, 312 | table.manage_custom_post_type_onomies .ability { width: 15%; } 313 | 314 | table.manage_custom_post_type_onomies tr.attention td { 315 | background: #f2ebe6; 316 | border-bottom-color: #e2caba; 317 | } 318 | 319 | table.manage_custom_post_type_onomies tr.attention .row-actions .message, 320 | table.manage_custom_post_type_onomies tr.attention .row-actions .message a { color: #d54e21; } 321 | 322 | table.manage_custom_post_type_onomies .status { width:45px; } 323 | table.manage_custom_post_type_onomies tr td.status { 324 | background-image: url(../images/working.png); 325 | background-position: 12px 9px; 326 | background-repeat: no-repeat; 327 | } 328 | table.manage_custom_post_type_onomies tr.attention td.status { 329 | background-image: url(../images/attention.png); 330 | background-position: 12px 9px; 331 | background-repeat: no-repeat; 332 | } 333 | table.manage_custom_post_type_onomies tr.inactive td.status { 334 | background-image: url(../images/inactive.png); 335 | background-position: 12px 9px; 336 | background-repeat: no-repeat; 337 | } 338 | 339 | table.manage_custom_post_type_onomies td.label { 340 | font-weight: bold; 341 | font-size: 1.2em; 342 | line-height: 1.3em; 343 | } 344 | table.manage_custom_post_type_onomies td.label a { text-decoration: none; } 345 | 346 | table.manage_custom_post_type_onomies td.label .row-actions .submitdelete { color: #BC0B0B; } 347 | 348 | table.manage_custom_post_type_onomies td.name { color: #666; } 349 | 350 | table.manage_custom_post_type_onomies td.registered_custom_post_type_onomy { font-weight: bold; } 351 | table.manage_custom_post_type_onomies td.registered_custom_post_type_onomy.error { color: red; } 352 | table.manage_custom_post_type_onomies td.registered_custom_post_type_onomy.attention { color: #d54e21; } 353 | table.manage_custom_post_type_onomies td.registered_custom_post_type_onomy.working { color: #457800; } 354 | 355 | table.manage_custom_post_type_onomies td.registered_custom_post_type_onomy a { 356 | font-size: 0.95em; 357 | font-weight: normal; 358 | } 359 | 360 | table.manage_custom_post_type_onomies .none { 361 | color: #666; 362 | font-style: italic; 363 | padding-top: 9px; 364 | padding-bottom: 0; 365 | border-bottom: 0; 366 | } 367 | 368 | table.manage_custom_post_type_onomies tr.add td { 369 | background: none !important; 370 | padding-top: 12px; 371 | padding-bottom: 2px; 372 | border: 0; 373 | } 374 | 375 | // Editing meta box 376 | #custom-post-type-onomies-edit-header { 377 | display: block; 378 | background: #333; 379 | color: #fff; 380 | padding: 30px 15px 10px 12px; 381 | margin: 0 0 7px 0; 382 | overflow: hidden; 383 | position: relative; 384 | } 385 | 386 | #custom-post-type-onomies-edit-header .label { 387 | display: block; 388 | font-size: 1.7em; 389 | line-height: normal; 390 | font-weight: bold; 391 | } 392 | #custom-post-type-onomies-edit-header.information .label { 393 | width: 40%; 394 | position: absolute; 395 | left: 12px; 396 | bottom: 10px; 397 | } 398 | 399 | #custom-post-type-onomies-edit-header .information { 400 | display: block; 401 | width: 55%; 402 | float: right; 403 | font-style: italic; 404 | opacity: 0.8; 405 | text-align: right; 406 | } 407 | 408 | #custom-post-type-onomies-edit-message { 409 | display: block; 410 | background-image: url(../images/working.png); 411 | background-position: 13px center; 412 | background-repeat: no-repeat; 413 | background-color: #e6eae1; 414 | min-height: 22px; 415 | padding: 0 15px 0 44px; 416 | margin: 0 0 7px 0; 417 | color: #457800; 418 | border: 1px solid #c7cfbd; 419 | font-weight: bold; 420 | 421 | a { 422 | color: #457800; 423 | } 424 | 425 | &.information, 426 | &.inactive { 427 | background-image: url(../images/inactive.png); 428 | background-color: #ddd; 429 | color: #333; 430 | border-color: #bbb; 431 | 432 | a { 433 | color: #333; 434 | } 435 | } 436 | 437 | &.information { 438 | background-image: url(../images/information.png); 439 | } 440 | 441 | &.attention { 442 | background-image: url(../images/attention.png); 443 | background-color: #f2ebe6; 444 | color: #d54e21; 445 | border-color: #e2caba; 446 | 447 | a { 448 | color: #8a2a0a; 449 | } 450 | } 451 | 452 | p { 453 | margin: 0; 454 | padding: 0 0 12px 0; 455 | line-height: 1.2em; 456 | 457 | &:first-child { 458 | padding-top: 12px; 459 | } 460 | } 461 | 462 | .action.button { 463 | display: inline-block; 464 | background: #457800; 465 | border: 0; 466 | color: #fff; 467 | margin: 0 5px 0 0; 468 | } 469 | 470 | &.attention .action.button { 471 | background: #d54e21; 472 | } 473 | } 474 | 475 | #custom-post-type-onomies-edit-table { 476 | width: 100%; 477 | height: auto; 478 | background: #f2f2f2; 479 | margin: 0 0 7px 0; 480 | padding: 10px 10px 0 10px; 481 | border: 1px solid #ddd; 482 | text-align: left; 483 | 484 | table { 485 | width: 100%; 486 | height: auto; 487 | background: none; 488 | margin: 0; 489 | padding: 0; 490 | border: 0; 491 | } 492 | 493 | td { 494 | width: auto; 495 | height: auto; 496 | background: none; 497 | margin: 0; 498 | padding: 0 0 10px 0; 499 | border: 0; 500 | vertical-align: top; 501 | 502 | &.group { 503 | padding-bottom: 0; 504 | } 505 | } 506 | } 507 | 508 | #custom-post-type-onomies-edit-table table.checkbox td, 509 | #custom-post-type-onomies-edit-table table.radio td { 510 | width: 50%; 511 | padding-bottom: 0; 512 | } 513 | 514 | #custom-post-type-onomies-edit-table td.label { 515 | width: 14%; 516 | font-weight: bold; 517 | font-size: 1.1em; 518 | line-height: normal; 519 | padding-top: 2px; 520 | padding-right: 15px; 521 | 522 | .programmatically { 523 | display: block; 524 | font-style: italic; 525 | font-weight: normal; 526 | line-height: 120%; 527 | } 528 | } 529 | 530 | #custom-post-type-onomies-edit-table table td.label { 531 | width: 16%; 532 | font-size: 1em; 533 | line-height: 1.2em; 534 | color: #000; 535 | padding-top:3px; 536 | } 537 | 538 | #custom-post-type-onomies-edit-table .advanced_message { 539 | display: block; 540 | font-weight: bold; 541 | padding-top: 4px; 542 | padding-bottom: 12px; 543 | line-height: 1.3em; 544 | 545 | a { 546 | font-weight: normal; 547 | } 548 | 549 | .show_advanced { 550 | cursor: pointer; 551 | text-decoration: underline; 552 | color: #0074a2; 553 | } 554 | 555 | .close_advanced { 556 | display: block; 557 | background: url(../images/close_advanced.png) 10px center no-repeat #dbecf9; 558 | text-align: left; 559 | padding: 11px 10px 9px 30px; 560 | color: #0074a2; 561 | font-weight: bold; 562 | cursor: pointer; 563 | border: 1px solid #71abc6; 564 | } 565 | } 566 | 567 | #custom-post-type-onomies-edit-table input[type="text"], 568 | #custom-post-type-onomies-edit-table select, 569 | #custom-post-type-onomies-edit-table textarea { 570 | width: 100%; 571 | margin: 0; 572 | } 573 | 574 | #custom-post-type-onomies-edit-table input[type="text"] { padding: 3px; } 575 | 576 | #custom-post-type-onomies-edit-table input[type="checkbox"], 577 | #custom-post-type-onomies-edit-table input[type="radio"] { 578 | margin-right: 5px; 579 | cursor: pointer; 580 | } 581 | 582 | input#custom-post-type-onomies-custom-post-type-name.inactive { color: #666; } 583 | 584 | #custom-post-type-onomies-edit-table .description { 585 | display: block; 586 | margin: 5px 0; 587 | padding: 0; 588 | font-weight: 300; 589 | 590 | .message { 591 | display: block; 592 | background: #DBECF9; 593 | border: 1px solid #71abc6; 594 | padding: 10px; 595 | color: #000; 596 | font-style: normal; 597 | margin: 4px 0 5px 0; 598 | 599 | a { 600 | color: #0074a2; 601 | } 602 | } 603 | } 604 | 605 | #custom-post-type-onomies-edit-table .dismiss { 606 | position: relative; 607 | 608 | .close { 609 | display: block; 610 | cursor: pointer; 611 | width: 22px; 612 | background: #71abc6; 613 | padding: 4px 0; 614 | position: absolute; 615 | right: -15px; 616 | top: 10px; 617 | font-size: 16px; 618 | line-height: normal; 619 | text-align: center; 620 | color: #000; 621 | text-transform: lowercase; 622 | } 623 | } 624 | 625 | #custom-post-type-onomies-edit-table .reset_property { 626 | font-style: normal; 627 | text-decoration: underline; 628 | cursor: pointer; 629 | color: #0074a2; 630 | } 631 | 632 | // Errors 633 | #custom-post-type-onomies-edit-table input.error, 634 | #custom-post-type-onomies-edit-table select.error { border-color: red; } 635 | 636 | #custom-post-type-onomies-edit-table label.error { 637 | display: block; 638 | padding: 2px 0 0 0; 639 | color: red; 640 | } 641 | 642 | // Thickboxes 643 | table#thickbox-network-sites { 644 | width: 100%; 645 | margin: 15px 0 0 0; 646 | border: 0; 647 | padding: 0; 648 | 649 | th { 650 | background: #333; 651 | padding: 5px 0 3px 5px; 652 | color: #fff; 653 | font-weight: bold; 654 | } 655 | 656 | td { 657 | padding: 5px 0 4px 5px; 658 | 659 | &.blog_id { 660 | width: 80px; 661 | } 662 | } 663 | 664 | tr:nth-child(even) { 665 | 666 | td { 667 | background: #eee; 668 | } 669 | } 670 | } -------------------------------------------------------------------------------- /assets/scss/admin-post.scss: -------------------------------------------------------------------------------- 1 | select.category.cpt_onomies { 2 | width: 100%; 3 | margin-top: 7px; 4 | } 5 | 6 | .cpt_onomies_tags_div input.cpt_onomies_new_tag { 7 | width: 71%; 8 | } 9 | 10 | .cpt_onomies_tags_div .cpt_onomies_add_tag_error_message { 11 | display: block; 12 | background: #FFFFE0; 13 | margin: 5px 0 0 0; 14 | padding: 7px 8px 5px 8px; 15 | border: 1px solid #E6DB55; 16 | -webkit-border-radius: 3px; 17 | -moz-border-radius: 3px; 18 | border-radius: 3px; 19 | cursor: pointer; 20 | color: #333; 21 | line-height: 1.3em; 22 | } 23 | 24 | .cpt_onomies_tags_div .cpt_onomies_add_tag_error_message .close { 25 | color: #888; 26 | text-decoration: underline; 27 | } 28 | 29 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist { 30 | margin: 0!important; 31 | padding: 0!important; 32 | margin-left: 8px!important; 33 | border: 0!important; 34 | } 35 | 36 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist.alone { 37 | margin-top: 10px!important; 38 | margin-left: 2px!important; 39 | } 40 | 41 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist.loading { 42 | min-height: 18px; 43 | background: url('../../../../wp-admin/images/loading.gif') left top no-repeat !important; 44 | } 45 | 46 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist .tag { 47 | display: inline-block!important; 48 | width: 50%!important; 49 | margin: 0!important; 50 | padding: 1px 0 2px 0!important; 51 | border: 0!important; 52 | cursor: default!important; 53 | } 54 | 55 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist .delbutton { 56 | display: inline-block!important; 57 | width: 10px!important; 58 | height: 12px!important; 59 | background: url('../../../../wp-admin/images/xit.gif') 0 2px no-repeat!important; 60 | margin: 0 5px 0 0!important; 61 | padding: 0!important; 62 | border: 0!important; 63 | position: static!important; 64 | line-height: normal!important; 65 | cursor: pointer!important; 66 | text-indent: -9999px!important; 67 | vertical-align: text-top!important; 68 | } 69 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist .delbutton:hover { 70 | background-position: -10px 2px!important; 71 | } 72 | 73 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist .term { 74 | display: inline-block!important; 75 | margin: 0!important; 76 | padding: 0 5px 0 0!important; 77 | border: 0!important; 78 | white-space: normal!important; 79 | font-size: 11px!important; 80 | line-height: 1.4em!important; 81 | vertical-align: text-top!important; 82 | } 83 | 84 | .cpt_onomies_tags_div .cpt_onomies_tag_checklist .term .parent { 85 | color: #888!important; 86 | font-style: italic!important; 87 | line-height: normal!important; 88 | padding: 0 3px 0 0!important; 89 | margin: 0!important; 90 | border: 0!important; 91 | white-space: normal!important; 92 | } 93 | 94 | .ui-autocomplete.cpt_onomies { 95 | background: none!important; 96 | max-width: 255px!important; 97 | border: 0!important; 98 | } 99 | 100 | .ui-autocomplete.cpt_onomies .ui-menu-item { 101 | padding: 0!important; 102 | margin: 3px 0 0 0!important; 103 | color: #fff!important; 104 | line-height: normal!important; 105 | white-space: normal!important; 106 | } 107 | 108 | .ui-autocomplete.cpt_onomies .ui-menu-item .parent { 109 | font-size: 90%!important; 110 | font-style: italic!important; 111 | opacity: 0.8!important; 112 | margin: 0!important; 113 | padding: 0 3px 0 0!important; 114 | border: 0!important; 115 | } 116 | 117 | .ui-autocomplete.cpt_onomies .ui-menu-item a { 118 | display: block!important; 119 | background: #0074a2!important; 120 | padding: 7px 5px!important; 121 | margin: 0!important; 122 | border: 0!important; 123 | -webkit-border-radius: 5px!important; 124 | -moz-border-radius: 5px!important; 125 | border-radius: 5px!important; 126 | color: #fff!important; 127 | cursor: pointer!important; 128 | } 129 | 130 | .ui-autocomplete.cpt_onomies .ui-menu-item a.ui-state-hover, 131 | .ui-autocomplete.cpt_onomies .ui-menu-item a:hover { 132 | background: #d54e21!important; 133 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bamadesigner/cpt-onomies", 3 | "description": "A WordPress plugin that allows you to use custom post types as taxonomies.", 4 | "type": "wordpress-plugin", 5 | "authors": [ 6 | { 7 | "name": "Rachel Carden", 8 | "email": "bamadesigner@gmail.com" 9 | } 10 | ], 11 | "license": "GPL-2.0+", 12 | "require-dev": { 13 | "squizlabs/php_codesniffer": "*", 14 | "wp-coding-standards/wpcs": "*" 15 | }, 16 | "scripts": { 17 | "post-install-cmd": [ 18 | "./vendor/bin/phpcs --config-set bin vendor/bin/phpcs", 19 | "./vendor/bin/phpcs --config-set installed_paths ../../wp-coding-standards/wpcs" 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "828712238082f1d79a6e36bc9d897ada", 8 | "content-hash": "17b3f3a9cfcb5daf0d20b8017a8b36bc", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "squizlabs/php_codesniffer", 13 | "version": "2.6.2", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 17 | "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4edb770cb853def6e60c93abb088ad5ac2010c83", 22 | "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "ext-simplexml": "*", 27 | "ext-tokenizer": "*", 28 | "ext-xmlwriter": "*", 29 | "php": ">=5.1.2" 30 | }, 31 | "require-dev": { 32 | "phpunit/phpunit": "~4.0" 33 | }, 34 | "bin": [ 35 | "scripts/phpcs", 36 | "scripts/phpcbf" 37 | ], 38 | "type": "library", 39 | "extra": { 40 | "branch-alias": { 41 | "dev-master": "2.x-dev" 42 | } 43 | }, 44 | "autoload": { 45 | "classmap": [ 46 | "CodeSniffer.php", 47 | "CodeSniffer/CLI.php", 48 | "CodeSniffer/Exception.php", 49 | "CodeSniffer/File.php", 50 | "CodeSniffer/Fixer.php", 51 | "CodeSniffer/Report.php", 52 | "CodeSniffer/Reporting.php", 53 | "CodeSniffer/Sniff.php", 54 | "CodeSniffer/Tokens.php", 55 | "CodeSniffer/Reports/", 56 | "CodeSniffer/Tokenizers/", 57 | "CodeSniffer/DocGenerators/", 58 | "CodeSniffer/Standards/AbstractPatternSniff.php", 59 | "CodeSniffer/Standards/AbstractScopeSniff.php", 60 | "CodeSniffer/Standards/AbstractVariableSniff.php", 61 | "CodeSniffer/Standards/IncorrectPatternException.php", 62 | "CodeSniffer/Standards/Generic/Sniffs/", 63 | "CodeSniffer/Standards/MySource/Sniffs/", 64 | "CodeSniffer/Standards/PEAR/Sniffs/", 65 | "CodeSniffer/Standards/PSR1/Sniffs/", 66 | "CodeSniffer/Standards/PSR2/Sniffs/", 67 | "CodeSniffer/Standards/Squiz/Sniffs/", 68 | "CodeSniffer/Standards/Zend/Sniffs/" 69 | ] 70 | }, 71 | "notification-url": "https://packagist.org/downloads/", 72 | "license": [ 73 | "BSD-3-Clause" 74 | ], 75 | "authors": [ 76 | { 77 | "name": "Greg Sherwood", 78 | "role": "lead" 79 | } 80 | ], 81 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 82 | "homepage": "http://www.squizlabs.com/php-codesniffer", 83 | "keywords": [ 84 | "phpcs", 85 | "standards" 86 | ], 87 | "time": "2016-07-13 23:29:13" 88 | }, 89 | { 90 | "name": "wp-coding-standards/wpcs", 91 | "version": "0.10.0", 92 | "source": { 93 | "type": "git", 94 | "url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git", 95 | "reference": "b39490465f6fd7375743a395019cd597e12119c9" 96 | }, 97 | "dist": { 98 | "type": "zip", 99 | "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/b39490465f6fd7375743a395019cd597e12119c9", 100 | "reference": "b39490465f6fd7375743a395019cd597e12119c9", 101 | "shasum": "" 102 | }, 103 | "require": { 104 | "squizlabs/php_codesniffer": "^2.6" 105 | }, 106 | "type": "library", 107 | "notification-url": "https://packagist.org/downloads/", 108 | "license": [ 109 | "MIT" 110 | ], 111 | "authors": [ 112 | { 113 | "name": "Contributors", 114 | "homepage": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/graphs/contributors" 115 | } 116 | ], 117 | "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", 118 | "keywords": [ 119 | "phpcs", 120 | "standards", 121 | "wordpress" 122 | ], 123 | "time": "2016-08-29 20:04:47" 124 | } 125 | ], 126 | "aliases": [], 127 | "minimum-stability": "stable", 128 | "stability-flags": [], 129 | "prefer-stable": false, 130 | "prefer-lowest": false, 131 | "platform": [], 132 | "platform-dev": [] 133 | } 134 | -------------------------------------------------------------------------------- /cpt-onomies.php: -------------------------------------------------------------------------------- 1 | is_network_active = is_multisite() && ( $plugins = get_site_option( 'active_sitewide_plugins' ) ) && isset( $plugins[ CPT_ONOMIES_PLUGIN_FILE ] ); 92 | 93 | // Load our text domain. 94 | add_action( 'init', array( $this, 'textdomain' ) ); 95 | 96 | // Runs on install. 97 | register_activation_hook( __FILE__, array( $this, 'install' ) ); 98 | 99 | // Runs when the plugin is upgraded. 100 | add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete' ), 1, 2 ); 101 | 102 | } 103 | 104 | /** 105 | * Method to keep our instance from being cloned. 106 | * 107 | * @since 1.3.5 108 | * @access private 109 | * @return void 110 | */ 111 | private function __clone() {} 112 | 113 | /** 114 | * Method to keep our instance from being unserialized. 115 | * 116 | * @since 1.3.5 117 | * @access private 118 | * @return void 119 | */ 120 | private function __wakeup() {} 121 | 122 | /** 123 | * Runs when the plugin is installed. 124 | * 125 | * @access public 126 | * @since 1.3.5 127 | */ 128 | public function install() { 129 | 130 | /* 131 | * Rewrite rules can be a pain in the ass 132 | * so let's flush them out and start fresh. 133 | */ 134 | flush_rewrite_rules( false ); 135 | 136 | } 137 | 138 | /** 139 | * Runs when the plugin is upgraded. 140 | * 141 | * @access public 142 | * @since 1.3.5 143 | * @param Plugin_Upgrader $upgrader Plugin_Upgrader instance. 144 | * @param array $upgrade_info Array of bulk item update data. 145 | * @type string $action Type of action. Default 'update'. 146 | * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'. 147 | * @type bool $bulk Whether the update process is a bulk update. Default true. 148 | * @type array $packages Array of plugin, theme, or core packages to update. 149 | */ 150 | public function upgrader_process_complete( $upgrader, $upgrade_info ) { 151 | 152 | /* 153 | * For some reason I find myself having to flush my 154 | * rewrite rules whenever I upgrade WordPress so just 155 | * helping everyone out by taking care of this automatically 156 | */ 157 | flush_rewrite_rules( false ); 158 | 159 | } 160 | 161 | /* 162 | * Internationalization FTW. 163 | * Load our textdomain. 164 | * 165 | * @access public 166 | * @since 1.3.5 167 | */ 168 | public function textdomain() { 169 | load_plugin_textdomain( 'cpt-onomies', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); 170 | } 171 | 172 | } 173 | 174 | /* 175 | * Returns the instance of our main CPT_onomies class. 176 | * 177 | * Will come in handy when we need to access the 178 | * class to retrieve data throughout the plugin. 179 | * 180 | * @since 1.3.5 181 | * @access public 182 | * @return CPT_onomies 183 | */ 184 | function cpt_onomies() { 185 | return CPT_onomies::instance(); 186 | } 187 | 188 | // Let's get this show on the road. 189 | cpt_onomies(); 190 | -------------------------------------------------------------------------------- /extend/gravity-forms-custom-post-types.php: -------------------------------------------------------------------------------- 1 | get_field_taxonomy( $field ) ) { 27 | custom_post_type_onomies_gform_post_submission_save_taxonomy_field( $field, $entry, $taxonomy ); 28 | } 29 | } 30 | } 31 | } 32 | add_action( 'gform_post_submission', 'custom_post_type_onomies_gform_post_submission_save_taxonomies', 10, 2 ); 33 | 34 | /** 35 | * Takes taxonomy information from a submitted "Gravity Forms + Custom Post Types" 36 | * form and sets CPT-onomy relationships. 37 | */ 38 | function custom_post_type_onomies_gform_post_submission_save_taxonomy_field( &$field, $entry, $taxonomy ) { 39 | global $cpt_onomies_manager, $cpt_onomy; 40 | 41 | // Make sure the taxonomy is a registered CPT-onomy. 42 | if ( $cpt_onomies_manager->is_registered_cpt_onomy( $taxonomy ) ) { 43 | 44 | if ( array_key_exists( 'type', $field ) && 'checkbox' == $field['type'] ) { 45 | $term_ids = array(); 46 | 47 | foreach ( $field['inputs'] as $input ) { 48 | $term_id = (int) $entry[ (string) $input['id'] ]; 49 | if ( $term_id > 0 ) { 50 | $term_ids[] = $term_id; 51 | } 52 | } 53 | 54 | if ( ! empty( $term_ids ) ) { 55 | $cpt_onomy->wp_set_object_terms( $entry['post_id'], $term_ids, $taxonomy, true ); 56 | } 57 | } elseif ( array_key_exists( 'type', $field ) && 'text' == $field['type'] ) { 58 | 59 | $terms = $entry[ $field['id'] ]; 60 | 61 | if ( ! empty( $terms ) ) { 62 | $cpt_onomy->wp_set_post_terms( $entry['post_id'], $terms, $taxonomy ); 63 | } 64 | } else { 65 | 66 | $term_id = (int) $entry[ $field['id'] ]; 67 | 68 | if ( $term_id > 0 ) { 69 | $cpt_onomy->wp_set_object_terms( $entry['post_id'], $term_id, $taxonomy, true ); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // Require all the things (that we need) 2 | var autoprefixer = require('gulp-autoprefixer'); 3 | var gulp = require('gulp'); 4 | var minify = require('gulp-minify'); 5 | var phpcs = require('gulp-phpcs'); 6 | var rename = require('gulp-rename'); 7 | var sass = require('gulp-sass'); 8 | var sort = require('gulp-sort'); 9 | var watch = require('gulp-watch'); 10 | var wp_pot = require('gulp-wp-pot'); 11 | 12 | // Define the source paths for each file type 13 | var src = { 14 | scss: ['assets/scss/**/*'], 15 | js: ['assets/js/**/*.js','!assets/js/*.min.js'], 16 | php: ['**/*.php','!vendor/**','!node_modules/**'] 17 | }; 18 | 19 | // Define the destination paths for each file type 20 | var dest = { 21 | scss: 'assets/css', 22 | js: 'assets/js' 23 | }; 24 | 25 | // Compile the SASS 26 | gulp.task( 'sass', function() { 27 | gulp.src(src.scss) 28 | .pipe(sass({ 29 | outputStyle: 'compressed' 30 | }) 31 | .on('error', sass.logError)) 32 | .pipe(autoprefixer({ 33 | browsers: ['last 2 versions'], 34 | cascade: false 35 | })) 36 | .pipe(rename({ 37 | suffix: '.min' 38 | })) 39 | .pipe(gulp.dest(dest.scss)); 40 | }); 41 | 42 | // Minify the JS 43 | gulp.task( 'js', function() { 44 | gulp.src(src.js) 45 | .pipe(minify({ 46 | mangle: false, 47 | ext:{ 48 | min:'.min.js' 49 | } 50 | })) 51 | .pipe(gulp.dest(dest.js)) 52 | }); 53 | 54 | // Check our PHP 55 | gulp.task( 'php', function() { 56 | gulp.src(src.php) 57 | .pipe(phpcs({ 58 | bin: 'vendor/bin/phpcs', 59 | standard: 'WordPress-Core' 60 | })) 61 | .pipe(phpcs.reporter('log')); 62 | }); 63 | 64 | // Create the .pot translation file 65 | gulp.task( 'translate', function() { 66 | gulp.src(src.php) 67 | .pipe(sort()) 68 | .pipe(wp_pot({ 69 | domain: 'cpt-onomies', 70 | destFile:'cpt-onomies.pot', 71 | package: 'cpt-onomies', 72 | bugReport: 'https://github.com/bamadesigner/cpt-onomies/issues', 73 | lastTranslator: 'Rachel Carden ', 74 | team: 'Rachel Carden ', 75 | headers: false 76 | })) 77 | .pipe(gulp.dest('languages')); 78 | }); 79 | 80 | // Watch the files 81 | gulp.task( 'watch', function() { 82 | gulp.watch(src.scss,['sass']); 83 | gulp.watch(src.js,['js']); 84 | gulp.watch(src.php,['translate','php']); 85 | }); 86 | 87 | // Test things out 88 | gulp.task( 'test', ['php'] ); 89 | 90 | // Compile our assets 91 | gulp.task( 'compile', ['sass','js'] ); 92 | 93 | // Let's get this party started 94 | gulp.task( 'default', ['compile','translate','test'] ); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cpt-onomies", 3 | "version": "1.3.6", 4 | "description": "A CPT-onomy is a taxonomy built from a custom post type, using the post titles as the taxonomy terms. Create custom post types using the CPT-onomies custom post type manager or use post types created by themes or other plugins.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/bamadesigner/cpt-onomies.git" 8 | }, 9 | "author": "Rachel Carden", 10 | "private": true, 11 | "license": "GPL-2.0+", 12 | "bugs": { 13 | "url": "https://github.com/bamadesigner/cpt-onomies/issues" 14 | }, 15 | "homepage": "https://github.com/bamadesigner/cpt-onomies#readme", 16 | "devDependencies": { 17 | "gulp": "^3.9.1", 18 | "gulp-autoprefixer": "^3.1.1", 19 | "gulp-clean-css": "^2.0.12", 20 | "gulp-phpcs": "^1.1.1", 21 | "gulp-rename": "^1.2.2", 22 | "gulp-sass": "^2.3.2", 23 | "gulp-sort": "^2.0.0", 24 | "gulp-uglify": "^2.0.0", 25 | "gulp-watch": "^4.3.9", 26 | "gulp-wp-pot": "^1.3.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === CPT-onomies: Using Custom Post Types as Taxonomies === 2 | Contributors: bamadesigner 3 | Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=bamadesigner%40gmail%2ecom&lc=US&item_name=Rachel%20Carden%20%28CPT%2donomies%29¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted 4 | Tags: custom post type, custom, post, post type, types, tax, taxonomy, taxonomies, cpt-onomy, cpt-onomies, cptonomies, custom post type taxonomies, custom post type as taxonomy, custom post types as taxonomies, relationships, relate, multisite 5 | Requires at least: 3.1 6 | Tested up to: 4.6.1 7 | Stable tag: 1.3.6 8 | License: GPLv2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | 11 | Use your custom post types as taxonomies. Create powerful relationships between your posts and, therefore, powerful content. 12 | 13 | == Description == 14 | 15 | *CPT-onomies* is a **multisite compatible** WordPress plugin that allows you to create very powerful taxonomies and, therefore, very powerful relationships between your posts. 16 | 17 | CPT-onomies are Custom-Post-Type-powered taxonomies that function just like regular WordPress taxonomies, even allowing you to use core WordPress taxonomy functions, such as [get_terms()](http://codex.wordpress.org/Function_Reference/get_terms "get_terms()") and [wp_get_object_terms()](http://codex.wordpress.org/Function_Reference/wp_get_object_terms "wp_get_object_terms()"). *[Check out the CPT-onomy documentation](http://wpdreamer.com/plugins/cpt-onomies/documentation "CPT-onomy documentation") to see which core WordPress taxonomy functions work and when you'll need to access the plugin's CPT-onomy functions.* 18 | 19 | CPT-onomies includes a custom post type manager, allowing you to create custom post types and register CPT-onomies **without touching one line of code!** 20 | 21 | **If you're running a WordPress multisite network**, you can register your custom post types/CPT-onomies across your entire network OR on a site-by-site selection. All from one screen! 22 | 23 | *If you're already using a plugin, or theme, that creates custom post types, don't worry, CPT-onomies is all-inclusive.* **Any registered custom post type can be used as a CPT-onomy.** 24 | 25 | = What Is A CPT-onomy? = 26 | 27 | A CPT-onomy is a Custom-Post-Type-powered taxonomy that functions just like a regular WordPress taxonomy, using your post titles as your taxonomy terms. "Attach", or register, your CPT-onomy to any post type and create relationships between your posts, just as you would create taxonomy relationships. Need to associate a CPT-onomy term with its post? No problem! **The CPT-onomy term's term ID is the same as the post ID.** 28 | 29 | = Is CPT-onomy An Official WordPress Term? = 30 | 31 | No. It's just a fun word I made up. 32 | 33 | = Need Custom Post Types But Not (Necessarily) CPT-onomies? = 34 | 35 | CPT-onomies offers an extensive, **and multisite compatible**, custom post type manager, allowing you to create and completely customize your custom post types within the admin. 36 | 37 | = Why CPT-onomies? = 38 | 39 | It doesn't take long to figure out that custom post types can be a pretty powerful tool for creating and managing numerous types of content. For example, you might use the custom post types "Movies" and "Actors" to build a movie database but what if you wanted to group your "movies" by its "actors"? You could create a custom "actors" taxonomy but then you would have to manage your list of actors in two places: your "actors" custom post type and your "actors" taxonomy. This can be a pretty big hassle, especially if you have an extensive custom post type. 40 | 41 | **This is where CPT-onomies steps in.** Register your custom post type, 'Actors', as a CPT-onomy and CPT-onomies will build your 'actors' taxonomy for you, using your actors' post titles as the terms. Pretty cool, huh? 42 | 43 | = Using CPT-onomies = 44 | 45 | What's really great about CPT-onomies is that they function just like any other taxonomy, allowing you to use WordPress taxonomy functions, like [get_terms()](http://codex.wordpress.org/Function_Reference/get_terms "get_terms()"), [get_the_terms()](http://codex.wordpress.org/Function_Reference/get_the_terms "get_the_terms()") and [wp_get_object_terms()](http://codex.wordpress.org/Function_Reference/wp_get_object_terms "wp_get_object_terms()"), to access the CPT-onomy information you need. CPT-onomies will also work with tax queries when using [The Loop](http://wpdreamer.com/plugins/cpt-onomies/documentation/The_Loop/ "The WordPress Loop"), help you build [custom CPT-onomy archive pages](http://wpdreamer.com/plugins/cpt-onomies/documentation/custom-archive-pages/ "Custom CPT-onomy Archive Pages"), allow you to [programmatically register your CPT-onomies](http://wpdreamer.com/plugins/cpt-onomies/documentation/register_cpt_onomy/), and includes a tag cloud widget for your sidebar. [Check out the CPT-onomies documentation](http://wpdreamer.com/plugins/cpt-onomies/documentation/ "CPT-onomies Documentation") for more information. 46 | 47 | If you're not sure what a taxonomy is, how to use one, or if it's right for your needs, be sure to do some research. [The WordPress Codex page for taxonomies](http://codex.wordpress.org/Taxonomies) is a great place to start! 48 | 49 | ***Note:** Unfortunately, not every taxonomy function can be used at this time. [Check out the CPT-onomy documentation](http://wpdreamer.com/plugins/cpt-onomies/documentation "CPT-onomy documentation") to see which WordPress taxonomy functions work and when you'll need to access the plugin's CPT-onomy functions.* 50 | 51 | == Installation == 52 | 53 | 1. Upload 'cpt-onomies' to the '/wp-content/plugins/' directory 54 | 1. Activate the plugin through the 'Plugins' menu in WordPress 55 | 1. Go to *Settings > CPT-onomies* 56 | 1. Create a new custom post type or edit an existing custom post type 57 | 1. Register your custom post type as a CPT-onomy by "attaching" it to a post type, under "Register this Custom Post Type as a CPT-onomy" on the edit screen 58 | 1. Use your CPT-onomy just like any other taxonomy (refer to the [CPT-onomy documentation](http://wpdreamer.com/plugins/cpt-onomies/documentation "CPT-onomy documentation") for help) 59 | 60 | == Frequently Asked Questions == 61 | 62 | = Why does CPT-onomies not work with all of the WordPress taxonomy functions? = 63 | 64 | Good question. While CPT-onomies strives to mimic taxonomy functionality as much as possible, CPT-onomies are not stored in the database in the same manner as taxonomies. The simplest answer to "Why not?" is that I believe my current method of *"not duplicating post information to resave as taxonomy information"* is in the best all-around interest of not only my plugin, but also your web site. With that said, I am constantly searching for new ways to "hook" into WordPress to improve CPT-onomy/taxonomy integration and, when impossible, will [continue to provide workarounds](http://wpdreamer.com/plugins/cpt-onomies/documentation/ "CPT-onomies Documentation"). 65 | 66 | = How do I associate a CPT-onomy term with it's matching post? = 67 | 68 | Another good question, with a very simple answer: the term ID. CPT-onomies return the same information as taxonomies, including a term ID. A CPT-onomy term's term ID is the same as its post's post ID. 69 | 70 | = I'm not able to save my custom post type because the page keeps telling me "That post type name already exists." = 71 | 72 | This is a jQuery "bug" that only seems to plague a few. I've noticed that this validation standstill will occur if you have any text printed outside the `` element on your page. If that's not the case, and the problem still lingers after you've upgraded to version 1.1, you can dequeue the validation script by placing the following code in your functions.php file: 73 | 74 | `` 80 | 81 | = When assigning my CPT-onomy terms, I see a checklist but I would like to use the autocomplete box (or a select dropdown). = 82 | 83 | ***As of version 1.3, you can change the format for your meta boxes via the settings page!*** The following filter still works, though, so feel free to use as you please. It will overwrite the settings. 84 | 85 | If you have a hierarchical CPT-onomy, the default selection format is a checklist. But if you would rather use the autocomplete box, or a select dropdown, CPT-onomies allows you to hook into the meta box (via a filter) and overwrite the default selection format. 86 | 87 | Here's an example of the filter. More information, check out the "Help" tab in the CPT-onomies settings or [visit the FAQ ](http://wordpress.org/plugins/cpt-onomies/faq/ "visit the FAQ"). 88 | 89 | `` 115 | 116 | = I added support for "Thumbnail" to my custom post type, but the "Featured Image" box does not show up = 117 | 118 | You also have to add theme support for post thumbnails to your functions.php file: 119 | 120 | `` 121 | 122 | If FAQ didn't cover your problem, refer to the following resources: 123 | 124 | * [CPT-onomies Support Forums](http://wordpress.org/support/plugin/cpt-onomies "CPT-onomies Support Forums") 125 | * [CPT-onomies Documentation](http://wpdreamer.com/plugins/cpt-onomies/documentation "CPT-onomies Documentation") 126 | 127 | == Screenshots == 128 | 129 | 1. CPT-onomies offers an extensive custom post type manager, allowing you to create new custom post types or use custom post types created by themes and other plugins. 130 | 2. CPT-onomies lets you manage and customize your custom post types without touching one line of code. 131 | 3. Create your custom post types to power your CPT-onomy. 132 | 4. Assign your CPT-onomy terms just like any other taxonomy. 133 | 5. The admin allows you to sort and filter your posts by CPT-onomy terms. 134 | 135 | == Changelog == 136 | 137 | = 1.3.6 = 138 | * Fixing memory leak issues. Still have some fixes remaining but wanted to get something out while they're being worked on. 139 | 140 | = 1.3.5 = 141 | * Fixes plugin to work with 4.6.1 142 | * Removed all the of the constants the plugin defined so be sure to remove any dependencies on them 143 | 144 | = 1.3.4 = 145 | * Changed default CPT-onomy labels to match the custom post type labels. 146 | * Added 'custom_post_type_onomies_cpt_onomy_labels' filter which allows users to change the CPT-onomy labels. 147 | * Fixed issue when using an array as your query orderby. 148 | * Fixed issue with CPT-onomies not showing all of the correct results. 149 | * Fixed issue with "other" custom post type settings not displaying their values. 150 | * Fixed issue with get_adjacent_post() that was causing issue with next_post_link() and previous_post_link(). 151 | * Added 'admin_column_title' CPT-onomy setting. 152 | * Added 'custom_post_type_onomies_cpt_onomy_admin_column_title' filter which allows users to change the CPT-onomy admin column title. 153 | * Added 'name_admin_bar' custom post type label setting. 154 | * Added 'delete_with_user' custom post type setting. 155 | * Added warning messages for when CPT-onomy terms might be conflicting with taxonomy terms. 156 | * Added action button to delete conflicting taxonomy terms. 157 | * Changed CPT-onomy capability prefixes to include ‘cpt_onomy_’ to help decrease compatibility issues with regular taxonomies. 158 | 159 | = 1.3.3 = 160 | * Fixed bug that was causing issues for multiple tax queries. 161 | * Optimized queries to help with memory problems. 162 | * Fixed PHP Parse error in cpt-onomy.php file for those who are running PHP < 5.3.0. 163 | 164 | = 1.3.2 = 165 | * Fixed a few WordPress 4.1 bugs. 166 | * Brought register_cpt_onomy() outside the manager class for ease of use. 167 | * You can now attach CPT-onomies to media. 168 | * Added hook to flush rewrite rules whenever settings are changed and an upgrade is run. 169 | * Added 'Show In Admin Bar' setting to custom post type registration. 170 | * Added 'Meta Box Title' property to CPT-onomy settings, to allow you to customize the title of your CPT-onomy meta boxes. 171 | * Added 'custom_post_type_onomies_meta_box_title' filter which allows users to change the meta box title. 172 | * Fixed a bug with admin drop down filters not tied to 'show_admin_column' setting. 173 | * Removed CPT_ONOMIES_URL constant and replaced with plugins_url(). 174 | * Updated jQuery Validate script to version 1.13.1. 175 | * Added functionality so when using autocomplete to assign CPT-onomies and term doesn't exist, clicking "Add the term" auto-populates the post title for the new term. 176 | * Reinstated the ability to make the CPT-onomy admin columns sortable. Disable the columns from being sortable by returning false to the 'custom_post_type_onomies_add_cpt_onomy_admin_sortable_column' filter. 177 | * Added ability to order posts queries by a CPT-onomy. 178 | * Changed enqueueing of scripts and styles to use plugins_url() and made sure no versions were used. 179 | * Fixed bug that was causing memory problems for those with a lot of posts. 180 | * Added/fixed rewrite rules for pagination and feeds. 181 | 182 | = 1.3.1 = 183 | * Documentation has moved to wpdreamer.com. 184 | * Fixed a bug with WP < 3.5 'show_admin_column' setting not tied to actually showing the column. 185 | * Fixed Bulk and Quick Edit to work with WP >= 3.5 register_taxonomy() 'show_admin_column' columns. 186 | * Added 'cpt_onomy_created_object_term_relationship' action, allowing users to run code when relationships are created. 187 | * Added 'cpt_onomy_deleted_object_term_relationship' action, allowing users to run code when relationships are deleted. 188 | * Tweaked 'supports' setting to prevent default (title and editor) behavior if no 'supports' are selected. Must have WP 3.5 or greater. 189 | * Fixed the "Redefining already defined constructor" issue for PHP5. 190 | * Edited CPTonomy_Walker_Terms_Checklist::start_el() to match Walker::start_el() and align with strict standards. 191 | * Removed all instances of default function parameter values in Javascript. 192 | * Fixed issue with wp_set_object_terms() not working with CRON. 193 | 194 | = 1.3 = 195 | * Added multisite custom post type manager. 196 | * Added setting to assign the meta box format, i.e. autocomplete, checklist or dropdown. 197 | * Added "Show Admin Column" to the CPT-onomy settings. 198 | * Deprecated the ability to make the CPT-onomy admin columns sortable in order to align with new, default WP taxonomy admin column functionality. 199 | * Deprecated the 'custom_post_type_onomies_add_cpt_onomy_admin_sortable_column' filter. 200 | * Added support for the "Gravity Forms + Custom Post Types" plugin. 201 | * Added the ability to only include/assign specific terms by passing term IDs to a filter. See documentation for more information. 202 | * Added wp_set_post_terms() to the CPT-onomy class. 203 | 204 | = 1.2.1 = 205 | * Cleaned up/fixed a bug with $cpt_onomy->wp_set_object_terms(). 206 | * Fixed a bug when assigning terms to CPTs with long names. 207 | * Fixed a bug when excluding terms from being assigned to new posts via checklist. 208 | * Fixed bug that sometimes caused fatal error during activation. 209 | * Added the exclude terms filter to the bulk and quick edit. 210 | 211 | = 1.2 = 212 | * Minor bug fixes. 213 | * Custom archive pages can be created pretty easily. See documentation for more information. 214 | * Non-public custom post types can now be used as CPT-onomies. 215 | * Added the ability to customize settings by removing options and setting default property values using various filters. See documentation for more information. 216 | * Added the ability to exclude terms from being assigned by passing term IDs to filter. See documentation for more information. 217 | * Added the ability to remove assign CPT-onomy terms meta box from edit screen via filter. See documentation for more information. 218 | * Added the ability to remove CPT-onomy dropdown filter from admin manage custom post type screen via filter. See documentation for more information. 219 | * Added the ability to remove CPT-onomy column (and/or it's sortability) from admin manage custom post type screen via filter. See documentation for more information. 220 | * Fixed a bug with the capability type setting. *BE SURE TO RE-SAVE YOUR SETTINGS IF YOU USE THIS PROPERTY.* 221 | * Fixed a bug with the 'read_private_posts' CPT capability. *BE SURE TO RE-SAVE YOUR SETTINGS IF YOU USE THIS PROPERTY.* 222 | * Changed cpt_onomy.php filename to cpt-onomy.php to match cpt-onomies.php. I'm not sure why I gave it an underscore to begin with. 223 | * Added the ability to set CPT-onomy term description using 'term_description' or '{$taxonomy}_description' filter'. 224 | 225 | = 1.1.1 = 226 | * Fixed bug with autocomplete box. 227 | * Fixed bug when editing "other" custom post types. 228 | * Fixed bug with custom CPT-onomy archive slug. 229 | 230 | = 1.1 = 231 | * Added support to programmatically register CPT-onomies. 232 | * Added support for autocomplete and dropdown CPT-onomy term selection. 233 | * Added support to customize the CPT-onomy archive page slug. 234 | * Added support to change term link in tag cloud widget. 235 | * Added support to exclude term ids from wp_get_object_terms(). 236 | * Added get_term_ancestors() to the CPT-onomy class. 237 | * Added support for Internationalization. 238 | * Tweaked the UI. 239 | * Fixed a few bugs. 240 | 241 | = 1.0.3 = 242 | * **DO NOT UPDATE IF YOU ARE NOT USING WORDPRESS 3.1 OR NEWER!!** If you're using a version older than 3.1., and having issues, download CPT-onomies 1.0.2. for bug fixes. 243 | * Added support for Bulk Edit and Quick Edit. 244 | * Added the ability to sort and filter by CPT-onomy on the admin "Edit Posts" screen. 245 | * Fixed a bug where tax queries wouldn't work with CPT-onomies AND taxonomies. 246 | * Fixed a bug with wp_get_object_terms() not working for multiple object IDs. 247 | * Fixed a bug with custom 'Has Archive' slugs not registering correctly. 248 | * Added backwards compatability/fixed bug for adding the help tab prior to WordPress version 3.3. 249 | 250 | = 1.0.2 = 251 | * Fixed a few bugs with the "Restrict User's Capability to Assign Term Relationships" feature. 252 | * The WordPress function, wp_count_terms(), now works with CPT-onomies and doesn't require the CPT-onomy class. 253 | * Added get_objects_in_term() to the CPT-onomy class. 254 | * Added previous_post_link(), next_post_link(), adjacent_post_link(), prev_post_rel_link(), next_post_rel_link(), get_adjacent_post_rel_link() and get_adjacent_post() to the CPT-onomy class with the ability to designate "in the same CPT-onomy". 255 | * Added support for tax queries when using The Loop. 256 | 257 | = 1.0.1 = 258 | * Fixed bug that didn't delete relationships when CPT-onomy "term" is deleted. 259 | 260 | = 1.0 = 261 | * Plugin launch! 262 | 263 | == Upgrade Notice == 264 | 265 | = 1.3.6 = 266 | * Fixing memory leak issues. Still have some fixes remaining but wanted to get something out while they're being worked on. 267 | 268 | = 1.3.5 = 269 | * Fixes plugin to work with 4.6.1 270 | * Removed all the of the constants the plugin defined so be sure to remove any dependencies on them 271 | 272 | = 1.3.4 = 273 | * Changed default CPT-onomy labels to match the custom post type labels. 274 | * Added 'custom_post_type_onomies_cpt_onomy_labels' filter which allows users to change the CPT-onomy labels. 275 | * Fixed issue when using an array as your query orderby. 276 | * Fixed issue with CPT-onomies not showing all of the correct results. 277 | * Fixed issue with "other" custom post type settings not displaying their values. 278 | * Fixed issue with get_adjacent_post() that was causing issue with next_post_link() and previous_post_link(). 279 | * Added 'admin_column_title' CPT-onomy setting. 280 | * Added 'custom_post_type_onomies_cpt_onomy_admin_column_title' filter which allows users to change the CPT-onomy admin column title. 281 | * Added 'name_admin_bar' custom post type label setting. 282 | * Added 'delete_with_user' custom post type setting. 283 | * Added warning messages for when CPT-onomy terms might be conflicting with taxonomy terms. 284 | * Added action button to delete conflicting taxonomy terms. 285 | * Changed CPT-onomy capability prefixes to include ‘cpt_onomy_’ to help decrease compatibility issues with regular taxonomies. 286 | 287 | = 1.3.3 = 288 | * Fixed bug that was causing issues for multiple tax queries. 289 | * Optimized queries to help with memory problems. 290 | * Fixed PHP Parse error in cpt-onomy.php file for those who are running PHP < 5.3.0. 291 | 292 | = 1.3.2 = 293 | * Fixed a few WordPress 4.1 bugs. 294 | * Brought register_cpt_onomy() outside the manager class for ease of use. 295 | * You can now attach CPT-onomies to media. 296 | * Added hook to flush rewrite rules whenever settings are changed and an upgrade is run. 297 | * Added 'Show In Admin Bar' setting to custom post type registration. 298 | * Added 'Meta Box Title' property to CPT-onomy settings, to allow you to customize the title of your CPT-onomy meta boxes. 299 | * Added 'custom_post_type_onomies_meta_box_title' filter which allows users to change the meta box title. 300 | * Fixed a bug with admin drop down filters not tied to 'show_admin_column' setting. 301 | * Removed CPT_ONOMIES_URL constant and replaced with plugins_url(). 302 | * Updated jQuery Validate script to version 1.13.1. 303 | * Added functionality so when using autocomplete to assign CPT-onomies and term doesn't exist, clicking "Add the term" auto-populates the post title for the new term. 304 | * Reinstated the ability to make the CPT-onomy admin columns sortable. Disable the columns from being sortable by returning false to the 'custom_post_type_onomies_add_cpt_onomy_admin_sortable_column' filter. 305 | * Added ability to order posts queries by a CPT-onomy. 306 | * Changed enqueueing of scripts and styles to use plugins_url() and made sure no versions were used. 307 | * Fixed bug that was causing memory problems for those with a lot of posts. 308 | * Added/fixed rewrite rules for pagination and feeds. 309 | 310 | = 1.3.1 = 311 | * Documentation has moved to wpdreamer.com. 312 | * Fixed a bug with WP < 3.5 'show_admin_column' setting not tied to actually showing the column. 313 | * Fixed Bulk and Quick Edit to work with WP >= 3.5 register_taxonomy() 'show_admin_column' columns. 314 | * Added 'cpt_onomy_created_object_term_relationship' action, allowing users to run code when relationships are created. 315 | * Added 'cpt_onomy_deleted_object_term_relationship' action, allowing users to run code when relationships are deleted. 316 | * Tweaked 'supports' setting to prevent default (title and editor) behavior if no 'supports' are selected. Must have WP 3.5 or greater. 317 | * Fixed the "Redefining already defined constructor" issue for PHP5. 318 | * Edited CPTonomy_Walker_Terms_Checklist::start_el() to match Walker::start_el() and align with strict standards. 319 | * Removed all instances of default function parameter values in Javascript. 320 | * Fixed issue with wp_set_object_terms() not working with CRON. 321 | 322 | = 1.3 = 323 | * Added multisite custom post type manager. 324 | * Added setting to assign the meta box format, i.e. autocomplete, checklist or dropdown. 325 | * Added "Show Admin Column" to the CPT-onomy settings. 326 | * Deprecated the ability to make the CPT-onomy admin columns sortable in order to align with new, default WP taxonomy admin column functionality. 327 | * Deprecated the 'custom_post_type_onomies_add_cpt_onomy_admin_sortable_column' filter. 328 | * Added support for the "Gravity Forms + Custom Post Types" plugin. 329 | * Added the ability to only include/assign specific terms by passing term IDs to a filter. See documentation for more information. 330 | * Added wp_set_post_terms() to the CPT-onomy class. 331 | 332 | = 1.2.1 = 333 | * Cleaned up/fixed a bug with $cpt_onomy->wp_set_object_terms(). 334 | * Fixed a bug when assigning terms to CPTs with long names. 335 | * Fixed a bug when excluding terms from being assigned to new posts via checklist. 336 | * Fixed bug that sometimes caused fatal error during activation. 337 | * Added the exclude terms filter to the bulk and quick edit. 338 | 339 | = 1.2 = 340 | * Minor bug fixes. 341 | * Custom archive pages can be created pretty easily. See documentation for more information. 342 | * Non-public custom post types can now be used as CPT-onomies. 343 | * Added the ability to customize settings by removing options and setting default property values using various filters. See documentation for more information. 344 | * Added the ability to exclude terms from being assigned by passing term IDs to filter. See documentation for more information. 345 | * Added the ability to remove assign CPT-onomy terms meta box from edit screen via filter. See documentation for more information. 346 | * Added the ability to remove CPT-onomy dropdown filter from admin manage custom post type screen via filter. See documentation for more information. 347 | * Added the ability to remove CPT-onomy column (and/or it's sortability) from admin manage custom post type screen via filter. See documentation for more information. 348 | * Fixed a bug with the capability type setting. *BE SURE TO RE-SAVE YOUR SETTINGS IF YOU USE THIS PROPERTY.* 349 | * Fixed a bug with the 'read_private_posts' CPT capability. *BE SURE TO RE-SAVE YOUR SETTINGS IF YOU USE THIS PROPERTY.* 350 | * Changed cpt_onomy.php filename to cpt-onomy.php to match cpt-onomies.php. I'm not sure why I gave it an underscore to begin with. 351 | * Added the ability to set CPT-onomy term description using 'term_description' or '{$taxonomy}_description' filter'. 352 | 353 | = 1.1.1 = 354 | * Fixed bug with autocomplete box. 355 | * Fixed bug when editing "other" custom post types. 356 | * Fixed bug with custom CPT-onomy archive slug. 357 | 358 | = 1.1 = 359 | * Added support to programmatically register CPT-onomies. 360 | * Added support for autocomplete and dropdown CPT-onomy term selection. 361 | * Added support to customize the CPT-onomy archive page slug. 362 | * Added support to change term link in tag cloud widget. 363 | * Added support to exclude term ids from wp_get_object_terms(). 364 | * Added get_term_ancestors() to the CPT-onomy class. 365 | * Added support for Internationalization. 366 | * Tweaked the UI. 367 | * Fixed a few bugs. 368 | 369 | = 1.0.3 = 370 | **DO NOT UPDATE IF YOU ARE NOT USING WORDPRESS 3.1 OR NEWER!!** If you're using a version older than 3.1., and having issues, download CPT-onomies 1.0.2. for bug fixes. Added support for Bulk/Quick Edit and Admin Sort/Filter. Fixed a few bugs. 371 | 372 | = 1.0.2 = 373 | * Fixed a few bugs with the "Restrict User's Capability to Assign Term Relationships" feature. 374 | * The WordPress function, wp_count_terms(), now works with CPT-onomies and doesn't require the CPT-onomy class. 375 | * Added get_objects_in_term() to the CPT-onomy class. 376 | * Added previous_post_link(), next_post_link(), adjacent_post_link(), prev_post_rel_link(), next_post_rel_link(), get_adjacent_post_rel_link() and get_adjacent_post() to the CPT-onomy class with the ability to designate "in the same CPT-onomy". 377 | * Added support for tax queries when using The Loop. 378 | 379 | = 1.0.1 = 380 | Fixed bug that didn't delete relationships when CPT-onomy "term" is deleted. -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | get_col( $wpdb->prepare( "SELECT blog_id FROM {$wpdb->blogs} ORDER BY blog_id", null ) ); 12 | foreach ( $blogs as $this_blog_id ) { 13 | 14 | // Set blog id so $wpdb will know which table to tweak. 15 | $wpdb->set_blog_id( $this_blog_id ); 16 | 17 | // Delete site options. 18 | $wpdb->delete( $wpdb->options, array( 'option_name' => 'custom_post_type_onomies_custom_post_types' ) ); 19 | $wpdb->delete( $wpdb->options, array( 'option_name' => 'custom_post_type_onomies_other_custom_post_types' ) ); 20 | 21 | // Delete post meta. 22 | $wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_custom_post_type_onomies_relationship' ) ); 23 | 24 | } 25 | 26 | // Delete network options 27 | delete_site_option( 'custom_post_type_onomies_custom_post_types' ); 28 | 29 | // Delete user options 30 | $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ( 'custom_post_type_onomies_dismiss', 'wp_custom_post_type_onomies_show_edit_tables', 'custom_post_type_onomies_show_edit_tables' )", null ) ); 31 | -------------------------------------------------------------------------------- /widgets.php: -------------------------------------------------------------------------------- 1 | sprintf( __( 'If you are using a custom post type as a taxonomy, a.k.a %s, this will show your most used tags in cloud format.' ), 'cpt-onomies' ), '"CPT-onomy"' ); 27 | parent::__construct( 'cpt_onomy_tag_cloud', sprintf( __( '%s Tag Cloud', 'cpt-onomies' ), 'CPT-onomy' ), $widget_ops ); 28 | } 29 | 30 | /** 31 | * This function creates and prints the widget's HTML for the front-end. 32 | * 33 | * As of 1.1, you are allowed to select whether you want the 34 | * term to link to the archive page or the actual post. 35 | * 36 | * @since 1.0 37 | * @uses $cpt_onomies_manager, $cpt_onomy 38 | * @param array $args - arguments to customize the widget 39 | * @param array $instance - the widget's saved information 40 | */ 41 | function widget( $args, $instance ) { 42 | global $cpt_onomies_manager, $cpt_onomy; 43 | 44 | if ( isset( $instance['taxonomy'] ) ) { 45 | 46 | $current_taxonomy = $instance['taxonomy']; 47 | 48 | if ( $cpt_onomies_manager->is_registered_cpt_onomy( $current_taxonomy ) ) { 49 | 50 | // Get tag cloud. 51 | $tag_cloud = $cpt_onomy->wp_tag_cloud( apply_filters( 'widget_tag_cloud_args', array( 52 | 'taxonomy' => $current_taxonomy, 53 | 'echo' => false, 54 | 'link' => ( isset( $instance['term_link'] ) && 'cpt_post' == $instance['term_link'] ) ? 'cpt_post' : 'view', 55 | ) 56 | )); 57 | 58 | // If empty, and they dont' want to show if empty, then don't show. 59 | if ( $instance['show_if_empty'] || ( ! $instance['show_if_empty'] && ! empty( $tag_cloud ) ) ) { 60 | 61 | if ( ! empty( $instance['title'] ) ) { 62 | $title = $instance['title']; 63 | } else { 64 | $tax = get_taxonomy( $current_taxonomy ); 65 | $title = $tax->labels->name; 66 | } 67 | 68 | $title = apply_filters( 'widget_title', $title, $instance, $this->id_base ); 69 | 70 | echo $args['before_widget']; 71 | 72 | if ( $title ) { 73 | echo $args['before_title'] . $title . $args['after_title']; 74 | } 75 | 76 | echo '
    ' . $tag_cloud . "
    \n"; 77 | 78 | echo $args['after_widget']; 79 | 80 | } 81 | } 82 | } 83 | } 84 | 85 | /** 86 | * This function updates the widget's settings. 87 | * 88 | * @since 1.0 89 | * @param array $new_instance - new settings to overwrite old settings. 90 | * @param array $old_instance - old settings. 91 | * @return array - the updated instance. 92 | */ 93 | function update( $new_instance, $old_instance ) { 94 | $instance['title'] = strip_tags( stripslashes( $new_instance['title'] ) ); 95 | $instance['taxonomy'] = stripslashes( $new_instance['taxonomy'] ); 96 | $instance['show_if_empty'] = stripslashes( $new_instance['show_if_empty'] ); 97 | $instance['term_link'] = stripslashes( $new_instance['term_link'] ); 98 | return $instance; 99 | } 100 | 101 | /** 102 | * This function prints the widget's form in the admin. 103 | * 104 | * As of 1.1, you are allowed to select whether you want the 105 | * term to link to the archive page or the actual post. 106 | * 107 | * @since 1.0 108 | * @uses $cpt_onomies_manager 109 | * @param $instance - widget settings 110 | */ 111 | function form( $instance ) { 112 | global $cpt_onomies_manager; 113 | 114 | $defaults = array( 115 | 'show_if_empty' => 1, 116 | 'term_link' => 'view', 117 | ); 118 | $instance = wp_parse_args( $instance, $defaults ); 119 | $current_taxonomy = ( ! empty( $instance['taxonomy'] ) && $cpt_onomies_manager->is_registered_cpt_onomy( $instance['taxonomy'] ) ) ? $instance['taxonomy'] : null; 120 | 121 | ?> 122 |

    123 |

    124 | 125 |

    126 |

    143 |

    144 |

    148 |

    149 |

    153 |