PluginProbe
Property Hive / 2.3.0
Property Hive v2.3.0
2.3.0 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 1.4.46 1.4.47 1.4.48 1.4.49 1.4.5 1.4.50 1.4.51 1.4.52 1.4.53 1.4.54 1.4.55 1.4.56 1.4.57 1.4.58 1.4.59 1.4.6 1.4.60 1.4.61 1.4.62 All 260 releases
← All changes | includes/class-ph-post-types.php +66 -5 2.2.62.3.0 View file →
@@ -13,14 +13,52 @@
13 13 * @package PropertyHive/Classes
14 14 * @category Class
15 15 * @author PropertyHive
16 16 */
17 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Legacy public PH_Post_types class; preserve its existing name for plugin and extension compatibility.
17 18 class PH_Post_types {
18 19
20 +
21 + /**
22 + * Keep native CRM screens separate from ordinary WordPress post access.
23 + * Existing post permissions remain required, alongside Property Hive access.
24 + *
25 + * @return array Dedicated primitive capabilities.
26 + */
27 + public static function record_capabilities() {
28 + $capabilities = array();
29 + foreach ( array( 'edit_posts', 'create_posts', 'edit_others_posts', 'edit_private_posts', 'edit_published_posts', 'publish_posts', 'delete_posts', 'delete_others_posts', 'delete_private_posts', 'delete_published_posts', 'read_private_posts' ) as $capability ) {
30 + $capabilities[$capability] = 'propertyhive_' . $capability;
31 + }
32 + return $capabilities;
33 + }
34 +
35 + /**
36 + * Resolve both direct checks and capabilities produced by core's post mapper.
37 + * This preserves custom roles' existing edit/publish/delete restrictions.
38 + *
39 + * @param array $caps Required primitive capabilities.
40 + * @return array Required capabilities.
41 + */
42 + public static function map_record_capabilities( $caps ) {
43 + $mapped = array();
44 + $record_caps = array_flip( self::record_capabilities() );
45 + foreach ( $caps as $capability ) {
46 + if ( isset( $record_caps[$capability] ) ) {
47 + $mapped[] = 'manage_propertyhive';
48 + $mapped[] = 'create_posts' === $record_caps[$capability] ? 'edit_posts' : $record_caps[$capability];
49 + } else {
50 + $mapped[] = $capability;
51 + }
52 + }
53 + return array_values( array_unique( $mapped ) );
54 + }
55 +
19 56 /**
20 57 * Constructor
21 58 */
22 59 public function __construct() {
60 + add_filter( 'map_meta_cap', array( __CLASS__, 'map_record_capabilities' ) );
23 61 add_action( 'init', array( __CLASS__, 'register_taxonomies' ), 5 );
24 62 add_action( 'init', array( __CLASS__, 'register_post_types' ), 5 );
25 63 add_action( 'init', array( __CLASS__, 'register_post_statuses' ), 5 );
26 64
@@ -67,10 +105,10 @@
67 105 'public' => false,
68 106 'exclude_from_search' => true,
69 107 'show_in_admin_all_list' => false,
70 108 'show_in_admin_status_list' => true,
109 + /* translators: %s: Number of archived posts. */
71 110 'label_count' => _n_noop(
72 - /* translators: %s: number of posts in "Archived" status */
73 111 'Archived <span class="count">(%s)</span>',
74 112 'Archived <span class="count">(%s)</span>',
75 113 'propertyhive'
76 114 ),
@@ -136,8 +174,9 @@
136 174 {
137 175 // Find all properties linked to this contact
138 176 $args = array(
139 177 'post_type' => 'property',
178 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Owner search metadata must be refreshed on properties linked through the existing serialized owner IDs; retain the relationship match.
140 179 'meta_query' => array(
141 180 array(
142 181 'key' => '_owner_contact_id',
143 182 'value' => '"' . $post_id . '"',
@@ -517,8 +556,9 @@
517 556 )
518 557 )
519 558 );
520 559
560 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Existing public Property Hive extension hook do_action_after_register_taxonomies; changing the established name would detach installed callbacks.
521 561 do_action( 'do_action_after_register_taxonomies' );
522 562 }
523 563
524 564 /**
@@ -556,8 +596,9 @@
556 596 'description' => __( 'This is where you can add new properties to your site.', 'propertyhive' ),
557 597 'public' => true,
558 598 'show_ui' => true,
559 599 'capability_type' => 'post',
600 + 'capabilities' => self::record_capabilities(),
560 601 'map_meta_cap' => true,
561 602 'publicly_queryable' => true,
562 603 'exclude_from_search' => false,
563 604 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -595,8 +636,9 @@
595 636 'description' => __( 'This is where you can add new contacts to your site.', 'propertyhive' ),
596 637 'public' => false,
597 638 'show_ui' => true,
598 639 'capability_type' => 'post',
640 + 'capabilities' => self::record_capabilities(),
599 641 'map_meta_cap' => true,
600 642 'publicly_queryable' => false,
601 643 'exclude_from_search' => true,
602 644 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -629,8 +671,9 @@
629 671 ),
630 672 'public' => true,
631 673 'show_ui' => false,
632 674 'capability_type' => 'post',
675 + 'capabilities' => self::record_capabilities(),
633 676 'map_meta_cap' => true,
634 677 'publicly_queryable' => false,
635 678 'exclude_from_search' => true,
636 679 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -664,8 +707,9 @@
664 707 ),
665 708 'public' => false,
666 709 'show_ui' => true,
667 710 'capability_type' => 'post',
711 + 'capabilities' => self::record_capabilities(),
668 712 'map_meta_cap' => true,
669 713 'publicly_queryable' => false,
670 714 'exclude_from_search' => true,
671 715 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -699,8 +743,9 @@
699 743 ),
700 744 'public' => false,
701 745 'show_ui' => true,
702 746 'capability_type' => 'post',
747 + 'capabilities' => self::record_capabilities(),
703 748 'map_meta_cap' => true,
704 749 'publicly_queryable' => false,
705 750 'exclude_from_search' => true,
706 751 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -733,8 +778,9 @@
733 778 ),
734 779 'public' => false,
735 780 'show_ui' => true,
736 781 'capability_type' => 'post',
782 + 'capabilities' => self::record_capabilities(),
737 783 'map_meta_cap' => true,
738 784 'publicly_queryable' => false,
739 785 'exclude_from_search' => true,
740 786 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -767,8 +813,9 @@
767 813 ),
768 814 'public' => false,
769 815 'show_ui' => true,
770 816 'capability_type' => 'post',
817 + 'capabilities' => self::record_capabilities(),
771 818 'map_meta_cap' => true,
772 819 'publicly_queryable' => false,
773 820 'exclude_from_search' => true,
774 821 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -801,11 +848,11 @@
801 848 ),
802 849 'public' => false,
803 850 'show_ui' => true,
804 851 'capability_type' => 'post',
805 - 'capabilities' => array(
852 + 'capabilities' => array_merge( self::record_capabilities(), array(
806 853 'create_posts' => false
807 - ),
854 + ) ),
808 855 'map_meta_cap' => true,
809 856 'publicly_queryable' => false,
810 857 'exclude_from_search' => true,
811 858 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -838,8 +885,9 @@
838 885 ),
839 886 'public' => false,
840 887 'show_ui' => true,
841 888 'capability_type' => 'post',
889 + 'capabilities' => self::record_capabilities(),
842 890 'map_meta_cap' => true,
843 891 'publicly_queryable' => false,
844 892 'exclude_from_search' => true,
845 893 'hierarchical' => false, // Hierarchical causes memory issues - WP loads all records!
@@ -880,11 +928,11 @@
880 928 'query_var' => true,
881 929 'supports' => false,
882 930 'show_in_nav_menus' => false,
883 931 'show_in_menu' => false,
884 - 'capabilities' => array(
932 + 'capabilities' => array_merge( self::record_capabilities(), array(
885 933 'create_posts' => 'do_not_allow'
886 - ),
934 + ) ),
887 935 )
888 936 )
889 937 );
890 938 do_action( 'propertyhive_after_register_post_types' );
@@ -925,8 +973,9 @@
925 973 $args = array(
926 974 'post_type' => 'enquiry',
927 975 'nopaging' => true,
928 976 'post_status' => array('publish', 'pending', 'private', 'draft', 'auto-draft', 'future', 'trash'),
977 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Both legacy and current property relationship metadata must match when the explicit enquiry-trash option is enabled.
929 978 'meta_query' => array(
930 979 'relation' => 'OR',
931 980 array(
932 981 'key' => '_property_id',
@@ -985,9 +1034,11 @@
985 1034 'post_type' => 'property',
986 1035 'fields' => 'ids',
987 1036 'suppress_filters' => TRUE,
988 1037 'posts_per_page' => 1,
1038 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Excludes only the property being deleted so its own media reference cannot prevent attachment cleanup.
989 1039 'post__not_in' => array( $post_id ),
1040 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Before deleting an attachment, check all four serialized property media relationships; the query stops at one matching property to preserve shared media.
990 1041 'meta_query' => array(
991 1042 'relation' => 'OR',
992 1043 array(
993 1044 'key' => '_photos',
@@ -1078,8 +1129,9 @@
1078 1129 $args = array(
1079 1130 'post_type' => 'enquiry',
1080 1131 'nopaging' => true,
1081 1132 'post_status' => array('publish', 'pending', 'private', 'draft', 'auto-draft', 'future', 'trash'),
1133 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Both legacy and current property relationship metadata must match when the explicit enquiry-delete option is enabled.
1082 1134 'meta_query' => array(
1083 1135 'relation' => 'OR',
1084 1136 array(
1085 1137 'key' => '_property_id',
@@ -1135,8 +1187,9 @@
1135 1187
1136 1188 $args = array(
1137 1189 'post_type' => 'contact',
1138 1190 'nopaging' => true,
1191 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Remove only contacts linked to the deleted user through their stored user ID.
1139 1192 'meta_query' => array(
1140 1193 array(
1141 1194 'key' => '_user_id',
1142 1195 'value' => (int)$user_id,
@@ -1257,8 +1310,10 @@
1257 1310 $args = array(
1258 1311 'post_type' => 'property',
1259 1312 'fields' => 'ids',
1260 1313 'post_status' => array( 'publish', 'draft'),
1314 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- This maintenance backfill must select records missing the destination metadata; removing the predicate would overwrite existing values.
1315 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Owner search metadata must be refreshed on properties linked through the existing serialized owner IDs; retain the relationship match.
1261 1316 'meta_query' => array(
1262 1317 array(
1263 1318 'key' => '_address_concatenated',
1264 1319 'compare' => 'NOT EXISTS'
@@ -1265,8 +1320,9 @@
1265 1320 )
1266 1321 ),
1267 1322 'nopaging' => true,
1268 1323 'orderby' => 'rand',
1324 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.SuppressFilters_suppress_filters -- Maintenance must cover every language; front-end language filters would omit records from this backfill.
1269 1325 'suppress_filters' => true,
1270 1326 );
1271 1327 $property_query = new WP_Query($args);
1272 1328
@@ -1288,8 +1344,10 @@
1288 1344 $args = array(
1289 1345 'post_type' => 'contact',
1290 1346 'fields' => 'ids',
1291 1347 'post_status' => 'publish',
1348 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- This maintenance backfill must select records missing the destination metadata; removing the predicate would overwrite existing values.
1349 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Owner search metadata must be refreshed on properties linked through the existing serialized owner IDs; retain the relationship match.
1292 1350 'meta_query' => array(
1293 1351 array(
1294 1352 'key' => '_address_concatenated',
1295 1353 'compare' => 'NOT EXISTS'
@@ -1296,8 +1354,9 @@
1296 1354 )
1297 1355 ),
1298 1356 'nopaging' => true,
1299 1357 'orderby' => 'rand',
1358 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.SuppressFilters_suppress_filters -- Maintenance must cover every language; front-end language filters would omit records from this backfill.
1300 1359 'suppress_filters' => true,
1301 1360 );
1302 1361 $contact_query = new WP_Query($args);
1303 1362
@@ -1359,8 +1418,9 @@
1359 1418 'fields' => 'ids',
1360 1419 'post_type' => 'viewing',
1361 1420 'nopaging' => true,
1362 1421 'post_status' => 'publish',
1422 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Recompute related-viewing metadata only for viewings linked to the changed property or applicant; retain existing relationship and status semantics.
1363 1423 'meta_query' => $meta_query,
1364 1424 'orderby' => 'none'
1365 1425 );
1366 1426
@@ -1393,8 +1453,9 @@
1393 1453 'fields' => 'ids',
1394 1454 'post_type' => 'viewing',
1395 1455 'nopaging' => true,
1396 1456 'post_status' => 'publish',
1457 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Recompute related-viewing metadata only for viewings linked to the changed property or applicant; retain existing relationship and status semantics.
1397 1458 'meta_query' => $meta_query,
1398 1459 'orderby' => 'none'
1399 1460 );
1400 1461