/** * Serialize an entity post. * * @param array $entity The entity post or the entity post id. * * @return array mixed The entity data array. */ function wl_serialize_entity($entity) { $entity = is_numeric($entity) ? get_post($entity) : $entity; $type = wl_entity_type_taxonomy_get_type($entity->ID); $images = wl_get_image_urls($entity->ID); return array('id' => wl_get_entity_uri($entity->ID), 'label' => $entity->post_title, 'description' => wp_strip_all_tags($entity->post_content), 'sameAs' => wl_schema_get_value($entity->ID, 'sameAs'), 'mainType' => str_replace('wl-', '', $type['css_class']), 'types' => wl_get_entity_rdf_types($entity->ID), 'images' => $images); }
function testFindByURI() { $entity_post_id = wl_create_post('', 'test_entity', 'Test Entity', 'draft', 'entity'); $entity_uri = wl_get_entity_uri($entity_post_id); wl_schema_set_value($entity_post_id, 'sameAs', 'http://example.org/entity/test_entity'); $same_as_array = wl_schema_get_value($entity_post_id, 'sameAs'); $this->assertTrue(is_array($same_as_array)); $this->assertEquals('http://example.org/entity/test_entity', $same_as_array[0]); wl_schema_set_value($entity_post_id, 'sameAs', array('http://example.org/entity/test_entity', 'http://data.example.org/entity/test_entity')); $same_as_array = wl_schema_get_value($entity_post_id, 'sameAs'); $this->assertTrue(is_array($same_as_array)); $this->assertEquals('http://example.org/entity/test_entity', $same_as_array[0]); $this->assertEquals('http://data.example.org/entity/test_entity', $same_as_array[1]); $post = wl_get_entity_post_by_uri('http://example.org/entity/test_entity'); $this->assertNotNull($post); $post = wl_get_entity_post_by_uri('http://data.example.org/entity/test_entity'); $this->assertNotNull($post); $same_as_uri = 'http://example.org/entity/test_entity2'; $entity_post_id = wl_create_post('', 'test_entity_2', 'Test Entity 2', 'draft', 'entity'); $entity_uri = wl_get_entity_uri($entity_post_id); wl_schema_set_value($entity_post_id, 'sameAs', $same_as_uri); $same_as_array = wl_schema_get_value($entity_post_id, 'sameAs'); $this->assertTrue(is_array($same_as_array)); $this->assertEquals($same_as_uri, $same_as_array[0]); $post = wl_get_entity_post_by_uri('http://example.org/entity/test_entity'); $this->assertNotNull($post); }
/** * Test set- and get- methods for schema properties */ function testSchemaProperty() { $place_id = wl_create_post('Entity 1 Text', 'entity-1', 'Entity 1 Title', 'publish', 'entity'); wl_schema_set_types($place_id, 'Place'); wl_schema_add_value($place_id, 'sameAs', 'http://dbpedia.org/resource/my-place'); wl_schema_add_value($place_id, 'sameAs', 'http://rdf.freebase.com/my-place'); wl_schema_set_value($place_id, 'latitude', 40.12); $event_id = wl_create_post("Entity 2 Text", 'entity-2', "Entity 2 Title", 'publish', 'entity'); wl_schema_set_types($event_id, 'Event'); wl_schema_set_value($event_id, 'sameAs', array('http://rdf.freebase.com/my-event', 'http://dbpedia.org/resource/my-event')); wl_schema_set_value($event_id, 'startDate', '2014-10-21'); // Positive tests $value = wl_schema_get_value($place_id, 'sameAs'); $this->assertEquals(array('http://rdf.freebase.com/my-place', 'http://dbpedia.org/resource/my-place'), $value); $value = wl_schema_get_value($place_id, 'latitude'); $this->assertEquals(array(40.12), $value); $value = wl_schema_get_value($event_id, 'sameAs'); $this->assertEquals(array('http://rdf.freebase.com/my-event', 'http://dbpedia.org/resource/my-event'), $value); $value = wl_schema_get_value($event_id, 'startDate'); $this->assertEquals(array('2014-10-21'), $value); // Negative tests $value = wl_schema_get_value($place_id, null); $this->assertEquals(null, $value); $value = wl_schema_get_value($place_id, 'startDate'); $this->assertEquals(null, $value); $value = wl_schema_get_value($place_id, 'http://invented_url/something'); $this->assertEquals(null, $value); //TODO: manage case of multiple values per property. }
/** * Add a value of the specified property for the entity, where * * @param $post_id numeric The numeric post ID. * @param $property_name string Name of the property (e.g. name, for the http://schema.org/name property). * @param $property_value mixed Value to save into the property (adding to already saved). * * @return array An array of values or NULL in case of no values (or error). */ function wl_schema_add_value($post_id, $property_name, $property_value) { if (!is_array($property_value)) { $property_value = array($property_value); } $old_values = wl_schema_get_value($post_id, $property_name); $merged_property_value = array_unique(array_merge($property_value, $old_values)); wl_schema_set_value($post_id, $property_name, $merged_property_value); }
function testSavePlaceWithCoordinates() { $entity_props = array('uri' => 'http://dbpedia.org/resource/Frattocchie', 'label' => 'Frattocchie', 'main_type' => 'http://schema.org/Place', 'description' => 'best place on hearth, where the porchetta freely flows', 'same_as' => array('http://dbpedia.org/resource/Frattocchie', 'http://frattocchie.com/love'), 'properties' => array('latitude' => array(43.21), 'longitude' => 12.34, 'fake' => array('must', 'not', 'be', 'saved'))); $entity_post = wl_save_entity($entity_props); $this->assertNotNull($entity_post); // Check that the type is set correctly. $this->assertEquals(array('http://schema.org/Place'), wl_schema_get_types($entity_post->ID)); // Check coordinates $this->assertEquals(array(43.21), wl_schema_get_value($entity_post->ID, 'latitude')); $this->assertEquals(array(12.34), wl_schema_get_value($entity_post->ID, 'longitude')); // Check invalid property $this->assertEquals(null, wl_schema_get_value($entity_post->ID, 'fake')); }
/** * Print wl_field shortcode * * @param array $atts An array of shortcode attributes. * @return string A dom element with requested property value(s). */ function wl_shortcode_field($atts) { // Extract attributes and set default values. $field_atts = shortcode_atts(array('id' => null, 'name' => null), $atts); // Get id of the post $entity_id = $field_atts['id']; if (is_null($field_atts['id']) || !is_numeric($field_atts['id'])) { $entity_id = get_the_ID(); } $property_name = $field_atts['name']; if (!is_null($property_name)) { $values = wl_schema_get_value($entity_id, $property_name); } // Return if (is_array($values)) { return implode(', ', $values); } else { return null; } }
function testEntityMetadataAreProperlyUpdated() { $fake = $this->prepareFakeGlobalPostArrayFromFile('/assets/fake_global_post_array_with_one_entity_linked_as_what.json'); $_POST = $fake; // Retrieve the entity uri (the first key in wl_entities associative aray) $original_entity_uri = current(array_keys($fake['wl_entities'])); // Reference the entity to the post content $content = <<<EOF <span itemid="{$original_entity_uri}">My entity</span> EOF; // Create a post referincing to the created entity $post_id = wl_create_post($content, 'my-post', 'A post', 'draft'); // Here the entity should have been created $original_entity = wl_get_entity_post_by_uri($original_entity_uri); $this->assertNotNull($original_entity); // Store entity type, images and sameAs (needed later) $original_type = wl_schema_get_types($original_entity->ID); $original_thumbnails = $this->getThumbs($original_entity->ID); $original_sameAs = wl_schema_get_value($original_entity->ID, 'sameAs'); // Query the same entity using the Redlink URI $entity_uri = wl_get_entity_uri($original_entity->ID); $e = wl_get_entity_post_by_uri($entity_uri); $this->assertEquals($original_entity, $e); // The entity description should be the same we expect $raw_entity = current(array_values($fake['wl_entities'])); $this->assertEquals($raw_entity['description'], $original_entity->post_content); // The entity is related as what predicate $related_entity_ids = wl_core_get_related_entity_ids($post_id, array("predicate" => "what")); $this->assertCount(1, $related_entity_ids); // Ensure there are no other relation instances $relation_instances = wl_tests_get_relation_instances_for($post_id); $this->assertCount(1, $relation_instances); /* Now Post is saved again with the same mentioned entity: * - with different type * - with different description * - with one more image * - with one modified sameAs * - as WHO instead fo WHAT */ $fake = $this->prepareFakeGlobalPostArrayFromFile('/assets/fake_global_post_array_with_one_entity_linked_as_who_and_modified_data.json'); $_POST = $fake; // The entity url should be the same we expect $raw_entity = current(array_values($fake['wl_entities'])); $raw_entity_uri = $raw_entity['uri']; $new_content = <<<EOF <span itemid="{$raw_entity_uri}">My entity</span> EOF; // Update the post content (to force existing entities update) wp_update_post(array('ID' => $post_id, 'post_content' => $new_content)); // Verify the mentioned entity was already into DB... $updated_entity = wl_get_entity_post_by_uri($raw_entity_uri); $this->assertEquals($original_entity->ID, $updated_entity->ID); $this->assertEquals($original_entity->post_title, $updated_entity->post_title); // ... but some properties changed! $this->assertNotEquals($original_entity, $updated_entity); // Verify entity type has been updated $updated_type = wl_schema_get_types($updated_entity->ID); $this->assertNotEquals($original_type, $updated_type); $this->assertEquals(array('http://schema.org/Organization'), $updated_type); // Verify entity description has been updated $this->assertEquals($raw_entity['description'], $updated_entity->post_content); // Verify entity images have been updated (one was added) $updated_thumbnails = $this->getThumbs($updated_entity->ID); $this->assertNotEquals($original_thumbnails, $updated_thumbnails); $this->assertContains($original_thumbnails[0], $updated_thumbnails); $this->assertCount(2, $updated_thumbnails); // There is one more $this->assertContains('Netherlands_vs_Ivory_Coast', $updated_thumbnails[1]); // ... about soccer // Verify entity sameAs have been updated $updated_sameAs = wl_schema_get_value($updated_entity->ID, 'sameAs'); $this->assertNotEquals($original_sameAs, $updated_sameAs); $this->assertContains($original_sameAs[1], $updated_sameAs); $this->assertNotContains($original_sameAs[0], $updated_sameAs); $this->assertContains('http://sv.dbpedia.org/page/Reason', $updated_sameAs); // Verify the entity is now related as who predicate $related_entity_ids = wl_core_get_related_entity_ids($post_id, array("predicate" => "who")); $this->assertCount(1, $related_entity_ids); // Ensure there are no other relation instances $relation_instances = wl_tests_get_relation_instances_for($post_id); $this->assertCount(1, $relation_instances); }
/** * Displays the sameAs meta box contents (called by *add_meta_box* callback). * * @param WP_Post $post The current post. */ function wl_entities_sameas_box_content($post) { // Set nonce for both meta (latitude and longitude) wl_echo_nonce(WL_CUSTOM_FIELD_SAME_AS); // Get sameAs $sameAs = implode("\n", wl_schema_get_value($post->ID, 'sameAs')); // Print input textarea. The user writes here the sameAs URIs, separated by \n. echo '<textarea style="width: 100%;" id="wl_same_as" placeholder="Same As URLs, one per row">' . esc_attr($sameAs) . '</textarea>'; echo '<div id="wl_same_as_list"></div>'; // Input tags are updated at each change to contain the rows typed in the textarea echo <<<EOF <script> \$ = jQuery; \$(document).ready(function(){ refreshSameAsList(); // refresh now and at every change event \$("#wl_same_as").on("change keyup paste", function(){ refreshSameAsList(); }); function refreshSameAsList() { \$("#wl_same_as_list").empty(); var sameAsList = \$("#wl_same_as").val(); sameAsList = sameAsList.split('\\n'); console.log(sameAsList); for(var i=0; i<sameAsList.length; i++){ // some validation if(sameAsList[i].indexOf("http") == 0){ // Refresh input tags \$("#wl_same_as_list").append( '<input type="hidden" name="wl_metaboxes[entity_same_as][' + i + ']" value="' + sameAsList[i] + '" />' ); } } } }); </script> EOF; }
/** * Push the provided entity post to Redlink. * * @param object $entity_post An entity post instance. */ function wl_push_entity_post_to_redlink($entity_post) { // Get the Entity service instance to perform actions related to entities. $entity_service = Wordlift_Entity_Service::get_instance(); // Only handle published entities. if (!$entity_service->is_entity($entity_post->ID) || 'publish' !== $entity_post->post_status) { wl_write_log("wl_push_entity_post_to_redlink : not an entity or not published [ post type :: {$entity_post->post_type} ][ post status :: {$entity_post->post_status} ]"); return; } // get the entity URI and the SPARQL escaped version. $uri = wl_get_entity_uri($entity_post->ID); $uri_e = wl_sparql_escape_uri($uri); // If the URI ends with a trailing slash, then we have a problem. if ('/' === substr($uri, -1, 1)) { wl_write_log("wl_push_entity_post_to_redlink : the URI is invalid [ post ID :: {$entity_post->ID} ][ URI :: {$uri} ]"); return; } // Get the site language in order to define the literals language. $site_language = wl_configuration_get_site_language(); // get the title and content as label and description. $label = wordlift_esc_sparql($entity_post->post_title); $descr = wordlift_esc_sparql(wp_strip_all_tags(strip_shortcodes($entity_post->post_content))); $permalink = wl_sparql_escape_uri(get_permalink($entity_post->ID)); // wl_write_log( "wl_push_entity_post_to_redlink [ entity post id :: $entity_post->ID ][ uri :: $uri ][ label :: $label ]" ); // create a new empty statement. $delete_stmt = ''; $sparql = ''; // delete on RL all statements regarding properties set from WL (necessary when changing entity type) $all_custom_fields = wl_entity_taxonomy_get_custom_fields(); $predicates_to_be_deleted = array(); foreach ($all_custom_fields as $type => $fields) { foreach ($fields as $cf) { $predicate = $cf['predicate']; if (!in_array($predicate, $predicates_to_be_deleted)) { $predicates_to_be_deleted[] = $predicate; $delete_stmt .= "DELETE { <{$uri_e}> <{$predicate}> ?o } WHERE { <{$uri_e}> <{$predicate}> ?o };\n"; } } } // set the same as. $same_as = wl_schema_get_value($entity_post->ID, 'sameAs'); foreach ($same_as as $same_as_uri) { $same_as_uri_esc = wl_sparql_escape_uri($same_as_uri); $sparql .= "<{$uri_e}> owl:sameAs <{$same_as_uri_esc}> . \n"; } // set the label $sparql .= "<{$uri_e}> rdfs:label \"{$label}\"@{$site_language} . \n"; // Set the alternative labels. $alt_labels = $entity_service->get_alternative_labels($entity_post->ID); foreach ($alt_labels as $alt_label) { $sparql .= sprintf('<%s> rdfs:label "%s"@%s . ', $uri_e, Wordlift_Query_Builder::escape_value($alt_label), $site_language); } // set the URL $sparql .= "<{$uri_e}> schema:url <{$permalink}> . \n"; // set the description. if (!empty($descr)) { $sparql .= "<{$uri_e}> schema:description \"{$descr}\"@{$site_language} . \n"; } $main_type = wl_entity_type_taxonomy_get_type($entity_post->ID); if (null != $main_type) { $main_type_uri = wl_sparql_escape_uri($main_type['uri']); $sparql .= " <{$uri_e}> a <{$main_type_uri}> . \n"; // The type define custom fields that hold additional data about the entity. // For example Events may have start/end dates, Places may have coordinates. // The value in the export fields must be rewritten as triple predicates, this // is what we're going to do here. // wl_write_log( 'wl_push_entity_post_to_redlink : checking if entity has export fields [ type :: ' . var_export( $main_type, true ) . ' ]' ); if (isset($main_type['custom_fields'])) { foreach ($main_type['custom_fields'] as $field => $settings) { // wl_write_log( "wl_push_entity_post_to_redlink : entity has export fields" ); $predicate = wordlift_esc_sparql($settings['predicate']); if (!isset($settings['export_type']) || empty($settings['export_type'])) { $type = null; } else { $type = $settings['export_type']; } foreach (get_post_meta($entity_post->ID, $field) as $value) { $sparql .= " <{$uri_e}> <{$predicate}> "; if (!is_null($type) && substr($type, 0, 4) == 'http') { // Type is defined by a raw uri (es. http://schema.org/PostalAddress) // Extract uri if the value is numeric if (is_numeric($value)) { $value = wl_get_entity_uri($value); } $sparql .= '<' . wl_sparql_escape_uri($value) . '>'; } else { // Type is defined in another way (es. xsd:double) $sparql .= '"' . wordlift_esc_sparql($value) . '"^^' . wordlift_esc_sparql($type); } $sparql .= " . \n"; } } } } // Get the entity types. $type_uris = wl_get_entity_rdf_types($entity_post->ID); // Support type are only schema.org ones: it could be null foreach ($type_uris as $type_uri) { $type_uri = wl_sparql_escape_uri($type_uri); $sparql .= "<{$uri_e}> a <{$type_uri}> . \n"; } // get related entities. $related_entities_ids = wl_core_get_related_entity_ids($entity_post->ID); if (is_array($related_entities_ids)) { foreach ($related_entities_ids as $entity_post_id) { $related_entity_uri = wl_sparql_escape_uri(wl_get_entity_uri($entity_post_id)); // create a two-way relationship. $sparql .= " <{$uri_e}> dct:relation <{$related_entity_uri}> . \n"; $sparql .= " <{$related_entity_uri}> dct:relation <{$uri_e}> . \n"; } } // Add SPARQL stmts to write the schema:image. $sparql .= wl_get_sparql_images($uri, $entity_post->ID); $query = rl_sparql_prefixes() . <<<EOF {$delete_stmt} DELETE { <{$uri_e}> rdfs:label ?o } WHERE { <{$uri_e}> rdfs:label ?o }; DELETE { <{$uri_e}> owl:sameAs ?o . } WHERE { <{$uri_e}> owl:sameAs ?o . }; DELETE { <{$uri_e}> schema:description ?o . } WHERE { <{$uri_e}> schema:description ?o . }; DELETE { <{$uri_e}> schema:url ?o . } WHERE { <{$uri_e}> schema:url ?o . }; DELETE { <{$uri_e}> a ?o . } WHERE { <{$uri_e}> a ?o . }; DELETE { <{$uri_e}> dct:relation ?o . } WHERE { <{$uri_e}> dct:relation ?o . }; DELETE { <{$uri_e}> schema:image ?o . } WHERE { <{$uri_e}> schema:image ?o . }; INSERT DATA { {$sparql} }; EOF; rl_execute_sparql_update_query($query); }
function testEntityAdditionalPropertiesAreSaved() { $fake = $this->prepareFakeGlobalPostArrayFromFile('/assets/fake_global_post_array_with_a_new_entity_linked_as_where_with_coordinates.json'); $_POST = $fake; // Retrieve the entity uri (the first key in wl_entities associative aray) $entity_uri = current(array_keys($fake['wl_entities'])); // Retrieve the label and compose expected uri $raw_entity = current(array_values($fake['wl_entities'])); $expected_entity_uri = $this->buildEntityUriForLabel($raw_entity['label']); // Reference the entity to the post content $content = <<<EOF <span itemid="{$entity_uri}">My entity</span> EOF; // Create a post referincing to the created entity $post_id = wl_create_post($content, 'my-post', 'A post', 'draft'); // Here the entity should have been created $entity = wl_get_entity_post_by_uri($expected_entity_uri); $this->assertNotNull($entity); // Verify association to post as where $related_entity_ids = wl_core_get_related_entity_ids($post_id, array("predicate" => "where")); $this->assertEquals(array($entity->ID), $related_entity_ids); // Verify schema type $this->assertEquals(array('http://schema.org/Place'), wl_schema_get_types($entity->ID)); // Verify coordinates $this->assertEquals(array(43.21), wl_schema_get_value($entity->ID, 'latitude')); $this->assertEquals(array(12.34), wl_schema_get_value($entity->ID, 'longitude')); }
/** * Get the coordinates for the specified post ID. * * @param int $post_id The post ID. * * @return array|null An array of coordinates or null. */ function wl_get_coordinates($post_id) { $latitude = wl_schema_get_value($post_id, 'latitude'); $longitude = wl_schema_get_value($post_id, 'longitude'); // DO NOT set latitude/longitude to 0/0 as default values. It's a specific place on the globe: // "The zero/zero point of this system is located in the Gulf of Guinea about 625 km (390 mi) south of Tema, Ghana." return array('latitude' => isset($latitude[0]) && is_numeric($latitude[0]) ? $latitude[0] : '', 'longitude' => isset($longitude[0]) && is_numeric($longitude[0]) ? $longitude[0] : ''); }
/** * Push the provided entity post to Redlink. * * @param object $entity_post An entity post instance. */ function wl_push_entity_post_to_redlink($entity_post) { // Only handle published entities. if ('entity' !== $entity_post->post_type or 'publish' !== $entity_post->post_status) { wl_write_log("wl_push_entity_post_to_redlink : not an entity or not published [ post type :: {$entity_post->post_type} ][ post status :: {$entity_post->post_status} ]"); return; } // get the entity URI and the SPARQL escaped version. $uri = wl_get_entity_uri($entity_post->ID); $uri_e = wl_sparql_escape_uri($uri); // If the URI ends with a trailing slash, then we have a problem. if ('/' === substr($uri, -1, 1)) { wl_write_log("wl_push_entity_post_to_redlink : the URI is invalid [ post ID :: {$entity_post->ID} ][ URI :: {$uri} ]"); return; } // Get the site language in order to define the literals language. $site_language = wl_configuration_get_site_language(); // get the title and content as label and description. $label = wordlift_esc_sparql($entity_post->post_title); $descr = wordlift_esc_sparql($entity_post->post_content); $permalink = wl_sparql_escape_uri(get_permalink($entity_post->ID)); wl_write_log("wl_push_entity_post_to_redlink [ entity post id :: {$entity_post->ID} ][ uri :: {$uri} ][ label :: {$label} ]"); // create a new empty statement. $delete_stmt = ''; $sparql = ''; // set the same as. $same_as = wl_schema_get_value($entity_post->ID, 'sameAs'); foreach ($same_as as $same_as_uri) { $same_as_uri_esc = wl_sparql_escape_uri($same_as_uri); $sparql .= "<{$uri_e}> owl:sameAs <{$same_as_uri_esc}> . \n"; } // set the label $sparql .= "<{$uri_e}> rdfs:label \"{$label}\"@{$site_language} . \n"; // set the URL $sparql .= "<{$uri_e}> schema:url <{$permalink}> . \n"; // set the description. if (!empty($descr)) { $sparql .= "<{$uri_e}> schema:description \"{$descr}\"@{$site_language} . \n"; } $main_type = wl_entity_type_taxonomy_get_type($entity_post->ID); if (null != $main_type) { $main_type_uri = wl_sparql_escape_uri($main_type['uri']); $sparql .= " <{$uri_e}> a <{$main_type_uri}> . \n"; // The type define custom fields that hold additional data about the entity. // For example Events may have start/end dates, Places may have coordinates. // The value in the export fields must be rewritten as triple predicates, this // is what we're going to do here. wl_write_log('wl_push_entity_post_to_redlink : checking if entity has export fields [ type :: ' . var_export($main_type, true) . ' ]'); if (isset($main_type['custom_fields'])) { foreach ($main_type['custom_fields'] as $field => $settings) { wl_write_log("wl_push_entity_post_to_redlink : entity has export fields"); $predicate = wordlift_esc_sparql($settings['predicate']); if (!isset($settings['export_type']) || empty($settings['export_type'])) { $type = null; } else { $type = $settings['export_type']; } // add the delete statement for later execution. $delete_stmt .= "DELETE { <{$uri_e}> <{$predicate}> ?o } WHERE { <{$uri_e}> <{$predicate}> ?o };\n"; foreach (get_post_meta($entity_post->ID, $field) as $value) { $sparql .= " <{$uri_e}> <{$predicate}> "; // Establish triple's <object> type if (is_null($type)) { // No type $sparql .= '<' . wl_sparql_escape_uri($value) . '>'; } else { $sparql .= '"' . wordlift_esc_sparql($value) . '"^^'; if (substr($type, 0, 4) == 'http') { // Type is defined by a raw uri (es. http://schema.org/PostalAddress) $sparql .= '<' . wl_sparql_escape_uri($type) . '>'; } else { // Type is defined in another way (es. xsd:double) $sparql .= wordlift_esc_sparql($type); } } $sparql .= " . \n"; } } } } // Get the entity types. $type_uris = wl_get_entity_rdf_types($entity_post->ID); // Support type are only schema.org ones: it could by null foreach ($type_uris as $type_uri) { $type_uri = wl_sparql_escape_uri($type_uri); $sparql .= "<{$uri_e}> a <{$type_uri}> . \n"; } // get related entities. $related_entities_ids = wl_core_get_related_entitY_ids($entity_post->ID); if (is_array($related_entities_ids)) { foreach ($related_entities_ids as $entity_post_id) { $related_entity_uri = wl_sparql_escape_uri(wl_get_entity_uri($entity_post_id)); // create a two-way relationship. $sparql .= " <{$uri_e}> dct:relation <{$related_entity_uri}> . \n"; $sparql .= " <{$related_entity_uri}> dct:relation <{$uri_e}> . \n"; } } // Add SPARQL stmts to write the schema:image. $sparql .= wl_get_sparql_images($uri, $entity_post->ID); $query = rl_sparql_prefixes() . <<<EOF {$delete_stmt} DELETE { <{$uri_e}> rdfs:label ?o } WHERE { <{$uri_e}> rdfs:label ?o }; DELETE { <{$uri_e}> owl:sameAs ?o . } WHERE { <{$uri_e}> owl:sameAs ?o . }; DELETE { <{$uri_e}> schema:description ?o . } WHERE { <{$uri_e}> schema:description ?o . }; DELETE { <{$uri_e}> schema:url ?o . } WHERE { <{$uri_e}> schema:url ?o . }; DELETE { <{$uri_e}> a ?o . } WHERE { <{$uri_e}> a ?o . }; DELETE { <{$uri_e}> dct:relation ?o . } WHERE { <{$uri_e}> dct:relation ?o . }; DELETE { <{$uri_e}> schema:image ?o . } WHERE { <{$uri_e}> schema:image ?o . }; DELETE { <{$uri_e}> geo:lat ?o . } WHERE { <{$uri_e}> geo:lat ?o . }; DELETE { <{$uri_e}> geo:long ?o . } WHERE { <{$uri_e}> geo:long ?o . }; INSERT DATA { {$sparql} }; EOF; rl_execute_sparql_update_query($query); }
/** * Fills up the microdata_template with entity's values. * * @param string $entity_id An entity ID. * @param string $entity_type Entity type stracture. * @param integer $recursion_level Recursion depth level in microdata compiling. Recursion depth limit is defined by WL_MAX_NUM_RECURSIONS_WHEN_PRINTING_MICRODATA constant. * * @return string The content with embedded microdata. */ function wl_content_embed_compile_microdata_template($entity_id, $entity_type, $recursion_level = 0) { wl_write_log("[ entity id :: {$entity_id} ][ entity type :: " . var_export($entity_type, true) . " ][ recursion level :: {$recursion_level} ]"); $regex = '/{{(.*?)}}/'; $matches = array(); if (null === $entity_type) { return ''; } $template = $entity_type['microdata_template']; // Return empty string if template fields have not been found. if (false === preg_match_all($regex, $template, $matches, PREG_SET_ORDER)) { return ''; } foreach ($matches as $match) { $placeholder = $match[0]; $field_name = $match[1]; // Get property value. $meta_collection = wl_schema_get_value($entity_id, $field_name); // If no value is given, just remove the placeholder from the template if (null == $meta_collection) { $template = str_replace($placeholder, '', $template); continue; } // What kind of value is it? // TODO: Performance issue here: meta type retrieving should be centralized $expected_type = wl_get_meta_type($field_name); foreach ($meta_collection as $field_value) { if (WL_DATA_TYPE_URI == $expected_type) { // If is a numeric value we assume it is an ID referencing for an internal entity. if (is_numeric($field_value)) { // Found id, get uri. $field_value = wl_get_entity_uri($field_value); } // Just if the linked entity does exist I can go further with template compiling $nested_entity = wl_get_entity_post_by_uri($field_value); if (!is_null($nested_entity)) { $content = '<span itemid="' . esc_attr($field_value) . '">' . $nested_entity->post_title . '</span>'; $compiled_template = wl_content_embed_item_microdata($content, $field_value, $field_name, ++$recursion_level); $template = str_replace($placeholder, $compiled_template, $template); } else { $template = str_replace($placeholder, '', $template); } continue; } // Standard condition: field containing a raw value $value = '<span itemprop="' . esc_attr($field_name) . '" content="' . esc_attr($field_value) . '"></span>'; $template = str_replace($placeholder, $value, $template); } } return $template; }
/** * Fills up the microdata_template with entity's values. * * @param string $entity_id An entity ID. * @param string $entity_type Entity type structure. * @param integer $recursion_level Recursion depth level in microdata compiling. Recursion depth limit is defined by WL_MAX_NUM_RECURSIONS_WHEN_PRINTING_MICRODATA constant. * * @return string The content with embedded microdata. */ function wl_content_embed_compile_microdata_template($entity_id, $entity_type, $recursion_level = 0) { global $wl_logger; if (WP_DEBUG) { $wl_logger->trace("Embedding microdata [ entity id :: {$entity_id} ][ entity type :: " . var_export($entity_type, true) . " ][ recursion level :: {$recursion_level} ]"); } $regex = '/{{(.*?)}}/'; $matches = array(); if (null === $entity_type) { return ''; } $template = $entity_type['microdata_template']; // Return empty string if template fields have not been found. if (false === preg_match_all($regex, $template, $matches, PREG_SET_ORDER)) { return ''; } foreach ($matches as $match) { $placeholder = $match[0]; $field_name = $match[1]; // Get property value. $meta_collection = wl_schema_get_value($entity_id, $field_name); // If no value is given, just remove the placeholder from the template if (null == $meta_collection) { $template = str_replace($placeholder, '', $template); continue; } // What kind of value is it? // TODO: Performance issue here: meta type retrieving should be centralized $expected_type = wl_get_meta_type($field_name); if (WP_DEBUG) { $wl_logger->trace("Embedding microdata [ placeholder :: {$placeholder} ][ field name :: {$field_name} ][ meta collection :: " . (is_array($meta_collection) ? var_export($meta_collection, true) : $meta_collection) . " ][ expected type :: {$expected_type} ]"); } foreach ($meta_collection as $field_value) { // Quick and dirty patch for #163: // - only apply to URIs, i.e. to properties pointing to another post ( $field_value should be a post ID ), // - check that $field_value is actually a number, // - check that the referenced post is published. // OR // - if the value is empty then we don't display it. if (Wordlift_Schema_Service::DATA_TYPE_URI === $expected_type && is_numeric($field_value) && 'publish' !== ($post_status = get_post_status($field_value)) || empty($field_value)) { if (WP_DEBUG) { $wl_logger->trace("Microdata refers to a non-published post [ field value :: {$field_value} ][ post status :: {$post_status} ]"); } // Remove the placeholder. $template = str_replace($placeholder, '', $template); continue; } if (Wordlift_Schema_Service::DATA_TYPE_URI == $expected_type) { // If is a numeric value we assume it is an ID referencing for an internal entity. if (is_numeric($field_value)) { // Found id, get uri. $field_value = wl_get_entity_uri($field_value); } // Just if the linked entity does exist I can go further with template compiling $nested_entity = wl_get_entity_post_by_uri($field_value); if (!is_null($nested_entity)) { $content = '<span itemid="' . esc_attr($field_value) . '">' . $nested_entity->post_title . '</span>'; $compiled_template = wl_content_embed_item_microdata($content, $field_value, $field_name, ++$recursion_level); $template = str_replace($placeholder, $compiled_template, $template); } else { $template = str_replace($placeholder, '', $template); } continue; } // Standard condition: field containing a raw value // For non visible test, schema.org dictates to use the *meta* tag. // see http://schema.org/docs/gs.html#advanced_missing $value = '<meta itemprop="' . esc_attr($field_name) . '" content="' . esc_attr($field_value) . '" />'; $template = str_replace($placeholder, $value, $template); } } return $template; }
/** * Get the coordinates for the specified post ID. * * @param int $post_id The post ID. * * @return array|null An array of coordinates or null. */ function wl_get_coordinates($post_id) { $latitude = wl_schema_get_value($post_id, 'latitude'); $longitude = wl_schema_get_value($post_id, 'longitude'); // Default coords values [0, 0] if (!isset($latitude[0]) || !is_numeric($latitude[0])) { $latitude = 0.0; } else { $latitude = floatval($latitude[0]); } if (!isset($longitude[0]) || !is_numeric($longitude[0])) { $longitude = 0.0; } else { $longitude = floatval($longitude[0]); } return array('latitude' => $latitude, 'longitude' => $longitude); }