/** * Sync the site to Redlink triple store and print out the post title being processed. */ function wl_admin_sync_to_redlink() { $posts = get_posts(array('post_type' => 'any', 'posts_per_page' => -1)); wl_write_log("wl_admin_sync_to_redlink [ post count :: " . sizeof($posts) . " ]"); foreach ($posts as $post) { echo esc_html($post->post_title) . '<br/>'; wl_linked_data_push_to_redlink($post->ID); } // Schedule the execution of SPARQL. wl_shutdown(); }
/** * Saves the values of wordlift metaboxes set in the entity editor page */ function wl_entity_metabox_save($post_id) { if (!isset($_POST['wl_metaboxes'])) { return; } // Loop over the wl_metaboxes array and save metaboxes values foreach ($_POST['wl_metaboxes'] as $meta_name => $meta_values) { // First, verify nonce is set for this meta $nonce_name = 'wordlift_' . $meta_name . '_entity_box_nonce'; $nonce_verify = 'wordlift_' . $meta_name . '_entity_box'; if (!isset($_POST[$nonce_name])) { return $post_id; } // Verify that the nonce is valid. if (!wp_verify_nonce($_POST[$nonce_name], $nonce_verify)) { return $post_id; } // Delete values before updating delete_post_meta($post_id, $meta_name); // Save the property value(s) if (isset($meta_name) && isset($meta_values) && $meta_values !== '') { // There can be one or more property values, so we force to array: if (!is_array($meta_values)) { $meta_values = array($meta_values); } foreach ($meta_values as $meta_value) { // If the meta expects an entity... $expecting_uri = wl_get_meta_type($meta_name) === WL_DATA_TYPE_URI; // ...and the user inputs an entity that is not present in the db... $absent_from_db = is_null(wl_get_entity_post_by_uri($meta_value)); // ...and that is not a external uri $name_is_uri = strpos($meta_value, 'http') === 0; if ($expecting_uri && $absent_from_db && !$name_is_uri) { // ...we create a new entity! $new_entity = wl_save_entity('', $meta_value, WL_ENTITY_TYPE_NAME, ''); // Assign type $constraints = wl_get_meta_constraints($meta_name); $type = 'http://schema.org/' . $constraints['uri_type']; wl_set_entity_main_type($new_entity->ID, $type); // TODO: directly publish the new entity // Update the value that will be saved as meta $meta_value = wl_get_entity_uri($new_entity->ID); } // TODO: use WL methods add_post_meta($post_id, $meta_name, $meta_value); } } } // Push changes on RedLink wl_linked_data_push_to_redlink($post_id); }
/** * Save the specified data as an entity in WordPress. This method only create new entities. When an existing entity is * found (by its URI), then the original post is returned. * * @param array $entity_properties, associative array containing: * string 'uri' The entity URI. * string 'label' The entity label. * string 'main_type_uri' The entity type URI. * string 'description' The entity description. * array 'type_uris' An array of entity type URIs. * array 'images' An array of image URLs. * int 'related_post_id' A related post ID. * array 'same_as' An array of sameAs URLs. * * @return null|WP_Post A post instance or null in case of failure. */ function wl_save_entity($entity_properties) { $uri = $entity_properties['uri']; $label = $entity_properties['label']; $type_uri = $entity_properties['main_type_uri']; $description = $entity_properties['description']; $entity_types = $entity_properties['type_uris']; $images = $entity_properties['images']; $related_post_id = $entity_properties['related_post_id']; $same_as = $entity_properties['same_as']; // Avoid errors due to null. if (is_null($entity_types)) { $entity_types = array(); } wl_write_log("[ uri :: {$uri} ][ label :: {$label} ][ type uri :: {$type_uri} ]"); // Prepare properties of the new entity. $params = array('post_status' => is_numeric($related_post_id) ? get_post_status($related_post_id) : 'draft', 'post_type' => WL_ENTITY_TYPE_NAME, 'post_title' => $label, 'post_content' => $description, 'post_excerpt' => ''); // Check whether an entity already exists with the provided URI. $post = wl_get_entity_post_by_uri($uri); if (null !== $post) { // We insert into the params the entity ID, so it will be updated and not inserted. $params['ID'] = $post->ID; } // create or update the post. $post_id = wp_insert_post($params, true); // TODO: handle errors. if (is_wp_error($post_id)) { wl_write_log(': error occurred'); // inform an error occurred. return null; } wl_set_entity_main_type($post_id, $type_uri); // Save the entity types. wl_set_entity_rdf_types($post_id, $entity_types); // Get a dataset URI for the entity. $wl_uri = wl_build_entity_uri($post_id); // Save the entity URI. wl_set_entity_uri($post_id, $wl_uri); // Add the uri to the sameAs data if it's not a local URI. if ($wl_uri !== $uri) { array_push($same_as, $uri); } $new_uri = wl_get_entity_uri($post_id); // Save the sameAs data for the entity. wl_schema_set_value($post_id, 'sameAs', $same_as); // Call hooks. do_action('wl_save_entity', $post_id); wl_write_log("[ post id :: {$post_id} ][ uri :: {$uri} ][ label :: {$label} ][ wl uri :: {$wl_uri} ][ types :: " . implode(',', $entity_types) . " ][ images count :: " . count($images) . " ][ same_as count :: " . count($same_as) . " ]"); foreach ($images as $image_remote_url) { // Check if image is already present in local DB if (strpos($image_remote_url, site_url()) !== false) { // Do nothing. continue; } // Check if there is an existing attachment for this post ID and source URL. $existing_image = wl_get_attachment_for_source_url($post_id, $image_remote_url); // Skip if an existing image is found. if (null !== $existing_image) { continue; } // Save the image and get the local path. $image = wl_save_image($image_remote_url); // Get the local URL. $filename = $image['path']; $url = $image['url']; $content_type = $image['content_type']; $attachment = array('guid' => $url, 'post_title' => $label, 'post_content' => '', 'post_status' => 'inherit', 'post_mime_type' => $content_type); // Create the attachment in WordPress and generate the related metadata. $attachment_id = wp_insert_attachment($attachment, $filename, $post_id); // Set the source URL for the image. wl_set_source_url($attachment_id, $image_remote_url); $attachment_data = wp_generate_attachment_metadata($attachment_id, $filename); wp_update_attachment_metadata($attachment_id, $attachment_data); // Set it as the featured image. set_post_thumbnail($post_id, $attachment_id); } // The entity is pushed to Redlink on save by the function hooked to save_post. // save the entity in the triple store. wl_linked_data_push_to_redlink($post_id); // finally return the entity post. return get_post($post_id); }
/** * Save the specified data as an entity in WordPress. This method only create new entities. When an existing entity is * found (by its URI), then the original post is returned. * * @param array $entity_data, associative array containing: * string 'uri' The entity URI. * string 'label' The entity label. * string 'main_type' The entity type URI. * array 'type' An array of entity type URIs. * string 'description' The entity description. * array 'images' An array of image URLs. * int 'related_post_id' A related post ID. * array 'same_as' An array of sameAs URLs. * * @return null|WP_Post A post instance or null in case of failure. */ function wl_save_entity($entity_data) { $uri = $entity_data['uri']; $label = $entity_data['label']; $type_uri = $entity_data['main_type']; $entity_types = isset($entity_data['type']) ? $entity_data['type'] : array(); $description = $entity_data['description']; $images = isset($entity_data['image']) ? wl_force_to_array($entity_data['image']) : array(); $same_as = isset($entity_data['sameas']) ? wl_force_to_array($entity_data['sameas']) : array(); $related_post_id = isset($entity_data['related_post_id']) ? $entity_data['related_post_id'] : null; $other_properties = isset($entity_data['properties']) ? $entity_data['properties'] : array(); // wl_write_log( "[ uri :: $uri ][ label :: $label ][ type uri :: $type_uri ]" ); // Prepare properties of the new entity. $params = array('post_status' => is_numeric($related_post_id) ? get_post_status($related_post_id) : 'draft', 'post_type' => Wordlift_Entity_Service::TYPE_NAME, 'post_title' => $label, 'post_content' => $description, 'post_excerpt' => ''); // Check whether an entity already exists with the provided URI. $post = wl_get_entity_post_by_uri($uri); if (null !== $post) { // We insert into the params the entity ID, so it will be updated and not inserted. $params['ID'] = $post->ID; // Preserve the current entity status if ('public' === $post->post_status) { $params['post_status'] = $post->post_status; } // Preserve the current entity post_content. $params['post_content'] = $post->post_content; // Preserve the entity post_title to avoid de-synch between WP and RL // See: https://github.com/insideout10/wordlift-plugin/issues/221 $params['post_title'] = $post->post_title; } // If Yoast is installed and active, we temporary remove the save_postdata hook which causes Yoast to "pass over" // the local SEO form values to the created entity (https://github.com/insideout10/wordlift-plugin/issues/156) // Same thing applies to SEO Ultimate (https://github.com/insideout10/wordlift-plugin/issues/148) // This does NOT affect saving an entity from the entity admin page since this function is called when an entity // is created when saving a post. global $wpseo_metabox, $seo_ultimate; if (isset($wpseo_metabox)) { remove_action('wp_insert_post', array($wpseo_metabox, 'save_postdata')); } if (isset($seo_ultimate)) { remove_action('save_post', array($seo_ultimate, 'save_postmeta_box')); } // The fact that we're calling here wp_insert_post is causing issues with plugins (and ourselves too) that hook to // save_post in order to save additional inputs from the edit page. In order to avoid issues, we pop all the hooks // to the save_post and restore them after we saved the entity. // see https://github.com/insideout10/wordlift-plugin/issues/203 // see https://github.com/insideout10/wordlift-plugin/issues/156 // see https://github.com/insideout10/wordlift-plugin/issues/148 global $wp_filter; $save_post_filters = $wp_filter['save_post']; $wp_filter['save_post'] = array(); // create or update the post. $post_id = wp_insert_post($params, true); // Restore all the existing filters. $wp_filter['save_post'] = $save_post_filters; // If Yoast is installed and active, we restore the Yoast save_postdata hook (https://github.com/insideout10/wordlift-plugin/issues/156) if (isset($wpseo_metabox)) { add_action('wp_insert_post', array($wpseo_metabox, 'save_postdata')); } // If SEO Ultimate is installed, add back the hook we removed a few lines above. if (isset($seo_ultimate)) { add_action('save_post', array($seo_ultimate, 'save_postmeta_box'), 10, 2); } // TODO: handle errors. if (is_wp_error($post_id)) { wl_write_log(': error occurred'); // inform an error occurred. return null; } wl_set_entity_main_type($post_id, $type_uri); // Save the entity types. wl_set_entity_rdf_types($post_id, $entity_types); // Get a dataset URI for the entity. $wl_uri = wl_build_entity_uri($post_id); // Save the entity URI. wl_set_entity_uri($post_id, $wl_uri); // Add the uri to the sameAs data if it's not a local URI. if ($wl_uri !== $uri) { array_push($same_as, $uri); } $new_uri = wl_get_entity_uri($post_id); // Save the sameAs data for the entity. wl_schema_set_value($post_id, 'sameAs', $same_as); // Save the other properties (latitude, langitude, startDate, endDate, etc.) foreach ($other_properties as $property_name => $property_value) { wl_schema_set_value($post_id, $property_name, $property_value); } // Call hooks. do_action('wl_save_entity', $post_id); wl_write_log("[ post id :: {$post_id} ][ uri :: {$uri} ][ label :: {$label} ][ wl uri :: {$wl_uri} ][ types :: " . implode(',', $entity_types) . " ][ images count :: " . count($images) . " ][ same_as count :: " . count($same_as) . " ]"); foreach ($images as $image_remote_url) { // Check if image is already present in local DB if (strpos($image_remote_url, site_url()) !== false) { // Do nothing. continue; } // Check if there is an existing attachment for this post ID and source URL. $existing_image = wl_get_attachment_for_source_url($post_id, $image_remote_url); // Skip if an existing image is found. if (null !== $existing_image) { continue; } // Save the image and get the local path. $image = wl_save_image($image_remote_url); // Get the local URL. $filename = $image['path']; $url = $image['url']; $content_type = $image['content_type']; $attachment = array('guid' => $url, 'post_title' => $label, 'post_content' => '', 'post_status' => 'inherit', 'post_mime_type' => $content_type); // Create the attachment in WordPress and generate the related metadata. $attachment_id = wp_insert_attachment($attachment, $filename, $post_id); // Set the source URL for the image. wl_set_source_url($attachment_id, $image_remote_url); $attachment_data = wp_generate_attachment_metadata($attachment_id, $filename); wp_update_attachment_metadata($attachment_id, $attachment_data); // Set it as the featured image. set_post_thumbnail($post_id, $attachment_id); } // The entity is pushed to Redlink on save by the function hooked to save_post. // save the entity in the triple store. wl_linked_data_push_to_redlink($post_id); // finally return the entity post. return get_post($post_id); }
/** * Test saving entities passed via a metabox. */ function testEntitiesViaArray() { // Create a post. $post_id = $this->createPost(); $this->assertTrue(is_numeric($post_id)); $post = get_post($post_id); $this->assertNotNull($post); // Read the entities from the mock-up analysis. $analysis_results = wl_parse_file(dirname(__FILE__) . '/' . self::FILENAME . '.json'); $this->assertTrue(is_array($analysis_results)); // For each entity get the label, type, description and thumbnails. $this->assertTrue(isset($analysis_results['entities'])); // Get a reference to the entities. $text_annotations = $analysis_results['text_annotations']; $best_entities = array(); foreach ($text_annotations as $id => $text_annotation) { $entity_annotation = wl_get_entity_annotation_best_match($text_annotation['entities']); $entity = $entity_annotation['entity']; $entity_id = $entity->{'@id'}; if (!array_key_exists($entity_id, $best_entities)) { $best_entities[$entity_id] = $entity; } } // Accumulate the entities in an array. $entities = array(); foreach ($best_entities as $uri => $entity) { // Label if (!isset($entity->{'http://www.w3.org/2000/01/rdf-schema#label'}->{'@value'})) { var_dump($entity); } $this->assertTrue(isset($entity->{'http://www.w3.org/2000/01/rdf-schema#label'}->{'@value'})); $label = $entity->{'http://www.w3.org/2000/01/rdf-schema#label'}->{'@value'}; $this->assertFalse(empty($label)); // Type // $type = wl_get_entity_type($entity); // $this->assertFalse(empty($type)); // Description $description = wl_get_entity_description($entity); $this->assertNotNull($description); // Images $images = wl_get_entity_thumbnails($entity); $this->assertTrue(is_array($images)); // Save the entity to the entities array. $entities = array_merge_recursive($entities, array($uri => array('uri' => $uri, 'label' => $label, 'main_type' => 'http://schema.org/Thing', 'type' => array(), 'description' => $description, 'images' => $images))); } // Save the entities in the array. $entity_posts = wl_save_entities($entities); // Publish $entity_post_ids = array_map(function ($item) { return $item->ID; }, $entity_posts); foreach ($entity_post_ids as $entity_id) { wp_publish_post($entity_id); } // TODO: need to bind entities with posts. wl_core_add_relation_instances($post_id, WL_WHAT_RELATION, $entity_post_ids); $this->assertCount(sizeof($entity_post_ids), wl_core_get_related_entity_ids($post_id)); // TODO: synchronize data. // NOTICE: this requires a published post! wl_linked_data_push_to_redlink($post_id); // Check that the entities are created in WordPress. $this->assertCount(count($entities), $entity_posts); // Check that each entity is bound to the post. $entity_ids = array(); foreach ($entity_posts as $post) { // Store the entity IDs for future checks. array_push($entity_ids, $post->ID); // Get the related posts IDs. $rel_posts = wl_core_get_related_post_ids($post->ID); $this->assertCount(1, $rel_posts); // The post must be the one the test created. $this->assertEquals($post_id, $rel_posts[0]); } // Check that the post references the entities. $rel_entities = wl_core_get_related_entity_ids($post_id); $this->assertEquals(count($entity_ids), count($rel_entities)); foreach ($entity_ids as $id) { $this->assertTrue(in_array($id, $rel_entities)); } // Check that the locally saved entities and the remotely saved ones match. $this->checkEntities($entity_posts); // Check that the locally saved post data match the ones on Redlink. $this->checkPost($post_id); // Check the post references, that they match between local and remote. $this->checkPostReferences($post_id); // Delete the post. $this->deletePost($post_id); }
public function save_form_data($entity_id) { // Build Field objects $this->instantiate_fields($entity_id); // Check if WL metabox form was posted if (!isset($_POST['wl_metaboxes'])) { return; } foreach ($this->fields as $field) { // Verify nonce $valid_nonce = $field->verify_nonce(); if ($valid_nonce) { $posted_data = $_POST['wl_metaboxes']; $field_name = $field->meta_name; // Each Filed only deals with its values. if (isset($posted_data[$field_name])) { $values = $posted_data[$field_name]; if (!is_array($values)) { $values = array($values); } // Save data permanently $field->save_data($values); } } } wl_linked_data_push_to_redlink($entity_id); }