y[ $hash[ $prop ][1] ] = $value; return; } $perform = "add_prop_{$prop}"; if ( method_exists( $this, $perform ) ) { $this->$perform( $entity, $key, $data ); } } /** * Add logo property to the entity. * * @param array $entity Array of JSON-LD entity. */ private function add_prop_image( &$entity ) { $logo = Helper::get_settings( 'titles.knowledgegraph_logo' ); if ( ! $logo ) { $logo_id = \get_option( 'site_logo' ); $logo = $logo_id ? wp_get_attachment_image_url( $logo_id ) : ''; } if ( ! $logo ) { return; } $entity['logo'] = [ '@type' => 'ImageObject', '@id' => home_url( '/#logo' ), 'url' => $logo, 'contentUrl' => $logo, 'caption' => $this->get_website_name(), ]; $this->add_prop_language( $entity['logo'] ); $attachment = wp_get_attachment_metadata( Helper::get_settings( 'titles.knowledgegraph_logo_id' ), true ); if ( ! $attachment ) { return; } $entity['logo']['width'] = $attachment['width']; $entity['logo']['height'] = $attachment['height']; } /** * Add Language property to the entity. * * @param array $entity Array of JSON-LD entity. */ private function add_prop_language( &$entity ) { $entity['inLanguage'] = $this->do_filter( 'schema/language', get_bloginfo( 'language' ) ); } /** * Add Image property to entity. * * @param array $entity Array of json-ld entity. * @param string $key Entity Key. * @param array $data Schema Data. */ private function add_prop_thumbnail( &$entity, $key, $data ) { if ( ! empty( $data['primaryImage'] ) ) { $entity[ $key ] = [ '@id' => $data['primaryImage']['@id'] ]; } } /** * Add isPartOf property to entity. * * @param array $entity Array of json-ld entity. * @param string $key Entity Key. */ private function add_prop_is_part_of( &$entity, $key ) { $hash = [ 'website' => home_url( '/#website' ), 'webpage' => Paper::get()->get_canonical() . '#webpage', ]; if ( ! empty( $hash[ $key ] ) ) { $entity['isPartOf'] = [ '@id' => $hash[ $key ] ]; } } /** * Add publisher property to entity * * @param array $entity Entity. * @param string $key Entity Key. * @param array $data Schema Data. */ public function add_prop_publisher( &$entity, $key, $data ) { if ( empty( $data['publisher'] ) ) { return; } $entity[ $key ] = [ '@id' => $data['publisher']['@id'] ]; } /** * Add url property to entity. * * @param array $entity Array of JSON-LD entity. */ private function add_prop_url( &$entity ) { if ( $url = Helper::get_settings( 'titles.url' ) ) { // phpcs:ignore $entity['url'] = ! Url::is_relative( $url ) ? $url : 'http://' . $url; } } /** * Add address property to entity. * * @param array $entity Array of JSON-LD entity. */ private function add_prop_address( &$entity ) { if ( $address = Helper::get_settings( 'titles.local_address' ) ) { // phpcs:ignore $entity['address'] = [ '@type' => 'PostalAddress' ] + $address; } } /** * Add aggregateratings to entity. * * @param string $schema Schema to get data for. * @param array $entity Array of JSON-LD entity to attach data to. */ public function add_ratings( $schema, &$entity ) { $rating = Helper::get_post_meta( "snippet_{$schema}_rating" ); // Early Bail! if ( ! $rating ) { return; } $entity['review'] = [ 'author' => [ '@type' => 'Person', 'name' => get_the_author_meta( 'display_name' ), ], 'datePublished' => get_post_time( 'Y-m-d\TH:i:sP', false ), 'dateModified' => get_post_modified_time( 'Y-m-d\TH:i:sP', false ), 'reviewRating' => [ '@type' => 'Rating', 'ratingValue' => $rating, 'bestRating' => Helper::get_post_meta( "snippet_{$schema}_rating_max" ) ? Helper::get_post_meta( "snippet_{$schema}_rating_max" ) : 5, 'worstRating' => Helper::get_post_meta( "snippet_{$schema}_rating_min" ) ? Helper::get_post_meta( "snippet_{$schema}_rating_min" ) : 1, ], ]; } /** * Get website name with a fallback to bloginfo( 'name' ). * * @return string */ public function get_website_name() { return Helper::get_settings( 'titles.website_name', $this->get_organization_name() ); } /** * Get website name with a fallback to bloginfo( 'name' ). * * @return string */ public function get_organization_name() { $name = Helper::get_settings( 'titles.knowledgegraph_name' ); return $name ? $name : get_bloginfo( 'name' ); } /** * Set publisher/provider data for JSON-LD. * * @param array $entity Array of JSON-LD entity. * @param array $organization Organization data. * @param string $type Type data set to. Default: 'publisher'. */ public function set_publisher( &$entity, $organization, $type = 'publisher' ) { $keys = [ '@context', '@type', 'url', 'name', 'logo', 'image', 'contactPoint', 'sameAs' ]; foreach ( $keys as $key ) { if ( ! isset( $organization[ $key ] ) ) { continue; } $entity[ $type ][ $key ] = 'logo' !== $key ? $organization[ $key ] : [ '@type' => 'ImageObject', 'url' => $organization[ $key ], ]; } } /** * Set address for JSON-LD. * * @param string $schema Schema to get data for. * @param array $entity Array of JSON-LD entity to attach data to. */ public function set_address( $schema, &$entity ) { $address = Helper::get_post_meta( "snippet_{$schema}_address" ); // Early Bail! if ( ! is_array( $address ) || empty( $address ) ) { return; } $entity['address'] = [ '@type' => 'PostalAddress' ]; foreach ( $address as $key => $value ) { $entity['address'][ $key ] = $value; } } /** * Set data to entity. * * Loop through post meta value grab data and attache it to the entity. * * @param array $hash Key to get data and Value to save as. * @param array $entity Array of JSON-LD entity to attach data to. */ public function set_data( $hash, &$entity ) { foreach ( $hash as $metakey => $dest ) { $entity[ $dest ] = Helper::get_post_meta( $metakey, $this->post_id ); } } /** * Get post title. * * Retrieves the title in this order. * 1. Custom post meta set in rich snippet * 2. Headline template set in Titles & Meta * * @param int $post_id Post ID to get title for. * * @return string */ public function get_post_title( $post_id = 0 ) { $title = Helper::get_post_meta( 'snippet_name', $post_id ); if ( ! $title && ! empty( $this->post ) ) { $title = Helper::replace_vars( Helper::get_settings( "titles.pt_{$this->post->post_type}_default_snippet_name", '%seo_title%' ), $this->post ); } $title = $title ? $title : Paper::get()->get_title(); return Str::truncate( $title ); } /** * Get post url. * * @param int $post_id Post ID to get URL for. * @return string */ public function get_post_url( $post_id = 0 ) { $url = Helper::get_post_meta( 'snippet_url', $post_id ); return $url ? $url : ( 0 === $post_id ? Paper::get()->get_canonical() : get_the_permalink( $post_id ) ); } /** * Get product description. * * @param object $product Product Object. * @return string */ public function get_product_desc( $product = [] ) { if ( empty( $product ) ) { return; } if ( $description = Helper::get_post_meta( 'description', $product->get_id() ) ) { //phpcs:ignore return $description; } $product_object = get_post( $product->get_id() ); $description = Paper::get_from_options( 'pt_product_description', $product_object, '%excerpt%' ); if ( ! $description ) { $description = $product->get_short_description() ? $product->get_short_description() : $product->get_description(); } $description = $this->do_filter( 'product_description/apply_shortcode', false ) ? do_shortcode( $description ) : WordPress::strip_shortcodes( $description ); return wp_strip_all_tags( $description, true ); } /** * Get product title. * * @param object $product Product Object. * @return string */ public function get_product_title( $product = [] ) { if ( empty( $product ) ) { return ''; } if ( $title = Helper::get_post_meta( 'title', $product->get_id() ) ) { //phpcs:ignore return $title; } $product_object = get_post( $product->get_id() ); $title = Paper::get_from_options( 'pt_product_title', $product_object, '%title% %sep% %sitename%' ); return $title ? $title : $product->get_name(); } /** * Get post parts. */ private function get_parts() { $parts = [ 'title' => $this->get_post_title(), 'url' => $this->get_post_url(), 'canonical' => Paper::get()->get_canonical(), 'modified' => mysql2date( DATE_W3C, $this->post->post_modified, false ), 'published' => mysql2date( DATE_W3C, $this->post->post_date, false ), 'excerpt' => Helper::replace_vars( '%excerpt%', $this->post ), ]; // Description. $desc = Helper::get_post_meta( 'snippet_desc' ); if ( ! $desc ) { $desc = Helper::replace_vars( Helper::get_settings( "titles.pt_{$this->post->post_type}_default_snippet_desc" ), $this->post ); } $parts['desc'] = $desc ? $desc : ( Helper::get_post_meta( 'description' ) ? Helper::get_post_meta( 'description' ) : $parts['excerpt'] ); // Author. $author = Helper::get_post_meta( 'snippet_author' ); $parts['author'] = $author ? $author : get_the_author_meta( 'display_name', $this->post->post_author ); // Modified date cannot be before publish date. if ( strtotime( $this->post->post_modified ) < strtotime( $this->post->post_date ) ) { $parts['modified'] = $parts['published']; } $this->parts = $parts; } /** * Get global social profile URLs, to use in the `sameAs` property. * * @link https://developers.google.com/webmasters/structured-data/customize/social-profiles */ public function get_social_profiles() { $profiles = [ Helper::get_settings( 'titles.social_url_facebook' ) ]; $twitter = Helper::get_settings( 'titles.twitter_author_names' ); if ( $twitter ) { $profiles[] = "https://twitter.com/$twitter"; } $addional_profiles = Helper::get_settings( 'titles.social_additional_profiles' ); if ( ! empty( $addional_profiles ) ) { $profiles = array_merge( $profiles, Arr::from_string( $addional_profiles, "\n" ) ); } return array_values( array_filter( $profiles ) ); } }