diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6e90591877..8b72e18ebb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -135,8 +135,11 @@ jobs: ACF_PRO_KEY: ${{ secrets.ACF_PRO_KEY }} ACF_PRO_ENABLED: ${{ matrix.acf-pro-enabled }} WORDLIFT_API_URL: ${{ secrets.WORDLIFT_API_URL }} + YOUTUBE_DATA_API_KEY: ${{ secrets.YOUTUBE_DATA_API_KEY }} + VIMEO_API_KEY: ${{ secrets.VIMEO_API_KEY }} WORDLIFT_KEY: ${{ secrets.WORDLIFT_KEY }} WL_DATASET_NG: ${{ matrix.dataset-ng }} + services: db: # WP set up uses SET storage_engine=InnoDB; which is removed after MySQL 5.6 @@ -154,7 +157,7 @@ jobs: - name: phpunit run: > docker run --workdir /github/workspace --rm -v "/var/run/docker.sock":"/var/run/docker.sock" \ - -e ACF_PRO_ENABLED -e ACF_PRO_KEY -e WORDLIFT_API_URL -e WORDLIFT_KEY -e WL_DATASET_NG \ + -e ACF_PRO_ENABLED -e YOUTUBE_DATA_API_KEY -e VIMEO_API_KEY -e ACF_PRO_KEY -e WORDLIFT_API_URL -e WORDLIFT_KEY -e WL_DATASET_NG \ -v $GITHUB_WORKSPACE:"/github/workspace" \ --network $(docker network ls --format="{{ .Name }}" --filter "Name=^github_network_") \ ziodave/wordpress-tests:${{ matrix.image }} -c ${{ matrix.phpunit-xml }} --stop-on-error --stop-on-fail diff --git a/package.json b/package.json index 1f42bb0ddc..b0a058971c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "wordlift-plugin", "description": "WordLift brings the power of Artificial Intelligence to organize content. Attract new readers and get their true attention with top notch semantic seo.", "private": true, - "version": "3.32.2", + "version": "3.32.3", "author": "WordLift", "homepage": "https://wordift.io/", "license": "GPL-3.0", diff --git a/src-js/webpack/package.json b/src-js/webpack/package.json index f73775551a..9ac27825c9 100644 --- a/src-js/webpack/package.json +++ b/src-js/webpack/package.json @@ -1,6 +1,6 @@ { "name": "wordlift-plugin", - "version": "3.32.2", + "version": "3.32.3", "description": "WordLift Plugin application for the web site public front-end.", "main": "index.js", "repository": "https://github.com/insideout10/wordlift-plugin", diff --git a/src/admin/class-wordlift-admin-settings-analytics-page.php b/src/admin/class-wordlift-admin-settings-analytics-page.php index a7d927fc62..e7ee3d69a7 100644 --- a/src/admin/class-wordlift-admin-settings-analytics-page.php +++ b/src/admin/class-wordlift-admin-settings-analytics-page.php @@ -57,11 +57,12 @@ class Wordlift_Admin_Settings_Analytics_Page extends Wordlift_Admin_Page { /** * Create a {@link Wordlift_Admin_Settings_Page} instance. * + * @param \Wordlift_Configuration_Service $configuration_service The wordlift configuration service. + * @param \Wordlift_Admin_Input_Element $input_element An input element class to output input boxes in a settings form. + * @param \Wordlift_Admin_Radio_Input_Element $radio_input_element A radio element input class for use in a settings form. + * * @since 3.21.0 * - * @param \Wordlift_Configuration_Service $configuration_service The wordlift configuration service. - * @param \Wordlift_Admin_Input_Element $input_element An input element class to output input boxes in a settings form. - * @param \Wordlift_Admin_Radio_Input_Element $radio_input_element A radio element input class for use in a settings form. */ public function __construct( $configuration_service, $input_element, $radio_input_element ) { @@ -80,8 +81,8 @@ public function __construct( $configuration_service, $input_element, $radio_inpu /** * Get the singleton instance of the Notice service. * - * @since 3.21.0 * @return \Wordlift_Admin_Settings_Page The singleton instance of the settings page service. + * @since 3.21.0 */ public static function get_instance() { @@ -140,8 +141,8 @@ public function get_partial_name() { * Returns the string to use for the tab slug on main admin settings page. * * @method get_admin_page_tab_slug - * @since 3.21.0 * @return string + * @since 3.21.0 */ public function get_admin_page_tab_slug() { return 'analytics'; @@ -151,14 +152,18 @@ public function get_admin_page_tab_slug() { * Adds pages to the tabs menu on the main admin settings page. * * @method add_admin_page_tab + * @param array $tabs an array of tab titles and slugs to use when building a tabbed menu on option pages. + * * @since 3.21.0 - * @param array $tabs an array of tab titles and slugs to use when building a tabbed menu on option pages. */ public function add_admin_page_tab( $tabs ) { - $tabs[] = array( - 'title' => $this->get_menu_title(), - 'slug' => $this->get_admin_page_tab_slug(), - ); + if ( apply_filters( 'wl_feature__enable__analytics', true ) ) { + $tabs[] = array( + 'title' => $this->get_menu_title(), + 'slug' => $this->get_admin_page_tab_slug(), + ); + } + return $tabs; } @@ -250,9 +255,10 @@ public function admin_init() { * TODO: Needs a feedback method to pass back error messages. * * @method validate_entity_uri - * @since 3.21.0 - * @param string $uri a sting representing an entity ID that can be converted to a uri. + * @param string $uri a sting representing an entity ID that can be converted to a uri. + * * @return int + * @since 3.21.0 */ public function validate_entity_uri( $uri ) { // Basic validation is to ensure number is between 1 and 20. @@ -262,6 +268,7 @@ public function validate_entity_uri( $uri ) { // if we are out of range then pass the default value. $uri = $this->configuration_service->get_analytics_entity_uri_dimension(); } + return absint( $uri ); } @@ -271,9 +278,10 @@ public function validate_entity_uri( $uri ) { * TODO: Needs a feedback method to pass back error messages. * * @method validate_entity_type - * @since 3.21.0 - * @param string $type This is an entity type ID in string form - really a number. + * @param string $type This is an entity type ID in string form - really a number. + * * @return int + * @since 3.21.0 */ public function validate_entity_type( $type ) { // Basic validation is to ensure number is between 1 and 20. @@ -283,6 +291,7 @@ public function validate_entity_type( $type ) { // if we are out of range then pass the default value. $type = $this->configuration_service->get_analytics_entity_type_dimension(); } + return absint( $type ); } @@ -292,11 +301,11 @@ public function validate_entity_type( $type ) { * If a new entity is being created for the publisher, create it and set The * publisher setting. * - * @since 3.21.0 - * * @param array $input The configuration settings array. * * @return array The sanitized input array. + * @since 3.21.0 + * */ public function sanitize_callback( $input ) { if ( ! check_admin_referer( 'wl_analytics_settings-options' ) ) { diff --git a/src/admin/class-wordlift-admin-settings-page.php b/src/admin/class-wordlift-admin-settings-page.php index 97a8480ddc..e1b7836bc6 100644 --- a/src/admin/class-wordlift-admin-settings-page.php +++ b/src/admin/class-wordlift-admin-settings-page.php @@ -93,15 +93,16 @@ class Wordlift_Admin_Settings_Page extends Wordlift_Admin_Page { /** * Create a {@link Wordlift_Admin_Settings_Page} instance. * + * @param \Wordlift_Configuration_Service $configuration_service A {@link Wordlift_Configuration_Service} instance. + * @param \Wordlift_Entity_Service $entity_service A {@link Wordlift_Entity_Service} instance. + * @param \Wordlift_Admin_Input_Element $input_element A {@link Wordlift_Admin_Input_Element} element renderer. + * @param \Wordlift_Admin_Language_Select_Element $language_select_element A {@link Wordlift_Admin_Language_Select_Element} element renderer. + * @param \Wordlift_Admin_Country_Select_Element $country_select_element A {@link Wordlift_Admin_Country_Select_Element} element renderer. + * @param \Wordlift_Admin_Publisher_Element $publisher_element A {@link Wordlift_Admin_Publisher_Element} element renderer. + * @param \Wordlift_Admin_Radio_Input_Element $radio_input_element A {@link Wordlift_Admin_Radio_Input_Element} element renderer. + * * @since 3.11.0 * - * @param \Wordlift_Configuration_Service $configuration_service A {@link Wordlift_Configuration_Service} instance. - * @param \Wordlift_Entity_Service $entity_service A {@link Wordlift_Entity_Service} instance. - * @param \Wordlift_Admin_Input_Element $input_element A {@link Wordlift_Admin_Input_Element} element renderer. - * @param \Wordlift_Admin_Language_Select_Element $language_select_element A {@link Wordlift_Admin_Language_Select_Element} element renderer. - * @param \Wordlift_Admin_Country_Select_Element $country_select_element A {@link Wordlift_Admin_Country_Select_Element} element renderer. - * @param \Wordlift_Admin_Publisher_Element $publisher_element A {@link Wordlift_Admin_Publisher_Element} element renderer. - * @param \Wordlift_Admin_Radio_Input_Element $radio_input_element A {@link Wordlift_Admin_Radio_Input_Element} element renderer. */ function __construct( $configuration_service, $entity_service, $input_element, $language_select_element, $country_select_element, $publisher_element, $radio_input_element ) { @@ -116,13 +117,14 @@ function __construct( $configuration_service, $entity_service, $input_element, $ $this->publisher_element = $publisher_element; self::$instance = $this; + } /** * Get the singleton instance of the Notice service. * - * @since 3.14.0 * @return \Wordlift_Admin_Settings_Page The singleton instance of the settings page service. + * @since 3.14.0 */ public static function get_instance() { @@ -200,7 +202,6 @@ public function enqueue_scripts() { * @since 3.11.0 */ function admin_init() { - // Register WordLift's general settings, providing our own sanitize callback // which will also check whether the user filled the WL Publisher form. register_setting( @@ -222,7 +223,7 @@ function admin_init() { 'name' => 'wl_general_settings[' . Wordlift_Configuration_Service::KEY . ']', 'value' => $this->configuration_service->get_key(), 'description' => __( 'Insert the WordLift Key you received via email.', 'wordlift' ) - . ' [' . get_option( 'home' ) . ']', + . ' [' . get_option( 'home' ) . ']', ); // Before we were used to validate the key beforehand, but this means @@ -357,11 +358,11 @@ function admin_init() { * Filter the {@link Wordlift_Admin_Input_Element} in order to add the * `readonly` flag to the `wl-entity-base-path` input. * - * @since 3.17.0 - * * @param array $args An array of {@link Wordlift_Admin_Input_Element} parameters. * * @return array The updated array. + * @since 3.17.0 + * */ public function entity_path_input_element_params( $args ) { @@ -383,11 +384,11 @@ public function entity_path_input_element_params( $args ) { * If a new entity is being created for the publisher, create it and set The * publisher setting. * - * @since 3.11.0 - * * @param array $input The configuration settings array. * * @return array The sanitized input array. + * @since 3.11.0 + * */ function sanitize_callback( $input ) { diff --git a/src/admin/class-wordlift-admin-setup.php b/src/admin/class-wordlift-admin-setup.php index 976a03fcd2..53b4b1c35d 100644 --- a/src/admin/class-wordlift-admin-setup.php +++ b/src/admin/class-wordlift-admin-setup.php @@ -210,7 +210,7 @@ public function hide_notices() { public function admin_menu() { /** * - * @see https://github.com/insideout10/wordlift-plugin/issues/1209 + * @see https://github.com/insideout10/wordlift-plugin/issues/1209 * @since 3.27.7 */ // @todo: find another way to do this, since this is adding an empty space in WP's dashboard menu. @@ -271,7 +271,7 @@ public function save_configuration( $params ) { // `key`, holding WL's key, // `vocabulary`, holding the vocabulary path, // `wl-site-language`, with the language code (e.g. `en`), - // `wl-country-code` with the country code (e.g. `us`), + // `wl-country-code` with the country code (e.g. `us`), // `share-diagnostic`, the user preferences about sharing data with us. // `user_type`, the user type either `personal` or `company`, // `name`, with the `personal` or `company`'s name, diff --git a/src/admin/class-wordlift-admin-term-adapter.php b/src/admin/class-wordlift-admin-term-adapter.php index 737b0d68d3..dd7ddfad2b 100644 --- a/src/admin/class-wordlift-admin-term-adapter.php +++ b/src/admin/class-wordlift-admin-term-adapter.php @@ -78,6 +78,15 @@ public function edit_form_fields( $tag, $taxonomy ) { $values = get_term_meta( $tag->term_id, self::META_KEY ); + /** + * @since 3.31.3 + * @see https://github.com/insideout10/wordlift-plugin/issues/1446 + * This field should be hidden by default + */ + if ( ! $values ) { + return; + } + ?> @@ -101,16 +110,11 @@ public function edit_form_fields( $tag, $taxonomy ) { */ public function add_action( $taxonomy ) { /** - * Filter: wl_feature__enable__taxonomy_term_entity_mapping. - * - * @param bool whether to show the taxonomy term to entity mapping field. - * - * @return bool - * @since 3.27.6 - */ - if ( apply_filters( 'wl_feature__enable__taxonomy_term_entity_mapping', true ) ) { - add_action( "{$taxonomy}_edit_form_fields", array( $this, 'edit_form_fields' ), 10, 2 ); - } + * Filter wl_feature__enable__taxonomy_term_entity_mapping renamed to wl_feature__enable__term-entity. + **/ + + add_action( "{$taxonomy}_edit_form_fields", array( $this, 'edit_form_fields' ), 10, 2 ); + } /** diff --git a/src/includes/class-wordlift-configuration-service.php b/src/includes/class-wordlift-configuration-service.php index 819da8b290..555b6e769f 100644 --- a/src/includes/class-wordlift-configuration-service.php +++ b/src/includes/class-wordlift-configuration-service.php @@ -431,7 +431,6 @@ public function get_package_type() { * */ public function set_package_type( $value ) { - $this->set( 'wl_advanced_settings', self::PACKAGE_TYPE, $value ); } diff --git a/src/includes/class-wordlift-entity-service.php b/src/includes/class-wordlift-entity-service.php index 4adb6fbced..f9697d7f38 100644 --- a/src/includes/class-wordlift-entity-service.php +++ b/src/includes/class-wordlift-entity-service.php @@ -355,14 +355,17 @@ public function get_alternative_labels( $post_id ) { * Retrieve the labels for an entity, i.e. the title + the synonyms. * * @param int $post_id The entity {@link WP_Post} id. + * @param int $object_type The object type {@link Object_Type_Enum} * * @return array An array with the entity title and labels. * @since 3.12.0 - * */ - public function get_labels( $post_id ) { - - return array_merge( (array) get_the_title( $post_id ), $this->get_alternative_labels( $post_id ) ); + public function get_labels( $post_id, $object_type = Object_Type_Enum::POST ) { + if ( $object_type === Object_Type_Enum::POST ) { + return array_merge( (array) get_the_title( $post_id ), $this->get_alternative_labels( $post_id ) ); + } + // Term Reference dont have synonyms yet. + return array(); } /** diff --git a/src/includes/class-wordlift-post-adapter.php b/src/includes/class-wordlift-post-adapter.php index bc101d71c9..1709de3bdd 100644 --- a/src/includes/class-wordlift-post-adapter.php +++ b/src/includes/class-wordlift-post-adapter.php @@ -252,7 +252,7 @@ public function locale() { * @param $post_id int * @param $references int[] */ - public function add_mentions( $post_id, &$references ) { + public function add_references( $post_id, &$references ) { $tags = get_the_tags( $post_id ); if ( $tags && ! is_wp_error( $tags ) ) { diff --git a/src/includes/class-wordlift-post-to-jsonld-converter.php b/src/includes/class-wordlift-post-to-jsonld-converter.php index 50cfa9c56e..02c7095984 100644 --- a/src/includes/class-wordlift-post-to-jsonld-converter.php +++ b/src/includes/class-wordlift-post-to-jsonld-converter.php @@ -175,74 +175,16 @@ public function convert( $post_id, &$references = array(), &$references_infos = } $jsonld['commentCount'] = $comment_count; $jsonld['inLanguage'] = $locale; - $post_adapter->add_mentions( $post_id, $references ); + $post_adapter->add_references( $post_id, $references ); } // Set the publisher. $this->set_publisher( $jsonld ); - // Process the references if any. - if ( 0 < count( $references ) ) { - - // Prepare the `about` and `mentions` array. - $about = $mentions = array(); - - $item = false; - $labels = array(); - - - // If the entity is in the title, then it should be an `about`. - foreach ( $references as $reference ) { - /** - * @var $reference Reference - */ - if ( $reference instanceof Post_Reference ) { - // Get the entity labels. - $labels = $this->entity_service->get_labels( $reference->get_id() ); - // Get the entity URI. - $item = array( - '@id' => $this->entity_service->get_uri( $reference->get_id(), $reference->get_type() ), - ); - } else if ( is_numeric( $reference ) ) { - // compatibility with legacy references using post id. - $labels = array(); - // Get the entity URI. - $item = array( - '@id' => $this->entity_service->get_uri( $reference ), - ); - } - - - $escaped_labels = array_map( function ( $value ) { - return preg_quote( $value, '/' ); - }, $labels ); - - // Check if the labels match any part of the title. - $matches = 1 === preg_match( '/' . implode( '|', $escaped_labels ) . '/', $post->post_title ); - - // Check if we have a valid reference. - if ( $item ) { - // If the title matches, assign the entity to the about, otherwise to the mentions. - if ( $matches ) { - $about[] = $item; - } else { - $mentions[] = $item; - } - } - - - } - - // If we have abouts, assign them to the JSON-LD. - if ( 0 < count( $about ) ) { - $jsonld['about'] = $about; - } + $references = $this->convert_references( $references ); - // If we have mentions, assign them to the JSON-LD. - if ( 0 < count( $mentions ) ) { - $jsonld['mentions'] = $mentions; - } - } + // Process the references if any. + $this->set_mentions_and_about( $references, $post, $jsonld ); // Finally set the author. $jsonld['author'] = $this->get_author( $post->post_author, $references ); @@ -507,4 +449,90 @@ private function get_publisher_logo( $post_id ) { ); } + /** + * @param $references + * @param $post + * @param $jsonld + * + * @return void + * + */ + private function set_mentions_and_about( $references, $post, &$jsonld ) { + + if ( count( $references ) === 0 ) { + return; + } + + // Prepare the `about` and `mentions` array. + $about = $mentions = array(); + + // If the entity is in the title, then it should be an `about`. + foreach ( $references as $reference ) { + + if ( ! $reference instanceof Reference ) { + // This condition should never be reached. + continue; + } + + // Get the entity labels. + $labels = $this->entity_service->get_labels( $reference->get_id(), $reference->get_type() ); + // Get the entity URI. + $item = array( + '@id' => $this->entity_service->get_uri( $reference->get_id(), $reference->get_type() ), + ); + + $escaped_labels = array_map( function ( $value ) { + return preg_quote( $value, '/' ); + }, $labels ); + + + $matches = false; + + // When the title is empty, then we shouldn't yield a match to about section. + if ( array_filter( $escaped_labels ) ) { + // Check if the labels match any part of the title. + $matches = 1 === preg_match( '/' . implode( '|', $escaped_labels ) . '/', $post->post_title ); + } + + // If the title matches, assign the entity to the about, otherwise to the mentions. + if ( $matches ) { + $about[] = $item; + } else { + $mentions[] = $item; + } + } + + // If we have abouts, assign them to the JSON-LD. + if ( 0 < count( $about ) ) { + $jsonld['about'] = $about; + } + + // If we have mentions, assign them to the JSON-LD. + if ( 0 < count( $mentions ) ) { + $jsonld['mentions'] = $mentions; + } + + return $jsonld; + } + + /** + * Convert references to abstract data type if we find any. + * + * @param $references array + * + * @return Reference[] + */ + private function convert_references( $references ) { + return array_map( function ( $reference ) { + // Legacy code may still push numerical references to this + // $references variable, so convert it to post references. + if ( is_numeric( $reference ) ) { + return new Post_Reference( $reference ); + } + + return $reference; + + }, $references ); + } + } diff --git a/src/includes/class-wordlift.php b/src/includes/class-wordlift.php index 0235932e7c..12b13793c3 100644 --- a/src/includes/class-wordlift.php +++ b/src/includes/class-wordlift.php @@ -30,6 +30,7 @@ use Wordlift\Entity\Entity_No_Index_Flag; use Wordlift\Entity\Entity_Rest_Service; use Wordlift\Entity_Type\Entity_Type_Change_Handler; +use Wordlift\Entity_Type\Entity_Type_Setter; use Wordlift\External_Plugin_Hooks\Recipe_Maker\Recipe_Maker_After_Get_Jsonld_Hook; use Wordlift\External_Plugin_Hooks\Recipe_Maker\Recipe_Maker_Jsonld_Hook; use Wordlift\External_Plugin_Hooks\Recipe_Maker\Recipe_Maker_Post_Type_Hook; @@ -773,7 +774,7 @@ public function __construct() { self::$instance = $this; $this->plugin_name = 'wordlift'; - $this->version = '3.32.2'; + $this->version = '3.32.3'; $this->load_dependencies(); $this->set_locale(); $this->define_admin_hooks(); @@ -1311,11 +1312,11 @@ private function load_dependencies() { * @since 3.20.0 */ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-wordlift-term-jsonld-adapter.php'; - $term_jsonld_adapter = new Wordlift_Term_JsonLd_Adapter( $this->entity_uri_service ); - $this->jsonld_service = new Wordlift_Jsonld_Service( $this->entity_service, $this->cached_postid_to_jsonld_converter, $this->jsonld_website_converter, $term_jsonld_adapter ); + $term_jsonld_adapter = new Wordlift_Term_JsonLd_Adapter( $this->entity_uri_service, $this->cached_postid_to_jsonld_converter ); + $this->jsonld_service = new Wordlift_Jsonld_Service( $this->entity_service, $this->cached_postid_to_jsonld_converter, $this->jsonld_website_converter, $term_jsonld_adapter ); - $jsonld_service = new Jsonld_Service( + $jsonld_service = new Jsonld_Service( $this->jsonld_service, $term_jsonld_adapter, new Jsonld_User_Service( $this->user_service ) ); @@ -1552,7 +1553,7 @@ private function load_dependencies() { * The post entity provider has the legacy code which provides the entity * if the object is post {@link \Wordlift\Object_Type_Enum::POST} */ - new Post_Entity_Provider($this->entity_uri_service, + new Post_Entity_Provider( $this->entity_uri_service, $this->entity_type_service, $this->storage_factory->post_images() ); /** * @since 3.32.0 @@ -1662,6 +1663,8 @@ private function load_dependencies() { $this->entity_service, $this->entity_type_service ); + + new Entity_Type_Setter(); } /** @@ -1994,7 +1997,7 @@ private function define_public_hooks() { $this->loader->add_action( 'save_post', $this->entity_type_adapter, 'save_post', 9, 3 ); // Analytics Script Frontend. - if ( $this->configuration_service->is_analytics_enable() ) { + if ( apply_filters( 'wl_feature__enable__analytics', true ) && $this->configuration_service->is_analytics_enable() ) { $this->loader->add_action( 'wp_enqueue_scripts', $this->analytics_connect, 'enqueue_scripts', 10 ); } @@ -2082,10 +2085,10 @@ public function add_wl_enabled_blocks() { $enabled_blocks = array(); /** - * Filter name: wl_feature_enable__product_navigator - * @since 3.30.0 + * Filter name: wl_feature__enable__product-navigator + * @since 3.32.3 */ - if ( apply_filters( 'wl_feature_enable__product-navigator', true ) ) { + if ( apply_filters( 'wl_feature__enable__product-navigator', true ) ) { $enabled_blocks[] = 'wordlift/products-navigator'; } diff --git a/src/public/class-wordlift-term-jsonld-adapter.php b/src/public/class-wordlift-term-jsonld-adapter.php index 5aeb51d8b5..0189f1767e 100644 --- a/src/public/class-wordlift-term-jsonld-adapter.php +++ b/src/public/class-wordlift-term-jsonld-adapter.php @@ -10,6 +10,7 @@ */ use Wordlift\Jsonld\Jsonld_Context_Enum; +use Wordlift\Jsonld\Reference; /** * Define the {@link Wordlift_Term_JsonLd_Adapter} class. @@ -29,20 +30,26 @@ class Wordlift_Term_JsonLd_Adapter { private static $instance; + /** + * @var Wordlift_Post_Converter + */ + private $post_id_to_jsonld_converter; + /** * Wordlift_Term_JsonLd_Adapter constructor. * * @param \Wordlift_Entity_Uri_Service $entity_uri_service The {@link Wordlift_Entity_Uri_Service} instance. - * @param \Wordlift_Jsonld_Service $jsonld_service The {@link Wordlift_Jsonld_Service} instance. + * @param \Wordlift_Post_Converter $post_id_to_jsonld_converter The {@link Wordlift_Post_Converter} instance. * * @since 3.20.0 * */ - public function __construct( $entity_uri_service ) { + public function __construct( $entity_uri_service, $post_id_to_jsonld_converter ) { add_action( 'wp_head', array( $this, 'wp_head' ) ); - $this->entity_uri_service = $entity_uri_service; + $this->entity_uri_service = $entity_uri_service; + $this->post_id_to_jsonld_converter = $post_id_to_jsonld_converter; self::$instance = $this; } @@ -161,7 +168,7 @@ public function get( $id, $context ) { * * @since 3.26.0 */ - $jsonld_array = array(); + $jsonld_array = array(); if ( Jsonld_Context_Enum::PAGE === $context ) { $carousel_data = $this->get_carousel_jsonld( $id ); @@ -177,7 +184,6 @@ public function get( $id, $context ) { 'references' => array() ); - /** * @since 3.26.3 * Filter: wl_term_jsonld_array @@ -185,6 +191,7 @@ public function get( $id, $context ) { * @var $jsonld_array array An array containing jsonld for term and entities. */ $arr = apply_filters( 'wl_term_jsonld_array', $result, $id ); + /** * @since 3.32.0 * Expand the references returned by this filter. @@ -218,11 +225,13 @@ private function get_term_url( $id ) { * @return array */ private function get_entity_jsonld( $term_id, $context ) { - $jsonld_service = Wordlift_Jsonld_Service::get_instance(); + // The `_wl_entity_id` are URIs. $entity_ids = get_term_meta( $term_id, '_wl_entity_id' ); $entity_uri_service = $this->entity_uri_service; + $wordlift_jsonld_service = Wordlift_Jsonld_Service::get_instance(); + $local_entity_ids = array_filter( $entity_ids, function ( $uri ) use ( $entity_uri_service ) { return $entity_uri_service->is_internal( $uri ); } ); @@ -233,11 +242,11 @@ private function get_entity_jsonld( $term_id, $context ) { } $post = $this->entity_uri_service->get_entity( array_shift( $local_entity_ids ) ); - $jsonld = $jsonld_service->get_jsonld( false, $post->ID, $context ); + $entities_jsonld = $wordlift_jsonld_service->get_jsonld( false, $post->ID ); // Reset the `url` to the term page. - $jsonld[0]['url'] = get_term_link( $term_id ); + $entities_jsonld[0]['url'] = get_term_link( $term_id ); - return $jsonld; + return $entities_jsonld; } @@ -247,7 +256,7 @@ private function get_entity_jsonld( $term_id, $context ) { * @return array */ private function expand_references( $references ) { - $jsonld_service = Wordlift_Jsonld_Service::get_instance(); + // @TODO: we are assuming all the references are posts // in this method, since now terms are getting converted to // entities, this might not be true in all cases. @@ -257,11 +266,16 @@ private function expand_references( $references ) { $references_jsonld = array(); // Expand the references. foreach ( $references as $reference ) { - $references_jsonld[] = $jsonld_service->get_jsonld( false, $reference ); + $post_id = $reference; + if ( $reference instanceof Reference ) { + $post_id = $reference->get_id(); + } + $references_jsonld[] = $this->post_id_to_jsonld_converter->convert( $post_id ); } return $references_jsonld; } + } diff --git a/src/readme.txt b/src/readme.txt index 6c63cd75e8..975e04f8de 100644 --- a/src/readme.txt +++ b/src/readme.txt @@ -142,6 +142,14 @@ You can open your datasets to the public, attaching to it a free or a commercial == Changelog == += 3.32.3 (2021-08-02) = + +* Enhancement [#1444](https://github.com/insideout10/wordlift-plugin/issues/1444): Add terms as mentions to the Article +* Enhancement [#1434](https://github.com/insideout10/wordlift-plugin/issues/1434): Restrict entity types by the subscription + +* Fix [#1446](https://github.com/insideout10/wordlift-plugin/issues/1446): Hide entity field on term page by default +* Fix [#1442](https://github.com/insideout10/wordlift-plugin/issues/1442): WordLift Plugin, Automatic Summarization, shortcode stripping + = 3.32.2 (2021-07-23) = * Fix: Videoobject fix embedded videos with jw player diff --git a/src/wordlift.php b/src/wordlift.php index 304edc867e..14ef527621 100644 --- a/src/wordlift.php +++ b/src/wordlift.php @@ -15,7 +15,7 @@ * Plugin Name: WordLift * Plugin URI: https://wordlift.io * Description: WordLift brings the power of AI to organize content, attract new readers and get their attention. To activate the plugin visit our website. - * Version: 3.32.2 + * Version: 3.32.3 * Author: WordLift, Insideout10 * Author URI: https://wordlift.io * License: GPL-2.0+ diff --git a/src/wordlift/entity-type/class-entity-type-setter.php b/src/wordlift/entity-type/class-entity-type-setter.php new file mode 100644 index 0000000000..8fe09f1b20 --- /dev/null +++ b/src/wordlift/entity-type/class-entity-type-setter.php @@ -0,0 +1,201 @@ + + */ + +namespace Wordlift\Entity_Type; + +use Wordlift_Entity_Type_Taxonomy_Service; + +class Entity_Type_Setter { + + + const STARTER_PLAN = 'entity-types-starter'; + + const PROFESSIONAL_PLAN = 'entity-types-professional'; + + const BUSINESS_PLAN = 'entity-types-business'; + + public function __construct() { + add_action( "wl_feature__change__entity-types-starter", array( $this, 'wl_entity_types_feature_changed' ), 10, 3 ); + add_action( "wl_feature__change__entity-types-professional", array( $this, 'wl_entity_types_feature_changed' ), 10, 3 ); + add_action( "wl_feature__change__entity-types-business", array( $this, 'wl_entity_types_feature_changed' ), 10, 3 ); + } + + + public function wl_entity_types_feature_changed( $new_value, $old_value, $feature_slug ) { + + // If the entity types is not set by server, then return early. + if ( ! $new_value ) { + return; + } + + + $entity_types_data = self::get_entity_types_by_feature_flag( $feature_slug ); + + // If we dont have entity types returned, then dont reset the entity types, return early. + if ( ! $entity_types_data ) { + return; + } + // Repopulate the ones returned by package type. + foreach ( $entity_types_data as $entity_type_data ) { + + $schema_label = $entity_type_data['label']; + + $term_exists = get_term_by( 'name', $schema_label, Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME ) instanceof \WP_Term; + + if ( $term_exists ) { + // Dont create term if it already exists. + continue; + } + + + $term_data = wp_insert_term( + $schema_label, + Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, + array( + 'description' => $entity_type_data['description'], + 'slug' => $entity_type_data['slug'] + ) + ); + + $term_id = $term_data['term_id']; + + update_term_meta( $term_id, '_wl_uri', 'http://schema.org/' . $schema_label ); + update_term_meta( $term_id, '_wl_name', $schema_label ); + } + + } + + + public static function get_starter_entity_types() { + return array( + array( + 'label' => 'Person', + 'description' => 'A person (or a music artist).', + 'slug' => 'person' + ), + array( + 'label' => 'Thing', + 'description' => 'A generic thing (something that doesn\'t fit in the previous definitions.', + 'slug' => 'thing' + ), + + array( + 'label' => 'Place', + 'description' => 'A place.', + 'slug' => 'place' + ), + + array( + 'label' => 'CreativeWork', + 'description' => 'A creative work (or a Music Album).', + 'slug' => 'creative-work' + ), + array( + 'label' => 'Organization', + 'description' => 'An organization, including a government or a newspaper.', + 'slug' => 'organization' + ), + + array( + 'label' => 'Article', + 'description' => 'An article, such as a news article or piece of investigative report. Newspapers and magazines have articles of many different types and this is intended to cover them all.', + 'slug' => 'article' + ), + + array( + 'label' => 'WebSite', + 'description' => 'A WebSite is a set of related web pages and other items typically served from a single web domain and accessible via URLs.', + 'slug' => 'web-site' + ), + + array( + 'label' => 'NewsArticle', + 'description' => 'A NewsArticle is an article whose content reports news, or provides background context and supporting materials for understanding the news.', + 'slug' => 'news-article' + ), + + array( + 'label' => 'AboutPage', + 'description' => 'An About page.', + 'slug' => 'about-page' + ), + + array( + 'label' => 'ContactPage', + 'description' => 'A Contact Page.', + 'slug' => 'contact-page' + ) + + ); + } + + + public static function get_professional_entity_types() { + return array( + + array( + 'label' => 'FAQPage', + 'description' => 'A FAQPage is a WebPage presenting one or more "Frequently asked questions".', + 'slug' => 'faq-page' + ), + array( + 'label' => 'LocalBusiness', + 'description' => 'A particular physical business or branch of an organization. Examples of LocalBusiness include a restaurant, a particular branch of a restaurant chain, a branch of a bank, a medical practice, a club, a bowling alley, etc.', + 'slug' => 'local-business' + + ), + array( + 'label' => 'Recipe', + 'description' => 'A recipe', + 'slug' => 'recipe' + ), + array( + 'label' => 'PodcastEpisode', + 'description' => 'A single episode of a podcast series.', + 'slug' => 'podcast-episode' + ), + array( + 'label' => 'Course', + 'description' => 'A description of an educational course which may be offered as distinct instances at which take place at different times or take place at different locations, or be offered through different media or modes of study.', + 'slug' => 'course' + ), + array( + 'label' => 'Event', + 'description' => 'An event happening at a certain time and location, such as a concert, lecture, or festival.', + 'slug' => 'event' + ), + array( + 'label' => 'Review', + 'description' => 'A review of an item - for example, of a restaurant, movie, or store.', + 'slug' => 'review' + ), + + ); + } + + + private static function get_entity_types_by_feature_flag( $package_type ) { + + switch ( $package_type ) { + case self::STARTER_PLAN: + return self::get_starter_entity_types(); + case self::BUSINESS_PLAN: + case self::PROFESSIONAL_PLAN: + // We return same entity types for professional and business plans. + // Business plan should have sync schema ui feature enabled, to sync all the entity types. + return array_merge( + self::get_starter_entity_types(), + self::get_professional_entity_types() + ); + default: + return array(); + + } + + } + + +} \ No newline at end of file diff --git a/src/wordlift/features/class-features-registry.php b/src/wordlift/features/class-features-registry.php index dbb49fdfce..933c765a5c 100644 --- a/src/wordlift/features/class-features-registry.php +++ b/src/wordlift/features/class-features-registry.php @@ -51,7 +51,6 @@ public function initialize_all_features() { } } - public function clear_all() { $this->features = array(); } diff --git a/src/wordlift/features/class-response-adapter.php b/src/wordlift/features/class-response-adapter.php index a748fa22a9..bc329010c1 100644 --- a/src/wordlift/features/class-response-adapter.php +++ b/src/wordlift/features/class-response-adapter.php @@ -43,10 +43,37 @@ function response( $response ) { $this->log->debug( "WL1 [ encoded :: $wl1_as_base64_string ] " . var_export( $wl1, true ) ); - // Update the feature flags. There's no need to check here if values differ (thus avoiding a call to db), since - // WordPress does that in `update_option`. - if ( isset( $wl1['features'] ) ) { - if ( update_option( self::WL_FEATURES, (array) $wl1['features'], true ) ) { + + $updated_features = $wl1['features']; + + $existing_features = get_option( self::WL_FEATURES, array() ); + + // Loop through updated features. + foreach ( $updated_features as $feature_slug => $new_value ) { + + // We cant pass false because that indicates if the feature is active or not, null is used to represent the features which are + // not set before. + $old_value = array_key_exists( $feature_slug, $existing_features ) ? $existing_features[ $feature_slug ] : null; + + if ( $old_value !== $new_value ) { + /** + * @param $feature_slug string The feature slug. + * @param $old_value null | boolean Null represents the feature flag was not set before. + * @param $new_value boolean True or false. + * + * @since 3.32.1 + * Hook : `wl_feature__change__{feature_slug}` + * Action hook to be fired when there is a change in feature state. + */ + do_action( "wl_feature__change__${feature_slug}", $new_value, $old_value, $feature_slug ); + } + + } + + + if ( isset( $updated_features ) ) { + + if ( update_option( self::WL_FEATURES, (array) $updated_features, true ) ) { $this->register_filters(); } } diff --git a/src/wordlift/post-excerpt/class-post-excerpt-rest-controller.php b/src/wordlift/post-excerpt/class-post-excerpt-rest-controller.php index ec8ded72bc..3876c289ab 100644 --- a/src/wordlift/post-excerpt/class-post-excerpt-rest-controller.php +++ b/src/wordlift/post-excerpt/class-post-excerpt-rest-controller.php @@ -50,7 +50,7 @@ public static function register_routes() { public static function get_post_excerpt( $request ) { $data = $request->get_params(); $post_id = $data['post_id']; - $post_body = $data['post_body']; + $post_body = strip_shortcodes( $data['post_body'] ); $current_hash = md5( $post_body ); $server_response = self::get_post_excerpt_conditionally( $post_id, $post_body, $current_hash ); if ( empty( $server_response ) || ! array_key_exists( 'post_excerpt', $server_response ) ) { diff --git a/src/wordlift/relation/class-object-relation-service.php b/src/wordlift/relation/class-object-relation-service.php index 4417e4dd50..7d9466bab0 100644 --- a/src/wordlift/relation/class-object-relation-service.php +++ b/src/wordlift/relation/class-object-relation-service.php @@ -54,7 +54,11 @@ public function get_references( $subject_id, $subject_type ) { $post_references = $this->post_relation_service->get_references( $subject_id, $subject_type ); $term_references = $this->term_relation_service->get_references( $subject_id, $subject_type ); - return array_merge( $post_references, $term_references ); + /** + * @since 3.31.3 + * Should return only unique references. + */ + return array_unique( array_merge( $post_references, $term_references ) ); } diff --git a/src/wordlift/term/class-type-service.php b/src/wordlift/term/class-type-service.php index b894e3b017..b01e7070b5 100644 --- a/src/wordlift/term/class-type-service.php +++ b/src/wordlift/term/class-type-service.php @@ -87,4 +87,16 @@ public function get_schema( $term_id ) { return $this->schema_service->get_schema( 'thing' ); } + /** + * Removes all the existing entity types and set the entity types for the term. + * @param $term_id int + * @param $entity_types array + */ + public function set_entity_types( $term_id, $entity_types ) { + delete_term_meta( $term_id, Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME ); + foreach ( $entity_types as $entity_type ) { + add_term_meta( $term_id, Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, $entity_type ); + } + } + } \ No newline at end of file diff --git a/src/wordlift/videoobject/filters/class-jw-player-capture.php b/src/wordlift/videoobject/filters/class-jw-player-capture.php index 0b47469cf6..0671b39db4 100644 --- a/src/wordlift/videoobject/filters/class-jw-player-capture.php +++ b/src/wordlift/videoobject/filters/class-jw-player-capture.php @@ -24,9 +24,9 @@ public function wl_videoobject_embedded_videos( $embedded_videos, $post_id ) { global $wpdb; $post_meta_table_name = $wpdb->postmeta; $query_template = <<prepare( $query_template, $post_id ); + $query = $wpdb->prepare( $query_template, '_jwppp-video-url-%', $post_id ); $video_ids = $wpdb->get_col( $query ); if ( ! $video_ids ) { return $embedded_videos; diff --git a/src/wordlift/vocabulary-terms/class-vocabulary-terms-loader.php b/src/wordlift/vocabulary-terms/class-vocabulary-terms-loader.php index 99ac4a56a5..a8299a3ca2 100644 --- a/src/wordlift/vocabulary-terms/class-vocabulary-terms-loader.php +++ b/src/wordlift/vocabulary-terms/class-vocabulary-terms-loader.php @@ -9,6 +9,7 @@ use Wordlift\Common\Loader\Default_Loader; use Wordlift\Vocabulary_Terms\Hooks\Term_Save; use Wordlift\Vocabulary_Terms\Jsonld\Jsonld_Generator; +use Wordlift\Vocabulary_Terms\Jsonld\Post_Jsonld; class Vocabulary_Terms_Loader extends Default_Loader { @@ -42,6 +43,8 @@ public function init_all_dependencies() { $jsonld->init(); $term_save_hook = new Term_Save(); $term_save_hook->init(); + $post_jsonld = new Post_Jsonld(); + $post_jsonld->init(); } protected function get_feature_slug() { diff --git a/src/wordlift/vocabulary-terms/jsonld/class-jsonld-generator.php b/src/wordlift/vocabulary-terms/jsonld/class-jsonld-generator.php index 151651d65f..69a8490d41 100644 --- a/src/wordlift/vocabulary-terms/jsonld/class-jsonld-generator.php +++ b/src/wordlift/vocabulary-terms/jsonld/class-jsonld-generator.php @@ -6,6 +6,7 @@ namespace Wordlift\Vocabulary_Terms\Jsonld; +use Wordlift\Jsonld\Post_Reference; use Wordlift\Object_Type_Enum; use Wordlift\Term\Type_Service; @@ -23,11 +24,16 @@ class Jsonld_Generator { * @var Type_Service */ private $term_entity_type_service; + /** + * @var \Wordlift_Entity_Service + */ + private $entity_service; public function __construct( $entity_type_service, $property_getter ) { $this->entity_type_service = $entity_type_service; $this->property_getter = $property_getter; $this->term_entity_type_service = Type_Service::get_instance(); + $this->entity_service = \Wordlift_Entity_Service::get_instance(); } public function init() { @@ -40,10 +46,17 @@ public function wl_term_jsonld_array( $data, $term_id ) { $term_jsonld_data = $this->get_jsonld_data_for_term( $term_id ); + // Return early if we dont have the entity data + // for the term. + if ( ! $term_jsonld_data ) { + return $data; + } + $term_jsonld = $term_jsonld_data['jsonld']; $references = array_merge( $references, $term_jsonld_data['references'] ); + array_unshift( $jsonld, $term_jsonld ); return array( @@ -53,15 +66,26 @@ public function wl_term_jsonld_array( $data, $term_id ) { } private function get_jsonld_data_for_term( $term_id ) { - $term = get_term( $term_id ); - $permalink = get_term_link( $term ); + + $id = wl_get_term_entity_uri( $term_id ); + + // If we dont have a dataset URI, then dont publish the term data + // on this page. + if ( ! $id ) { + return false; + } + + $references = array(); + $term = get_term( $term_id ); + $permalink = get_term_link( $term ); + $custom_fields = $this->entity_type_service->get_custom_fields_for_term( $term_id ); $term = get_term( $term_id ); $jsonld = array( '@context' => 'http://schema.org', 'name' => $term->name, '@type' => $this->term_entity_type_service->get_entity_types_labels( $term_id ), - '@id' => wl_get_term_entity_uri( $term_id ), + '@id' => $id, 'description' => $term->description, ); @@ -72,9 +96,12 @@ private function get_jsonld_data_for_term( $term_id ) { foreach ( $custom_fields as $key => $value ) { $name = $this->relative_to_schema_context( $value['predicate'] ); $value = $this->property_getter->get( $term_id, $key, Object_Type_Enum::TERM ); - if ( $value ) { - $jsonld[ $name ] = $value; + $value = $this->process_value( $value, $references ); + if ( ! $value ) { + continue; } + $jsonld[ $name ] = $value; + } if ( $permalink ) { @@ -84,7 +111,7 @@ private function get_jsonld_data_for_term( $term_id ) { return apply_filters( 'wl_no_vocabulary_term_jsonld_array', array( 'jsonld' => $jsonld, - 'references' => array() + 'references' => $references ), $term_id ); @@ -95,4 +122,37 @@ private function relative_to_schema_context( $predicate ) { return str_replace( 'http://schema.org/', '', $predicate ); } + private function process_value( $value, &$references ) { + + if ( ! $value ) { + return false; + } + + if ( is_array( $value ) + && count( $value ) > 0 + && $value[0] instanceof \Wordlift_Property_Entity_Reference ) { + + // All of the references from the custom fields are post references. + $references = array_merge( $references, array_map( function ( $property_entity_reference ) { + /** + * @var $property_entity_reference \Wordlift_Property_Entity_Reference + */ + return new Post_Reference( $property_entity_reference->get_id() ); + }, $value ) ); + + + $that = $this; + + return array_map( function ( $reference ) use ( $that ) { + /** + * @var $reference \Wordlift_Property_Entity_Reference + */ + return array( '@id' => $that->entity_service->get_uri( $reference->get_id() ) ); + }, $value ); + + } + + return $value; + } + } \ No newline at end of file diff --git a/src/wordlift/vocabulary-terms/jsonld/class-post-jsonld.php b/src/wordlift/vocabulary-terms/jsonld/class-post-jsonld.php new file mode 100644 index 0000000000..19e74bbbf4 --- /dev/null +++ b/src/wordlift/vocabulary-terms/jsonld/class-post-jsonld.php @@ -0,0 +1,88 @@ + + */ + +namespace Wordlift\Vocabulary_Terms\Jsonld; + +use Wordlift\Jsonld\Term_Reference; + +class Post_Jsonld { + + public function init() { + add_filter( 'wl_post_jsonld_array', array( $this, 'wl_post_jsonld_array' ), 10, 2 ); + } + + public function wl_post_jsonld_array( $data, $post_id ) { + + $term_references = $this->get_term_references( $post_id ); + + if ( ! $term_references ) { + return $data; + } + + $references = $data['references']; + $jsonld = $data['jsonld']; + + $jsonld['mentions'] = $this->append_term_mentions( $jsonld, $term_references ); + + return array( + 'jsonld' => $jsonld, + 'references' => array_merge( $references, $term_references ) + ); + } + + /** + * @param $post_id + * + * @return array Returns a list of term references, Returns empty array if none found. + */ + private function get_term_references( $post_id ) { + + $taxonomies_for_post = get_object_taxonomies( get_post_type( $post_id ) ); + + // now we need to collect all terms attached to this post. + $terms = array(); + + foreach ( $taxonomies_for_post as $taxonomy ) { + $taxonomy_terms = get_the_terms( $post_id, $taxonomy ); + if ( is_array( $taxonomy_terms ) ) { + $terms = array_merge( $terms, $taxonomy_terms ); + } + } + + // Convert everything to the Term Reference. + return array_filter( array_map( function ( $term ) { + /** + * @var \WP_Term $term + */ + if ( wl_get_term_entity_uri( $term->term_id ) ) { + return new Term_Reference( $term->term_id ); + } + + return false; + }, $terms ) ); + + } + + /** + * @param $jsonld array + * @param $term_references array + */ + private function append_term_mentions( $jsonld, $term_references ) { + + $existing_mentions = array_key_exists( 'mentions', $jsonld ) ? $jsonld['mentions'] : array(); + + + $term_mentions = array_map( function ( $term_reference ) { + return array( + '@id' => wl_get_term_entity_uri( $term_reference->get_id() ) + ); + }, $term_references ); + + return array_merge( $existing_mentions, $term_mentions ); + } + +} \ No newline at end of file diff --git a/src/wordlift/vocabulary/class-terms-compat.php b/src/wordlift/vocabulary/class-terms-compat.php index 3d2bf94d8b..b1c61460d9 100644 --- a/src/wordlift/vocabulary/class-terms-compat.php +++ b/src/wordlift/vocabulary/class-terms-compat.php @@ -3,14 +3,14 @@ class Terms_Compat { - public static function get_terms( $taxonomy, $args_with_taxonomy_key ) { + public static function get_terms( $taxonomy, $args ) { global $wp_version; if ( version_compare( $wp_version, '4.5', '<' ) ) { - return get_terms( $taxonomy, $args_with_taxonomy_key ); + return get_terms( $taxonomy, $args ); } else { - $args_with_taxonomy_key['taxonomy'] = $taxonomy; - return get_terms( $args_with_taxonomy_key ); + $args['taxonomy'] = $taxonomy; + return get_terms( $args ); } } diff --git a/tests/assets/videoobject/1cc59e342985a6f54ce0ef54900d530c.json b/tests/assets/videoobject/1cc59e342985a6f54ce0ef54900d530c.json new file mode 100644 index 0000000000..7cdf4f7721 --- /dev/null +++ b/tests/assets/videoobject/1cc59e342985a6f54ce0ef54900d530c.json @@ -0,0 +1,147 @@ +{ + "kind": "youtube#videoListResponse", + "etag": "RkIibqsuVdxjf-V8a_534USJzVg", + "items": [ + { + "kind": "youtube#video", + "etag": "FLH9Xx5_4qoa2p6NdzZ269Dbe4I", + "id": "fJAPDAK4GiI", + "snippet": { + "publishedAt": "2020-09-21T10:00:26Z", + "channelId": "UC4EW8bTZUPItoYhNeaWnQFg", + "title": "WordLift Review: How to Leverage AI to Improve your SEO", + "description": "Semantic Search has forever shifted how SEO should be approached. Today's SEO's need to optimize their pages so that machines can grasp the meaning in the same way their readers can. While this sounds overwhelming, there are some amazing tools on the market that can help you streamline this process. \n\nIn this video, we will review WordLift, \"An AI-powered SEO tool that does the heavy lifting for you.\" We will share what is it, why you need it, some of the results we are already seeing and how it works. \n\nIf you want to learn more about WordLift, check out: https://wordlift.io/\n\n\nšŸŽ“ Want to learn how to leverage Schema.org to improve your SEO results? Get my course \"Mastering Structured Data & Schema.org for Rich Results\" here: https://learn.simplifiedsearch.net/courses/mastering-structured-data-schema-org-for-rich-results\n\n______________________________________________\n\nšŸ“ŗ Learn more about Schema.org & Structured Data: https://www.youtube.com/playlist?list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6\n\nšŸŽ¬ How to Use Schema.org to Create and Add Structured Data to Your Website: https://www.youtube.com/watch?v=xQeRA-Ojq5c&list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6&index=4&t=0s\n\nšŸŽ¬ Where To Put Schema Markup On Your Website: https://www.youtube.com/watch?v=Uq9FjFngcUg\n\n_____________________________________________\n\nWho is SMA Marketing? \n\nSMA Marketing is an international search marketing agency that has been helping global and local brands grow online since 2009. \n\nWe specialize in SEO and Inbound lead generation. Levering both data and intuition, we've help hundreds of companies succeed online and trained thousands of entrepreneurs and marketers with the help of our videos. \n\nLearn more at: https://www.smamarketing.net\n\n#aiseo #schema.org #structureddata", + "thumbnails": { + "default": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/default.jpg", + "width": 120, + "height": 90 + }, + "medium": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/mqdefault.jpg", + "width": 320, + "height": 180 + }, + "high": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/hqdefault.jpg", + "width": 480, + "height": 360 + }, + "standard": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/sddefault.jpg", + "width": 640, + "height": 480 + }, + "maxres": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/maxresdefault.jpg", + "width": 1280, + "height": 720 + } + }, + "channelTitle": "SMA Marketing", + "tags": [ + "schema.org", + "structured data", + "ai tools for seo", + "AI SEO", + "WORDLIFT", + "technical seo", + "technical seo tutorial", + "technical seo 2020" + ], + "categoryId": "22", + "liveBroadcastContent": "none", + "localized": { + "title": "WordLift Review: How to Leverage AI to Improve your SEO", + "description": "Semantic Search has forever shifted how SEO should be approached. Today's SEO's need to optimize their pages so that machines can grasp the meaning in the same way their readers can. While this sounds overwhelming, there are some amazing tools on the market that can help you streamline this process. \n\nIn this video, we will review WordLift, \"An AI-powered SEO tool that does the heavy lifting for you.\" We will share what is it, why you need it, some of the results we are already seeing and how it works. \n\nIf you want to learn more about WordLift, check out: https://wordlift.io/\n\n\nšŸŽ“ Want to learn how to leverage Schema.org to improve your SEO results? Get my course \"Mastering Structured Data & Schema.org for Rich Results\" here: https://learn.simplifiedsearch.net/courses/mastering-structured-data-schema-org-for-rich-results\n\n______________________________________________\n\nšŸ“ŗ Learn more about Schema.org & Structured Data: https://www.youtube.com/playlist?list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6\n\nšŸŽ¬ How to Use Schema.org to Create and Add Structured Data to Your Website: https://www.youtube.com/watch?v=xQeRA-Ojq5c&list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6&index=4&t=0s\n\nšŸŽ¬ Where To Put Schema Markup On Your Website: https://www.youtube.com/watch?v=Uq9FjFngcUg\n\n_____________________________________________\n\nWho is SMA Marketing? \n\nSMA Marketing is an international search marketing agency that has been helping global and local brands grow online since 2009. \n\nWe specialize in SEO and Inbound lead generation. Levering both data and intuition, we've help hundreds of companies succeed online and trained thousands of entrepreneurs and marketers with the help of our videos. \n\nLearn more at: https://www.smamarketing.net\n\n#aiseo #schema.org #structureddata" + }, + "defaultAudioLanguage": "en" + }, + "contentDetails": { + "duration": "PT14M56S", + "dimension": "2d", + "definition": "hd", + "caption": "false", + "licensedContent": true, + "contentRating": {}, + "projection": "rectangular" + }, + "statistics": { + "viewCount": "1143", + "likeCount": "34", + "dislikeCount": "1", + "favoriteCount": "0", + "commentCount": "10" + } + }, + { + "kind": "youtube#video", + "etag": "ATjvjcoc2kpMe_8lnQxAxZptla4", + "id": "y-n93I5q-0g", + "snippet": { + "publishedAt": "2020-09-17T09:06:09Z", + "channelId": "UClqyCdHaE40_dEQM5cvLSnQ", + "title": "WordLift Mappings tutorial", + "description": "WordLift Mappings is a new and powerful feature of WordLift, that allows anyone ā€” without any coding skills ā€” to add schema.org markup to their websites enhancing the holistic perspective of the content model with structured data.\n\nOur SEO Expert Doreid Haddad will guide you step-by-step in this short tutorial. Ready?", + "thumbnails": { + "default": { + "url": "https://i.ytimg.com/vi/y-n93I5q-0g/default.jpg", + "width": 120, + "height": 90 + }, + "medium": { + "url": "https://i.ytimg.com/vi/y-n93I5q-0g/mqdefault.jpg", + "width": 320, + "height": 180 + }, + "high": { + "url": "https://i.ytimg.com/vi/y-n93I5q-0g/hqdefault.jpg", + "width": 480, + "height": 360 + }, + "standard": { + "url": "https://i.ytimg.com/vi/y-n93I5q-0g/sddefault.jpg", + "width": 640, + "height": 480 + } + }, + "channelTitle": "WordLift", + "tags": [ + "semantic seo", + "ai-powered seo", + "wordlift", + "search engine optimization", + "content modeling" + ], + "categoryId": "28", + "liveBroadcastContent": "none", + "defaultLanguage": "en", + "localized": { + "title": "WordLift Mappings tutorial", + "description": "WordLift Mappings is a new and powerful feature of WordLift, that allows anyone ā€” without any coding skills ā€” to add schema.org markup to their websites enhancing the holistic perspective of the content model with structured data.\n\nOur SEO Expert Doreid Haddad will guide you step-by-step in this short tutorial. Ready?" + }, + "defaultAudioLanguage": "en" + }, + "contentDetails": { + "duration": "PT19M38S", + "dimension": "2d", + "definition": "hd", + "caption": "false", + "licensedContent": false, + "contentRating": {}, + "projection": "rectangular" + }, + "statistics": { + "viewCount": "272", + "likeCount": "8", + "dislikeCount": "0", + "favoriteCount": "0", + "commentCount": "4" + } + } + ], + "pageInfo": { + "totalResults": 2, + "resultsPerPage": 2 + } +} diff --git a/tests/assets/videoobject/3e18aa6d46e45dc427faabe9eec8bd88.json b/tests/assets/videoobject/3e18aa6d46e45dc427faabe9eec8bd88.json new file mode 100644 index 0000000000..74f43f51b0 --- /dev/null +++ b/tests/assets/videoobject/3e18aa6d46e45dc427faabe9eec8bd88.json @@ -0,0 +1,82 @@ +{ + "kind": "youtube#videoListResponse", + "etag": "O8AfMr6VYVCs-cJE-bxQy55UkZg", + "items": [ + { + "kind": "youtube#video", + "etag": "FLH9Xx5_4qoa2p6NdzZ269Dbe4I", + "id": "fJAPDAK4GiI", + "snippet": { + "publishedAt": "2020-09-21T10:00:26Z", + "channelId": "UC4EW8bTZUPItoYhNeaWnQFg", + "title": "WordLift Review: How to Leverage AI to Improve your SEO", + "description": "Semantic Search has forever shifted how SEO should be approached. Today's SEO's need to optimize their pages so that machines can grasp the meaning in the same way their readers can. While this sounds overwhelming, there are some amazing tools on the market that can help you streamline this process. \n\nIn this video, we will review WordLift, \"An AI-powered SEO tool that does the heavy lifting for you.\" We will share what is it, why you need it, some of the results we are already seeing and how it works. \n\nIf you want to learn more about WordLift, check out: https://wordlift.io/\n\n\nšŸŽ“ Want to learn how to leverage Schema.org to improve your SEO results? Get my course \"Mastering Structured Data & Schema.org for Rich Results\" here: https://learn.simplifiedsearch.net/courses/mastering-structured-data-schema-org-for-rich-results\n\n______________________________________________\n\nšŸ“ŗ Learn more about Schema.org & Structured Data: https://www.youtube.com/playlist?list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6\n\nšŸŽ¬ How to Use Schema.org to Create and Add Structured Data to Your Website: https://www.youtube.com/watch?v=xQeRA-Ojq5c&list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6&index=4&t=0s\n\nšŸŽ¬ Where To Put Schema Markup On Your Website: https://www.youtube.com/watch?v=Uq9FjFngcUg\n\n_____________________________________________\n\nWho is SMA Marketing? \n\nSMA Marketing is an international search marketing agency that has been helping global and local brands grow online since 2009. \n\nWe specialize in SEO and Inbound lead generation. Levering both data and intuition, we've help hundreds of companies succeed online and trained thousands of entrepreneurs and marketers with the help of our videos. \n\nLearn more at: https://www.smamarketing.net\n\n#aiseo #schema.org #structureddata", + "thumbnails": { + "default": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/default.jpg", + "width": 120, + "height": 90 + }, + "medium": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/mqdefault.jpg", + "width": 320, + "height": 180 + }, + "high": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/hqdefault.jpg", + "width": 480, + "height": 360 + }, + "standard": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/sddefault.jpg", + "width": 640, + "height": 480 + }, + "maxres": { + "url": "https://i.ytimg.com/vi/fJAPDAK4GiI/maxresdefault.jpg", + "width": 1280, + "height": 720 + } + }, + "channelTitle": "SMA Marketing", + "tags": [ + "schema.org", + "structured data", + "ai tools for seo", + "AI SEO", + "WORDLIFT", + "technical seo", + "technical seo tutorial", + "technical seo 2020" + ], + "categoryId": "22", + "liveBroadcastContent": "none", + "localized": { + "title": "WordLift Review: How to Leverage AI to Improve your SEO", + "description": "Semantic Search has forever shifted how SEO should be approached. Today's SEO's need to optimize their pages so that machines can grasp the meaning in the same way their readers can. While this sounds overwhelming, there are some amazing tools on the market that can help you streamline this process. \n\nIn this video, we will review WordLift, \"An AI-powered SEO tool that does the heavy lifting for you.\" We will share what is it, why you need it, some of the results we are already seeing and how it works. \n\nIf you want to learn more about WordLift, check out: https://wordlift.io/\n\n\nšŸŽ“ Want to learn how to leverage Schema.org to improve your SEO results? Get my course \"Mastering Structured Data & Schema.org for Rich Results\" here: https://learn.simplifiedsearch.net/courses/mastering-structured-data-schema-org-for-rich-results\n\n______________________________________________\n\nšŸ“ŗ Learn more about Schema.org & Structured Data: https://www.youtube.com/playlist?list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6\n\nšŸŽ¬ How to Use Schema.org to Create and Add Structured Data to Your Website: https://www.youtube.com/watch?v=xQeRA-Ojq5c&list=PLRFTkssEVFpdb_M7rxX5LlVzvvVn5MHy6&index=4&t=0s\n\nšŸŽ¬ Where To Put Schema Markup On Your Website: https://www.youtube.com/watch?v=Uq9FjFngcUg\n\n_____________________________________________\n\nWho is SMA Marketing? \n\nSMA Marketing is an international search marketing agency that has been helping global and local brands grow online since 2009. \n\nWe specialize in SEO and Inbound lead generation. Levering both data and intuition, we've help hundreds of companies succeed online and trained thousands of entrepreneurs and marketers with the help of our videos. \n\nLearn more at: https://www.smamarketing.net\n\n#aiseo #schema.org #structureddata" + }, + "defaultAudioLanguage": "en" + }, + "contentDetails": { + "duration": "PT14M56S", + "dimension": "2d", + "definition": "hd", + "caption": "false", + "licensedContent": true, + "contentRating": {}, + "projection": "rectangular" + }, + "statistics": { + "viewCount": "1143", + "likeCount": "34", + "dislikeCount": "1", + "favoriteCount": "0", + "commentCount": "10" + } + } + ], + "pageInfo": { + "totalResults": 1, + "resultsPerPage": 1 + } +} diff --git a/tests/assets/videoobject/48f4f7efed307453ab9051ed7caa1236.json b/tests/assets/videoobject/48f4f7efed307453ab9051ed7caa1236.json new file mode 100644 index 0000000000..747331b183 --- /dev/null +++ b/tests/assets/videoobject/48f4f7efed307453ab9051ed7caa1236.json @@ -0,0 +1,137 @@ +{ + "total": 2, + "page": 1, + "per_page": 25, + "paging": { + "next": null, + "previous": null, + "first": "/videos/?uris=%2Fvideos%2F162427937%2C%2Fvideos%2F49219317&fields=name%2Cdescription%2Clink%2Curi%2Cduration%2Crelease_time%2Cpictures%2Cstats&page=1", + "last": "/videos/?uris=%2Fvideos%2F162427937%2C%2Fvideos%2F49219317&fields=name%2Cdescription%2Clink%2Curi%2Cduration%2Crelease_time%2Cpictures%2Cstats&page=1" + }, + "data": [ + { + "uri": "/videos/49219317", + "name": "Hexagon Example", + "description": "http://www.DigitalSandwich.net\n\nAn example of the \"Create C4D-style shader effector within AE\" tutorial found here: https://vimeo.com/49216173", + "link": "https://vimeo.com/49219317", + "duration": 4, + "release_time": "2012-09-11T06:50:13+00:00", + "pictures": { + "uri": "/videos/49219317/pictures/339541620", + "active": true, + "type": "custom", + "sizes": [ + { + "width": 100, + "height": 75, + "link": "https://i.vimeocdn.com/video/339541620_100x75?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F339541620_100x75&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 200, + "height": 150, + "link": "https://i.vimeocdn.com/video/339541620_200x150?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F339541620_200x150&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 295, + "height": 166, + "link": "https://i.vimeocdn.com/video/339541620_295x166?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F339541620_295x166&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 640, + "height": 360, + "link": "https://i.vimeocdn.com/video/339541620_640x360?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F339541620_640x360&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 960, + "height": 540, + "link": "https://i.vimeocdn.com/video/339541620_960x540?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F339541620_960x540&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 1280, + "height": 720, + "link": "https://i.vimeocdn.com/video/339541620_1280x720?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F339541620_1280x720&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 1920, + "height": 1080, + "link": "https://i.vimeocdn.com/video/339541620_1920x1080?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F339541620_1920x1080&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + } + ], + "resource_key": "fc895a716cd48f59eca6ecfe1b82c1b6064338bb", + "default_picture": false + }, + "stats": { + "plays": null + } + }, + { + "uri": "/videos/162427937", + "name": "EXAMPLE#1", + "description": "Animation example for projection mapping.\n\nProject on Behance:\ngoo.gl/h9pQmc", + "link": "https://vimeo.com/162427937", + "duration": 24, + "release_time": "2016-04-11T19:59:54+00:00", + "pictures": { + "uri": "/videos/162427937/pictures/567447764", + "active": true, + "type": "custom", + "sizes": [ + { + "width": 100, + "height": 75, + "link": "https://i.vimeocdn.com/video/567447764_100x75?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_100x75&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 200, + "height": 150, + "link": "https://i.vimeocdn.com/video/567447764_200x150?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_200x150&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 295, + "height": 166, + "link": "https://i.vimeocdn.com/video/567447764_295x166?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_295x166&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 640, + "height": 360, + "link": "https://i.vimeocdn.com/video/567447764_640x360?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_640x360&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 960, + "height": 540, + "link": "https://i.vimeocdn.com/video/567447764_960x540?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_960x540&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 1280, + "height": 720, + "link": "https://i.vimeocdn.com/video/567447764_1280x720?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_1280x720&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 1920, + "height": 1080, + "link": "https://i.vimeocdn.com/video/567447764_1920x1080?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_1920x1080&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + } + ], + "resource_key": "3916671c92378b4bb40fb7b4ea1860a3cb0d2206", + "default_picture": false + }, + "stats": { + "plays": 1112 + } + } + ] +} \ No newline at end of file diff --git a/tests/assets/videoobject/4e320a4557031abd25de340bd14067c2.json b/tests/assets/videoobject/4e320a4557031abd25de340bd14067c2.json new file mode 100644 index 0000000000..0fed3eacfb --- /dev/null +++ b/tests/assets/videoobject/4e320a4557031abd25de340bd14067c2.json @@ -0,0 +1,83 @@ +{ + "title": "AI-powered SEO Explained", + "description": "A quick introduction by Courtney McGhee from WooRank on how artificial intelligence and semantic technologies can help you grow the traffic on your website.\n\nFind out more on https://wordlift.io/ai-powered-seo", + "kind": "Single Item", + "playlist": [ + { + "title": "AI-powered SEO Explained", + "mediaid": "nT18k1bf", + "link": "https://cdn.jwplayer.com/previews/nT18k1bf", + "image": "https://cdn.jwplayer.com/v2/media/nT18k1bf/poster.jpg?width=720", + "images": [ + { + "src": "https://cdn.jwplayer.com/v2/media/nT18k1bf/poster.jpg?width=320", + "width": 320, + "type": "image/jpeg" + }, + { + "src": "https://cdn.jwplayer.com/v2/media/nT18k1bf/poster.jpg?width=480", + "width": 480, + "type": "image/jpeg" + }, + { + "src": "https://cdn.jwplayer.com/v2/media/nT18k1bf/poster.jpg?width=640", + "width": 640, + "type": "image/jpeg" + }, + { + "src": "https://cdn.jwplayer.com/v2/media/nT18k1bf/poster.jpg?width=720", + "width": 720, + "type": "image/jpeg" + } + ], + "duration": 103, + "pubdate": 1549021572, + "description": "A quick introduction by Courtney McGhee from WooRank on how artificial intelligence and semantic technologies can help you grow the traffic on your website.\n\nFind out more on https://wordlift.io/ai-powered-seo", + "tags": "ai,seo,wordlift,wordpress,machine learning", + "sources": [ + { + "file": "https://cdn.jwplayer.com/manifests/nT18k1bf.m3u8", + "type": "application/vnd.apple.mpegurl" + }, + { + "file": "https://cdn.jwplayer.com/videos/nT18k1bf-eir90hOW.mp4", + "type": "video/mp4", + "height": 180, + "width": 320, + "label": "H.264 320px", + "filesize": 3240664 + }, + { + "file": "https://cdn.jwplayer.com/videos/nT18k1bf-rxTKHieL.mp4", + "type": "video/mp4", + "height": 360, + "width": 640, + "label": "H.264 640px", + "filesize": 5102920 + }, + { + "file": "https://cdn.jwplayer.com/videos/nT18k1bf-0juCgc3x.mp4", + "type": "video/mp4", + "height": 720, + "width": 1280, + "label": "H.264 1280px", + "filesize": 14080110 + }, + { + "file": "https://cdn.jwplayer.com/videos/nT18k1bf-BFAxJ20w.m4a", + "type": "audio/mp4", + "label": "AAC Audio", + "filesize": 1465495 + } + ], + "tracks": [ + { + "file": "https://cdn.jwplayer.com/strips/nT18k1bf-120.vtt", + "kind": "thumbnails" + } + ], + "variations": {} + } + ], + "feed_instance_id": "a4ddb7e7-bf98-40e1-9880-882c167d7a9c" +} \ No newline at end of file diff --git a/tests/assets/videoobject/b06e27d9b8eed9dc4b5e92620714737d.json b/tests/assets/videoobject/b06e27d9b8eed9dc4b5e92620714737d.json new file mode 100644 index 0000000000..ef1c4317c0 --- /dev/null +++ b/tests/assets/videoobject/b06e27d9b8eed9dc4b5e92620714737d.json @@ -0,0 +1,75 @@ +{ + "total": 1, + "page": 1, + "per_page": 25, + "paging": { + "next": null, + "previous": null, + "first": "/videos/?uris=%2Fvideos%2F162427937&fields=name%2Cdescription%2Clink%2Curi%2Cduration%2Crelease_time%2Cpictures%2Cstats&page=1", + "last": "/videos/?uris=%2Fvideos%2F162427937&fields=name%2Cdescription%2Clink%2Curi%2Cduration%2Crelease_time%2Cpictures%2Cstats&page=1" + }, + "data": [ + { + "uri": "/videos/162427937", + "name": "EXAMPLE#1", + "description": "Animation example for projection mapping.\n\nProject on Behance:\ngoo.gl/h9pQmc", + "link": "https://vimeo.com/162427937", + "duration": 24, + "release_time": "2016-04-11T19:59:54+00:00", + "pictures": { + "uri": "/videos/162427937/pictures/567447764", + "active": true, + "type": "custom", + "sizes": [ + { + "width": 100, + "height": 75, + "link": "https://i.vimeocdn.com/video/567447764_100x75?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_100x75&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 200, + "height": 150, + "link": "https://i.vimeocdn.com/video/567447764_200x150?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_200x150&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 295, + "height": 166, + "link": "https://i.vimeocdn.com/video/567447764_295x166?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_295x166&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 640, + "height": 360, + "link": "https://i.vimeocdn.com/video/567447764_640x360?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_640x360&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 960, + "height": 540, + "link": "https://i.vimeocdn.com/video/567447764_960x540?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_960x540&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 1280, + "height": 720, + "link": "https://i.vimeocdn.com/video/567447764_1280x720?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_1280x720&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + }, + { + "width": 1920, + "height": 1080, + "link": "https://i.vimeocdn.com/video/567447764_1920x1080?r=pad", + "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F567447764_1920x1080&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png" + } + ], + "resource_key": "3916671c92378b4bb40fb7b4ea1860a3cb0d2206", + "default_picture": false + }, + "stats": { + "plays": 1112 + } + } + ] +} \ No newline at end of file diff --git a/tests/assets/videoobject/cc2f448decc234f18950a5cc32e525e7.json b/tests/assets/videoobject/cc2f448decc234f18950a5cc32e525e7.json new file mode 100644 index 0000000000..d3ced84643 --- /dev/null +++ b/tests/assets/videoobject/cc2f448decc234f18950a5cc32e525e7.json @@ -0,0 +1,9 @@ +{ + "kind": "youtube#videoListResponse", + "etag": "YIUPVpqNjppyCWOZfL-19bLb7uk", + "items": [], + "pageInfo": { + "totalResults": 0, + "resultsPerPage": 0 + } +} diff --git a/tests/class-wordlift-videoobject-unit-test-case.php b/tests/class-wordlift-videoobject-unit-test-case.php index 63c9e75c57..8dfaf39866 100644 --- a/tests/class-wordlift-videoobject-unit-test-case.php +++ b/tests/class-wordlift-videoobject-unit-test-case.php @@ -2,7 +2,7 @@ use Wordlift\Videoobject\Loader; -abstract class Wordlift_Videoobject_Unit_Test_Case extends Wordlift_Unit_Test_Case { +abstract class Wordlift_Videoobject_Unit_Test_Case extends Wordlift_Unit_Test_Case { public function setUp() { parent::setUp(); @@ -16,14 +16,37 @@ public function setUp() { $wp_styles = null; $loader = new Loader(); $loader->init_all_dependencies(); + add_filter( 'pre_http_request', array( $this, 'mock_api' ), 10, 3 ); + } + + function tearDown() { + parent::tearDown(); + remove_filter( 'pre_http_request', array( $this, 'mock_api' ) ); + } + + public function mock_api( $response, $request, $url ) { + + $mock_response_file = __DIR__ . "/assets/videoobject/" . md5( $url ) . '.json'; + $response_file_exists = file_exists( $mock_response_file ); + + if ( $response_file_exists ) { + return array( + 'body' => file_get_contents( $mock_response_file ), + 'response' => array( 'code' => 200 ) + ); + } + + return $response; + } public static function remove_all_whitespaces( $string ) { - $string = str_replace(" ", "", $string); - $string = str_replace("\n", "", $string); - $string = str_replace("\t", "", $string); - $string = str_replace("\r", "", $string); + $string = str_replace( " ", "", $string ); + $string = str_replace( "\n", "", $string ); + $string = str_replace( "\t", "", $string ); + $string = str_replace( "\r", "", $string ); + return $string; } } \ No newline at end of file diff --git a/tests/class-wordlift-vocabulary-terms-unit-test-case.php b/tests/class-wordlift-vocabulary-terms-unit-test-case.php index 71d46e4e6b..34196d5917 100644 --- a/tests/class-wordlift-vocabulary-terms-unit-test-case.php +++ b/tests/class-wordlift-vocabulary-terms-unit-test-case.php @@ -27,7 +27,6 @@ public function setUp() { // vocabulary terms feature should now be enabled. run_wordlift(); do_action('plugins_loaded'); - $features_registry->initialize_all_features(); } diff --git a/tests/test-backend-post-excerpt-rest-controller.php b/tests/test-backend-post-excerpt-rest-controller.php index ad744b1928..b4f6d15a92 100644 --- a/tests/test-backend-post-excerpt-rest-controller.php +++ b/tests/test-backend-post-excerpt-rest-controller.php @@ -133,6 +133,31 @@ public function test_if_valid_content_posted_should_return_valid_excerpt() { $this->assertEquals( $response_data['status'], 'success' ); } + public function test_post_excerpt_should_strip_shortcodes_before_sending_to_server() { + + $post_body_with_shortcode = <<factory()->post->create(); + + // hash the post body and save it. + $data = array( + 'post_body_hash' => md5( $post_body_without_shortcode ), + 'post_excerpt' => $post_body_without_shortcode + ); + update_post_meta( $post_id, Post_Excerpt_Rest_Controller::POST_EXCERPT_META_KEY, $data ); + + $request = new WP_REST_Request(); + $request->set_param( 'post_id', $post_id ); + $request->set_param( 'post_body', $post_body_with_shortcode); + + $response = Post_Excerpt_Rest_Controller::get_post_excerpt( $request ); + $this->assertSame( $post_body_without_shortcode, $response['post_excerpt'] ); + } + + /** * When the duplicate request with same body, then it should verify the hash in meta and deliever the response. */ diff --git a/tests/test-entity-package-type.php b/tests/test-entity-package-type.php new file mode 100644 index 0000000000..9b5e93b46f --- /dev/null +++ b/tests/test-entity-package-type.php @@ -0,0 +1,171 @@ +set_feature_and_trigger_config_save( 'entity-types-starter' ); + + $starter_feature_labels = array( + 'Person', + 'Thing', + 'Place', + 'CreativeWork', + 'Organization', + 'Article', + 'WebSite', + 'NewsArticle', + 'AboutPage', + 'ContactPage' + ); + + $entity_types = Terms_Compat::get_terms( Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, array( + 'hide_empty' => false, + ) ); + + $entity_type_labels = array_map( function ( $term ) { + return $term->name; + }, $entity_types ); + + $this->assertSame( + count( array_intersect( $entity_type_labels, $starter_feature_labels ) ), + count( $starter_feature_labels ), + 'Starter feature entity types should be present.' + ); + + + $this->verify_term_meta( $entity_types ); + } + + + public function test_when_package_type_changed_to_professional_should_have_only_professional_entity_types() { + + $this->set_feature_and_trigger_config_save( 'entity-types-professional' ); + + + $entity_types = Terms_Compat::get_terms( Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, array( + 'hide_empty' => false, + ) ); + + $entity_type_labels = array_map( function ( $term ) { + return $term->name; + }, $entity_types ); + + + $this->assertSame( + count( array_intersect( $entity_type_labels, $this->professional_feature_labels ) ), + count( $this->professional_feature_labels ), + 'Pro feature entity types should be present.' + ); + + $this->verify_term_meta( $entity_types ); + + } + + + public function test_when_package_type_changed_to_business_should_have_only_business_entity_types() { + + $this->set_feature_and_trigger_config_save( 'entity-types-business' ); + + + $entity_types = Terms_Compat::get_terms( Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, array( + 'hide_empty' => false, + ) ); + + $entity_type_labels = array_map( function ( $term ) { + return $term->name; + }, $entity_types ); + + $business_feature_labels = $this->professional_feature_labels; + + + $this->assertSame( + count( array_intersect( $entity_type_labels, $business_feature_labels ) ), + count( $business_feature_labels ), + 'Business feature entity types should be present.' + ); + + $this->verify_term_meta( $entity_types ); + + } + + + public function test_when_package_type_is_not_recognized_dont_alter_entity_types() { + + + $before_entity_types = Terms_Compat::get_terms( Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, array( + 'hide_empty' => false, + ) ); + + $before_entity_type_labels = array_map( function ( $term ) { + return $term->name; + }, $before_entity_types ); + + sort( $before_entity_type_labels ); + + // we set an unknown value to package type, for now we only recognize wl_starter, wl_professional, wl_business + // if we dont have any of these value then we shouldnt alter the entity types. + $this->set_feature_and_trigger_config_save( 'entity-types-blogger' ); + + $after_entity_types = Terms_Compat::get_terms( Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, array( + 'hide_empty' => false, + ) ); + + $after_entity_type_labels = array_map( function ( $term ) { + return $term->name; + }, $after_entity_types ); + + sort( $after_entity_type_labels ); + + + $this->assertSame( $before_entity_type_labels, $after_entity_type_labels, 'Entity types should not be affected by unknown package type' ); + + } + + private function set_feature_and_trigger_config_save( $feature_slug ) { + // This action hook is fired to indicate the feature was changed. + do_action("wl_feature__change__${feature_slug}", true, null, $feature_slug ); + } + + /** + * @param $terms + */ + private function verify_term_meta( $terms ) { + foreach ( $terms as $term ) { + $name = $term->name; + $this->assertSame( "http://schema.org/$name", get_term_meta( $term->term_id, '_wl_uri', true ), 'We should have term _wl_uri for the item' ); + $this->assertSame( $name, get_term_meta( $term->term_id, '_wl_name', true ), 'We should have term _wl_name for the item' ); + + } + } + + +} \ No newline at end of file diff --git a/tests/test-jsonld-post-to-jsonld-converter.php b/tests/test-jsonld-post-to-jsonld-converter.php index 0ab2dc0d1b..8434d160de 100644 --- a/tests/test-jsonld-post-to-jsonld-converter.php +++ b/tests/test-jsonld-post-to-jsonld-converter.php @@ -1397,10 +1397,10 @@ public function test_should_be_able_to_use_array_unique_on_references() { $term_reference = new Term_Reference( 1 ); $this->assertSame( (string) $post_reference, Object_Type_Enum::POST . "_1", "Post reference should be - able to convert to string"); + able to convert to string" ); $this->assertSame( (string) $term_reference, Object_Type_Enum::TERM . "_1", "Term reference should be - able to convert to string"); + able to convert to string" ); $this->assertCount( 2, array_unique( array( $post_reference, @@ -1411,6 +1411,76 @@ public function test_should_be_able_to_use_array_unique_on_references() { } + public function test_when_the_article_is_linked_to_entity_should_not_have_duplicate_mentions() { + + $post = $this->factory()->post->create(); + + // create an entity and link it to this post. + $entity = $this->factory()->post->create( array( 'post_type' => 'entity' ) ); + + // create a relation. + wl_core_add_relation_instance( $post, WL_WHAT_RELATION, $entity ); + // create duplicate relation + wl_core_add_relation_instance( $post, WL_WHAT_RELATION, $entity ); + + $jsonld = Wordlift_Jsonld_Service::get_instance()->get_jsonld( + false, + $post + ); + + $this->assertArrayHasKey( 'mentions', $jsonld[0] ); + + $mentions = $jsonld[0]['mentions']; + $this->assertCount( 1, $mentions ); + $this->assertEquals( array( '@id' => wl_get_entity_uri( $entity ) ), $mentions[0] ); + } + + + public function test_when_the_linked_entity_has_no_labels_should_not_add_to_about() { + $post = $this->factory()->post->create(); + + // create a tag. + $tag = wp_create_tag( 'linked_tag' ); + $term_id = $tag['term_id']; + // create an entity. + $entity = $this->factory()->post->create( array( 'post_type' => 'entity' ) ); + add_term_meta( $term_id, '_wl_entity_id', wl_get_entity_uri( $entity ) ); + + // set this tag to the post. + wp_set_object_terms( $post, array( $term_id ), 'post_tag' ); + + wp_update_post( array( + 'ID' => $entity, + 'post_title' => '' + ) ); + + // get the jsonld + $jsonld = Wordlift_Jsonld_Service::get_instance()->get_jsonld( + false, + $post + ); + + $article_jsonld = $jsonld[0]; + $this->assertFalse( array_key_exists( 'about', $article_jsonld ), 'About should not be present since it has empty labels' ); + } + + + public function test_when_the_linked_entity_title_matches_the_title_of_post_should_add_it_to_about() { + $post = $this->factory()->post->create( array( 'post_title' => 'Windows 7 ' ) ); + $entity = $this->factory()->post->create( array( 'post_type' => 'entity', 'post_title' => 'Windows' ) ); + wl_core_add_relation_instance( $post, WL_WHAT_RELATION, $entity ); + // get the jsonld + $jsonld = Wordlift_Jsonld_Service::get_instance()->get_jsonld( + false, + $post + ); + $article_jsonld = $jsonld[0]; + $this->assertTrue( array_key_exists( 'about', $article_jsonld ), 'About should be present since the title matches' ); + $this->assertCount( 1, $article_jsonld['about'] ); + $this->assertSame( array( '@id' => wl_get_entity_uri( $entity ) ), $article_jsonld['about'][0], 'The entity id should be correctly added on about key' ); + } + + /** * Get the word count for a {@link WP_Post}. * diff --git a/tests/test-jsonld-term-jsonld-adapter.php b/tests/test-jsonld-term-jsonld-adapter.php index dd9000d665..c77fb32701 100644 --- a/tests/test-jsonld-term-jsonld-adapter.php +++ b/tests/test-jsonld-term-jsonld-adapter.php @@ -9,6 +9,7 @@ */ use Wordlift\Jsonld\Jsonld_Context_Enum; +use Wordlift\Term\Type_Service; /** * Class Wordlift_Term_Jsonld_Adapter_Test @@ -22,7 +23,7 @@ class Wordlift_Term_Jsonld_Adapter_Test extends Wordlift_Unit_Test_Case { function setUp() { parent::setUp(); // TODO: Change the autogenerated stub - $this->adapter = new Wordlift_Term_JsonLd_Adapter( Wordlift_Entity_Uri_Service::get_instance(), Wordlift_Jsonld_Service::get_instance() ); + $this->adapter = Wordlift_Term_JsonLd_Adapter::get_instance(); } public function test_if_less_than_2_posts_are_present_then_dont_alter_the_jsonld() { diff --git a/tests/test-no-vocabulary-terms-jsonld.php b/tests/test-no-vocabulary-terms-jsonld.php index 718b8c3d92..dabfcfdde5 100644 --- a/tests/test-no-vocabulary-terms-jsonld.php +++ b/tests/test-no-vocabulary-terms-jsonld.php @@ -5,6 +5,7 @@ use Wordlift\Jsonld\Jsonld_Service; use Wordlift\Object_Type_Enum; use Wordlift\Relation\Object_Relation_Service; +use Wordlift\Term\Type_Service; use Wordlift\Term\Uri_Service; /** @@ -16,12 +17,60 @@ class No_Vocabulary_Terms_Jsonld extends \Wordlift_Vocabulary_Terms_Unit_Test_Ca public function test_when_term_saved_should_generate_entity_uri() { - $term_id = wp_insert_term( 'vocabulary_term_test_1', 'no_vocabulary_terms' ); - $term_id = $term_id['term_id']; + $term_id = $this->create_and_get_term(); $entity_uri = get_term_meta( $term_id, 'entity_url', true ); $this->assertNotEmpty( $entity_uri, 'Entity uri should be set upon term save' ); } + public function test_when_the_dataset_uri_not_present_dont_add_it_to_jsonld() { + $term_id = $this->create_and_get_term(); + delete_term_meta( $term_id, 'entity_url' ); + // Try to get the jsonld for this term. + $jsonld = Wordlift_Term_JsonLd_Adapter::get_instance()->get( $term_id, Jsonld_Context_Enum::UNKNOWN ); + $this->assertCount( 0, $jsonld ); + } + + public function test_when_the_property_reference_gets_added_to_the_term_should_print_correctly() { + $term_id = $this->create_and_get_term(); + // Set the Entity type to Person. + $term_type_service = Type_Service::get_instance(); + $term_type_service->set_entity_types( $term_id, array( 'person' ) ); + // Set the birthPlace property to refer to another entity. + $birth_place_entity_id = $this->factory()->post->create( array( 'post_type' => 'entity' ) ); + update_term_meta( $term_id, 'wl_birth_place', $birth_place_entity_id ); + // We should have this property on jsonld. + $jsonld = Wordlift_Term_JsonLd_Adapter::get_instance()->get( $term_id, Jsonld_Context_Enum::UNKNOWN ); + $term_entity_jsonld = $jsonld[0]; + $this->assertArrayHasKey( 'birthPlace', $term_entity_jsonld ); + $this->assertCount( 2, $jsonld, 'Term and the birth place reference should be expanded' ); + $this->assertCount( 1, $term_entity_jsonld['birthPlace'], 'Birth place ids should be present' ); + $birth_place_data = array( '@id' => wl_get_entity_uri( $birth_place_entity_id ) ); + $this->assertSame( $birth_place_data, $term_entity_jsonld['birthPlace'][0], 'Reference data should be expanded correctly.' ); + $this->assertSame( $jsonld[1]['@id'], wl_get_entity_uri( $birth_place_entity_id ), 'Entity URI should be present' ); + } + + public function test_when_term_has_post_entity_reference_and_linked_to_different_entity_should_generate_correct_jsonld() { + $tag = wp_create_tag( "test_jsonld_tag" ); + $term_id = $tag['term_id']; + // Set the Entity type to Person. + $term_type_service = Type_Service::get_instance(); + $term_type_service->set_entity_types( $term_id, array( 'person' ) ); + // Set the birthPlace property to refer to another entity. + $birth_place_entity_id = $this->factory()->post->create( array( 'post_type' => 'entity' ) ); + update_term_meta( $term_id, 'wl_birth_place', $birth_place_entity_id ); + // Link another entity to birthplace entity. + $another_entity = $this->factory()->post->create( array( 'post_type' => 'entity' ) ); + wl_core_add_relation_instance( $birth_place_entity_id, WL_WHAT_RELATION, $another_entity ); + // Now generate the jsonld. + $jsonld = Wordlift_Term_JsonLd_Adapter::get_instance()->get( + $term_id, + Jsonld_Context_Enum::PAGE + ); + $this->assertCount( 2, $jsonld, 'We should have term, as well as the post entity reference' ); + + $this->assertSame( $jsonld[1]['@id'], wl_get_entity_uri( $birth_place_entity_id ) ); + } + public function test_should_generate_id_for_term_correctly() { @@ -48,16 +97,16 @@ public function test_when_save_post_with_term_references_should_generate_jsonld_ $references = Object_Relation_Service::get_instance()->get_references( $post_id, Object_Type_Enum::POST ); $term_uri = Uri_Service::get_instance()->get_uri_by_term( $references[0]->get_id() ); $this->assertSame( $term_uri, $jsonld[1]['@id'], 'The term @id should be present in jsonld' ); - $this->assertSame( array('Thing'), $jsonld[1]['@type'], 'The term @type should be present in jsonld' ); + $this->assertSame( array( 'Thing' ), $jsonld[1]['@type'], 'The term @type should be present in jsonld' ); } public function test_should_get_annotation_also_for_terms() { - $term_data = wp_insert_term( 'term_analysis_test_1', 'category' ); + $term_data = wp_insert_term( 'term_analysis_test_1', 'category' ); $term = get_term( $term_data['term_id'] ); $term_uri_service = Uri_Service::get_instance(); - $term_uri_service->set_entity_uri( $term->term_id, "http://example.org/content_analysis_test_2"); + $term_uri_service->set_entity_uri( $term->term_id, "http://example.org/content_analysis_test_2" ); $request_body = file_get_contents( dirname( __FILE__ ) . '/assets/content-term-analysis-request.json' ); $request_json = json_decode( $request_body, true ); @@ -75,4 +124,70 @@ public function test_should_get_annotation_also_for_terms() { $this->assertCount( 1, array_values( $response_json['annotations'] ), 'The term annotation should be present in response' ); } + + /** + * @return int|mixed + */ + private function create_and_get_term() { + $term_id = wp_insert_term( 'vocabulary_term_test_1', 'no_vocabulary_terms' ); + $term_id = $term_id['term_id']; + + return $term_id; + } + + + public function test_when_post_is_annotated_with_term_without_dataset_uri_should_not_add_it_to_mentions() { + + $term_data = wp_insert_term( 'vocabulary_term_test_3', 'no_vocabulary_terms' ); + $term_id = $term_data['term_id']; + // Add it to a post. + $post_id = $this->factory()->post->create(); + // set the terms + wp_set_object_terms( $post_id, array( $term_id ), 'no_vocabulary_terms' ); + + // We manually remove entity_url + delete_term_meta( $term_id, 'entity_url' ); + + // Check the jsonld of the post + $jsonld = Wordlift_Jsonld_Service::get_instance() + ->get_jsonld( false, $post_id, Jsonld_Context_Enum::PAGE ); + $this->assertCount( 1, $jsonld, 'We should have no term references' ); + + $this->assertFalse( array_key_exists( 'mentions', $jsonld[0] ), 'Shouldnt be added to mentions since it doesnt have dataset uri' ); + } + + + public function test_when_post_is_annotated_with_term_with_dataset_uri_should_be_added_to_mentions() { + + $term_data = wp_insert_term( 'vocabulary_term_test_4', 'no_vocabulary_terms' ); + $term_id = $term_data['term_id']; + // Add it to a post. + $post_id = $this->factory()->post->create(); + // set the terms + wp_set_object_terms( $post_id, array( $term_id ), 'no_vocabulary_terms' ); + + // Check the jsonld of the post + $jsonld = Wordlift_Jsonld_Service::get_instance() + ->get_jsonld( false, $post_id, Jsonld_Context_Enum::PAGE ); + $post_jsonld = $jsonld[0]; + $this->assertTrue( array_key_exists( 'mentions', $post_jsonld ), 'Mentions should have the terms' ); + $this->assertCount( 1, $post_jsonld['mentions'], 'The term mention should be present' ); + + } + + function test_when_the_post_has_term_which_is_converted_to_entity_should_be_added_to_mentions() { + $post_id = $this->factory()->post->create(); + $term_data = wp_insert_term( 'vocabulary_term_test_5', 'no_vocabulary_terms' ); + $term_id = $term_data['term_id']; + wp_set_object_terms( $post_id, array( $term_id ), 'no_vocabulary_terms' ); + + $jsonld = Wordlift_Jsonld_Service::get_instance() + ->get_jsonld( false, $post_id, Jsonld_Context_Enum::PAGE ); + + // we should have the term entity in mentions. + $term_entity_uri = wl_get_term_entity_uri( $term_id ); + $this->assertSame( array( '@id' => $term_entity_uri ), $jsonld[0]['mentions'][0] ); + $this->assertSame( $term_entity_uri, $jsonld[1]['@id'] ); + + } } \ No newline at end of file diff --git a/tests/test-term-entity-field.php b/tests/test-term-entity-field.php new file mode 100644 index 0000000000..a580208e18 --- /dev/null +++ b/tests/test-term-entity-field.php @@ -0,0 +1,47 @@ +create_and_get_term(); + ob_start(); + $term_adapter->edit_form_fields( $term, 'category' ); + $output = ob_get_contents(); + ob_end_clean(); + $this->assertSame( '', $output ); + } + + public function test_when_term_have_data_for_term_entity_should_show_it() { + $term_adapter = new Wordlift_Admin_Term_Adapter(); + $term = $this->create_and_get_term(); + // Add term data. + add_term_meta( $term->term_id, Wordlift_Admin_Term_Adapter::META_KEY, 'https://dbpedia.org/test-entity' ); + ob_start(); + $term_adapter->edit_form_fields( $term, 'category' ); + $output = ob_get_contents(); + ob_end_clean(); + $this->assertNotSame( '', $output, 'Field should be shown, Should have HTML output.'); + } + + /** + * @return array|WP_Error|WP_Term|null + */ + private function create_and_get_term() { + $term_data = wp_insert_term( 'wordlift_admin_term_adapter_test_1', 'category' ); + + return get_term( $term_data['term_id'] ); + } + + +} \ No newline at end of file diff --git a/tests/test-videoobject-jsonld-test.php b/tests/test-videoobject-jsonld-test.php index 3a9b169074..045db561b3 100644 --- a/tests/test-videoobject-jsonld-test.php +++ b/tests/test-videoobject-jsonld-test.php @@ -35,7 +35,6 @@ public function test_given_post_id_should_generate_correct_jsonld() { $this->assertArrayHasKey( 'name', $single_video ); $this->assertArrayHasKey( 'description', $single_video ); $this->assertArrayHasKey( 'contentUrl', $single_video ); - $this->assertArrayHasKey( 'embedUrl', $single_video ); $this->assertArrayHasKey( 'uploadDate', $single_video ); $this->assertArrayHasKey( 'thumbnailUrl', $single_video ); $this->assertArrayHasKey( 'duration', $single_video );