PluginProbe
Property Hive / 2.2.3
Property Hive v2.2.3
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
propertyhive / includes / class-ph-yoast-seo.php

class-ph-yoast-seo.php in Property Hive 2.2.3, at includes/class-ph-yoast-seo.php

287 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 /**
8 * Yoast SEO Compatibility
9 *
10 * @class PH_Yoast_SEO
11 * @version 1.0.0
12 * @package PropertyHive/Classes/
13 * @category Class
14 * @author PropertyHive
15 */
16 class PH_Yoast_SEO {
17
18 /** @var PH_Yoast_SEO The single instance of the class */
19 protected static $_instance = null;
20
21 /**
22 * Hook in methods
23 */
24 public static function init() {
25 add_filter( 'wpseo_sitemap_exclude_taxonomy', array( __CLASS__, 'sitemap_exclude_taxonomy' ), 10, 2 );
26 add_filter( 'wpseo_metabox_prio', array( __CLASS__, 'yoast_meta_box_to_bottom') );
27 add_filter( 'manage_edit-property_columns', array( __CLASS__, 'yoast_remove_columns') );
28 add_filter( 'wpseo_exclude_from_sitemap_by_post_ids', array( __CLASS__, 'sitemap_exclude_off_market') );
29
30 add_filter( 'wpseo_schema_webpage_type', array( __CLASS__, 'yoast_schema_webpage_type') );
31 add_filter( 'wpseo_schema_webpage', array( __CLASS__, 'yoast_schema_webpage') );
32 add_filter( 'wpseo_schema_graph', array( __CLASS__, 'yoast_schema_graph'), 20 );
33
34 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
35 }
36
37 public static function enqueue_scripts()
38 {
39 $screen = get_current_screen();
40
41 if ( in_array( $screen->id, array( 'property' ) ) )
42 {
43 wp_enqueue_script( 'propertyhive-yoast', PH()->plugin_url() . '/assets/js/admin/yoast.js', array(), PH_VERSION );
44 }
45 }
46
47 public static function yoast_schema_webpage_type( $type )
48 {
49 global $post;
50
51 if ( isset($post->post_type) && $post->post_type == 'property' )
52 {
53 if ( !is_array($type) )
54 {
55 $type = array($type);
56 }
57 $type[] = 'RealEstateListing';
58 $type = array_filter( array_values( array_unique( $type ) ) );
59 }
60
61 return $type;
62 }
63
64 public static function yoast_schema_webpage( $data )
65 {
66 // Enrich the WebPage piece with RealEstateListing props (datePosted, offers, mainEntity)
67
68 if ( ! is_singular( 'property' ) ) {
69 return $data;
70 }
71
72 $post_id = get_the_ID();
73
74 $property = new PH_Property($post_id);
75
76 $url = get_permalink( $post_id );
77
78 // IDs so everything links together nicely in the graph
79 $residence_id = $url . '#/residence/' . $post_id;
80 $offer_id = $url . '#/offer/' . $post_id;
81
82 // Core listing bits
83 $department = $property->_department;
84
85 $data['datePosted'] = date("Y-m-d\TH:i:s", strtotime($property->_on_market_change_date)) . "+00:00";
86
87 // Attach an Offer (price, currency, availability) that points at the Residence
88 if ( $department == 'residential-sales' || ph_get_custom_department_based_on($department) == 'residential-sales' )
89 {
90 $data['offers'] = [
91 '@type' => 'Offer',
92 '@id' => $offer_id,
93 'price' => $property->_poa != 'yes' ? (float)$property->_price : '',
94 'priceCurrency' => $property->_currency,
95 // Use a schema.org ItemAvailability URL if you have one; default to InStock
96 //'availability' => $availability ?: 'https://schema.org/InStock',
97 'businessFunction' => 'https://purl.org/goodrelations/v1#Sell',
98 'itemOffered' => [ '@id' => $residence_id ],
99 'url' => $url
100 ];
101 }
102 elseif ( $department == 'residential-lettings' || ph_get_custom_department_based_on($department) == 'residential-lettings' )
103 {
104 $data['offers'] = [
105 '@type' => 'Offer',
106 '@id' => $offer_id,
107 'price' => $property->_poa != 'yes' ? (float)$property->_rent : '',
108 'priceCurrency' => $property->_currency,
109 'priceSpecification' => [
110 '@type' => 'UnitPriceSpecification',
111 'price' => $property->_poa != 'yes' ? (float)$property->_rent : '',
112 'priceCurrency' => $property->_currency,
113 'unitText' => $property->_rent_frequency,
114 ],
115 'businessFunction' => 'https://purl.org/goodrelations/v1#LeaseOut',
116 // Use a schema.org ItemAvailability URL if you have one; default to InStock
117 //'availability' => $availability ?: 'https://schema.org/InStock',
118 'itemOffered' => [ '@id' => $residence_id ],
119 'url' => $url
120 ];
121 }
122
123 // Point the WebPage at the main entity (the actual property)
124 $data['mainEntity'] = [ '@id' => $residence_id ];
125
126 return $data;
127 }
128
129 public static function yoast_schema_graph( $graph )
130 {
131 // Append a Residence/House node with all the property specifics
132
133 if ( ! is_singular( 'property' ) ) {
134 return $graph;
135 }
136
137 $post_id = get_the_ID();
138
139 $property = new PH_Property($post_id);
140
141 $url = get_permalink( $post_id );
142
143 $department = $property->_department;
144
145 $residence_id = $url . '#/residence/' . $post_id;
146
147 // Collect property meta
148 $bedrooms = (int)$property->_bedrooms;
149 $bathrooms = (int)$property->_bathrooms;
150 $street = $property->_address_street;
151 $locality = $property->_address_two;
152 $region = $property->_address_three;
153 $postcode = $property->_address_postcode;
154 $country = $property->_address_country;
155 $lat = $property->_latitude;
156 $lng = $property->_longitude;
157
158 $images = array();
159 if ( get_option('propertyhive_images_stored_as', '') == 'urls' )
160 {
161 $photo_urls = $property->_photo_urls;
162 if ( !is_array($photo_urls) ) { $photo_urls = array(); }
163
164 if ( !empty($num_images) )
165 {
166 $photo_urls = array_slice($photo_urls, 0, $num_images);
167 }
168
169 foreach ( $photo_urls as $photo )
170 {
171 $images[] = isset($photo['url']) ? $photo['url'] : '';
172 }
173 }
174 else
175 {
176 $gallery_attachments = $property->get_gallery_attachment_ids();
177
178 if ( !empty($gallery_attachments) )
179 {
180 if ( !empty($num_images) )
181 {
182 $gallery_attachments = array_slice($gallery_attachments, 0, $num_images);
183 }
184
185 foreach ($gallery_attachments as $gallery_attachment)
186 {
187 $images[] = wp_get_attachment_url( $gallery_attachment );
188 }
189 }
190 }
191 $images = array_values( array_unique( array_filter( $images ) ) );
192
193 $types = array( 'Residence' );
194 if ( $department != 'commercial' && ph_get_custom_department_based_on($department) != 'commercial' )
195 {
196 $types[] = 'SingleFamilyResidence';
197 }
198 $residence = [
199 '@type' => $types,
200 '@id' => $residence_id,
201 'url' => $url,
202 'name' => get_the_title( $post_id ),
203 ];
204
205 // Address
206 if ( $street || $locality || $region || $postcode || $country ) {
207 $residence['address'] = array_filter( [
208 '@type' => 'PostalAddress',
209 'streetAddress' => $street,
210 'addressLocality' => $locality,
211 'addressRegion' => $region,
212 'postalCode' => $postcode,
213 'addressCountry' => $country,
214 ] );
215 }
216
217 // Geo
218 if ( $lat && $lng ) {
219 $residence['geo'] = [
220 '@type' => 'GeoCoordinates',
221 'latitude' => (float)$lat,
222 'longitude' => (float)$lng,
223 ];
224 }
225
226 // Rooms
227 if ( $bedrooms && $department != 'commercial' && ph_get_custom_department_based_on($department) != 'commercial' ) { $residence['numberOfBedrooms'] = $bedrooms; }
228 if ( $bathrooms && $department != 'commercial' && ph_get_custom_department_based_on($department) != 'commercial' ) { $residence['numberOfBathroomsTotal'] = $bathrooms; }
229
230 // Photos / primary image
231 if ( $images ) {
232 $residence['image'] = $images;
233 }
234
235 $graph[] = $residence;
236 return $graph;
237 }
238
239 public static function sitemap_exclude_taxonomy( $value, $taxonomy ) {
240 $taxonomy_objects = get_object_taxonomies( 'property', 'objects' );
241 $taxonomies = array();
242
243 if ( !empty($taxonomy_objects) )
244 {
245 foreach ( $taxonomy_objects as $taxonomy_name => $object )
246 {
247 $taxonomies[] = $taxonomy_name;
248 }
249 }
250 if (
251 in_array($taxonomy, $taxonomies)
252 )
253 {
254 return true;
255 }
256 }
257
258 public static function yoast_meta_box_to_bottom() {
259 return 'low';
260 }
261
262 public static function yoast_remove_columns( $columns ) {
263 unset( $columns['wpseo-score'] );
264 unset( $columns['wpseo-score-readability'] );
265 unset( $columns['wpseo-title'] );
266 unset( $columns['wpseo-metadesc'] );
267 unset( $columns['wpseo-focuskw'] );
268 return $columns;
269 }
270
271 public static function sitemap_exclude_off_market() {
272 return get_posts(array(
273 'fields' => 'ids',
274 'posts_per_page' => -1,
275 'post_type' => 'property',
276 'meta_query' => array(
277 array(
278 'key' => '_on_market',
279 'value' => '',
280 )
281 )
282 ));
283 }
284
285 }
286
287 PH_Yoast_SEO::init();