/** * Install known types in WordPress. */ function wl_core_install_create_relation_instance_table() { global $wpdb; // global $wl_db_version; $installed_version = get_option("wl_db_version"); if ($installed_version != WL_DB_VERSION) { $table_name = $wpdb->prefix . WL_DB_RELATION_INSTANCES_TABLE_NAME; $charset_collate = $wpdb->get_charset_collate(); // Sql statement for the relation instances custom table $sql = <<<EOF \t\t\tCREATE TABLE {$table_name} ( \t\t\t\tid int(11) NOT NULL AUTO_INCREMENT, \t\t\t\tsubject_id int(11) NOT NULL, \t\t\t\tpredicate char(10) NOT NULL, \t\t\t\tobject_id int(11) NOT NULL, \t\t\t\tUNIQUE KEY id (id), \t\t\t\tKEY subject_id_index (subject_id), \t\t\t\tKEY object_id_index (object_id) \t\t\t) {$charset_collate}; EOF; // @see: https://codex.wordpress.org/Creating_Tables_with_Plugins require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $results = dbDelta($sql); wl_write_log($results); update_option("wl_db_version", WL_DB_VERSION); } }
function wordlift_ajax_related_posts($http_raw_data = null) { // Extract filtering conditions if (!isset($_GET["post_id"]) || !is_numeric($_GET["post_id"])) { wp_die('Post id missing or invalid!'); return; } $post_id = $_GET["post_id"]; // Get the current post $post = get_post($post_id); wl_write_log("Going to find posts related to current with post id: {$post_id} ..."); // Extract filtering conditions $filtering_entity_uris = null == $http_raw_data ? file_get_contents("php://input") : $http_raw_data; $filtering_entity_uris = json_decode($filtering_entity_uris); $filtering_entity_ids = wl_get_entity_post_ids_by_uris($filtering_entity_uris); $related_posts = array(); // If the current post is an antity // related posts to the current entity are returned if (Wordlift_Entity_Service::TYPE_NAME == $post->post_type) { $filtering_entity_ids = array($post_id); } if (!empty($filtering_entity_ids)) { $related_posts = wl_core_get_posts(array('get' => 'posts', 'related_to__in' => $filtering_entity_ids, 'post__not_in' => array($post_id), 'post_type' => 'post', 'post_status' => 'publish', 'as' => 'subject')); foreach ($related_posts as $post_obj) { $thumbnail = wp_get_attachment_url(get_post_thumbnail_id($post_obj->ID, 'thumbnail')); $post_obj->thumbnail = $thumbnail ? $thumbnail : WL_DEFAULT_THUMBNAIL_PATH; $post_obj->link = get_edit_post_link($post_obj->ID, 'none'); $post_obj->permalink = get_post_permalink($post_obj->ID); } } wl_core_send_json($related_posts); }
/** * Execute a query on Redlink. * * @since 3.0.0 * * @uses wl_queue_sparql_update_query() to queue a query if query buffering is on. * * @param string $query The query to execute. * @param bool $queue Whether to queue the update. * * @return bool True if successful otherwise false. */ function rl_execute_sparql_update_query($query, $queue = WL_ENABLE_SPARQL_UPDATE_QUERIES_BUFFERING) { // Get the calling function for debug purposes. $callers = debug_backtrace(); $calling_function = $callers[1]['function']; wl_write_log("[ calling function :: {$calling_function} ][ queue :: " . ($queue ? 'true' : 'false') . ' ]'); // Queue the update query. if ($queue) { wl_queue_sparql_update_query($query); return true; } // Get the update end-point. $url = wl_configuration_get_query_update_url(); // Prepare the request. $args = array_merge_recursive(unserialize(WL_REDLINK_API_HTTP_OPTIONS), array('method' => 'POST', 'headers' => array('Accept' => 'application/json', 'Content-type' => 'application/sparql-update; charset=utf-8'), 'body' => $query)); // Send the request. $response = wp_remote_post($url, $args); // If an error has been raised, return the error. if (is_wp_error($response) || 200 !== (int) $response['response']['code']) { $body = is_wp_error($response) ? $response->get_error_message() : $response['body']; wl_write_log("rl_execute_sparql_update_query : error [ url :: {$url} ][ args :: "); wl_write_log("\n" . var_export($args, true)); wl_write_log("[ response :: "); wl_write_log("\n" . var_export($response, true)); wl_write_log("][ body :: "); wl_write_log("\n" . $body); wl_write_log("]"); return false; } wl_write_log("rl_execute_sparql_query [ url :: {$url} ][ response code :: " . $response['response']['code'] . " ][ query :: "); wl_write_log("\n" . $query); wl_write_log("]"); return true; }
/** * Retrieve timeline events. * * @uses wl_core_get_related_entity_ids() to retrieve the entities referenced by the specified post. * * @param int $post_id The post ID. * @return array An array of event posts. */ function wl_shortcode_timeline_get_events($post_id = null) { // Build list of event-entities. if (is_null($post_id) || !is_numeric($post_id)) { // Global timeline. Get entities from the latest posts. $latest_posts_ids = get_posts(array('numberposts' => 50, 'fields' => 'ids', 'post_type' => 'post', 'post_status' => 'publish')); if (empty($latest_posts_ids)) { // There are no posts. return array(); } // Collect entities related to latest posts $entity_ids = array(); foreach ($latest_posts_ids as $id) { $entity_ids = array_merge($entity_ids, wl_core_get_related_entity_ids($id, array('status' => 'publish'))); } if (empty($entity_ids)) { return array(); } } else { // Post-specific timeline. Search for entities in the post itself. $entity_ids = wl_core_get_related_entity_ids($post_id); } wl_write_log("wl_shortcode_timeline_get_events [ entity IDs :: " . join(', ', $entity_ids) . " ]"); return get_posts(array('post__in' => $entity_ids, 'post_type' => WL_ENTITY_TYPE_NAME, 'post_status' => 'publish', 'posts_per_page' => -1, 'meta_query' => array('relation' => 'AND', array('key' => WL_CUSTOM_FIELD_CAL_DATE_START, 'value' => null, 'compare' => '!='), array('key' => WL_CUSTOM_FIELD_CAL_DATE_END, 'value' => null, 'compare' => '!=')))); }
/** * Execute a query on Redlink. * * @since 3.0.0 * * @uses wl_queue_sparql_update_query() to queue a query if query buffering is on. * * @param string $query The query to execute. * @param bool $queue Whether to queue the update. * * @return bool True if successful otherwise false. */ function rl_execute_sparql_update_query($query, $queue = WL_ENABLE_SPARQL_UPDATE_QUERIES_BUFFERING) { // Queue the update query. if ($queue) { if (WP_DEBUG) { global $wl_logger; $wl_logger->trace("Buffering a query [ query :: {$query} ]"); } wl_queue_sparql_update_query($query); return true; } // Get the update end-point. $url = wl_configuration_get_query_update_url(); // Prepare the request. $args = array_merge_recursive(unserialize(WL_REDLINK_API_HTTP_OPTIONS), array('method' => 'POST', 'headers' => array('Accept' => 'application/json', 'Content-type' => 'application/sparql-update; charset=utf-8'), 'body' => $query)); // Send the request. $response = wp_remote_post($url, $args); // If an error has been raised, return the error. if (is_wp_error($response) || 200 !== (int) $response['response']['code']) { $body = is_wp_error($response) ? $response->get_error_message() : $response['body']; wl_write_log("rl_execute_sparql_update_query : error [ url :: {$url} ][ args :: "); wl_write_log("\n" . var_export($args, true)); wl_write_log("[ response :: "); wl_write_log("\n" . var_export($response, true)); wl_write_log("][ body :: "); wl_write_log("\n" . $body); wl_write_log("]"); return false; } if (WP_DEBUG) { global $wl_logger; $wl_logger->trace("Query executed successfully [ query :: {$query} ]"); } return true; }
/** * Get list of posts that will populate the navigator. * * @param int $post_id Id of the post. * * @return Array List of tuples organized in this way: * Array( * [0] => Array( * [0] => related post Object * [1] => related entity Object (main post and the post above are related via this entity) * ) * [1] => another tuple [2] => ... * ) */ function wordlift_shortcode_navigator_populate($post_id) { // prepare structures to memorize other related posts $related_posts_ids = array(); $related_posts = array(); // get the related entities, ordered by WHO-WHAT-WHERE-WHEN (as established the 29/7/2015 12:45 in the grottino) // TODO: should be a single query $related_entities = wl_core_get_related_entities($post_id, array('predicate' => WL_WHO_RELATION, 'status' => 'publish')); $related_entities = array_merge($related_entities, wl_core_get_related_entities($post_id, array('predicate' => WL_WHAT_RELATION, 'status' => 'publish'))); $related_entities = array_merge($related_entities, wl_core_get_related_entities($post_id, array('predicate' => WL_WHERE_RELATION, 'status' => 'publish'))); $related_entities = array_merge($related_entities, wl_core_get_related_entities($post_id, array('predicate' => WL_WHEN_RELATION, 'status' => 'publish'))); foreach ($related_entities as $rel_entity) { wl_write_log("Looking for posts related to entity {$rel_entity->ID}"); // take the id of posts referencing the entity $referencing_posts = wl_core_get_related_posts($rel_entity->ID, array('status' => 'publish')); // loop over them and take the first one which is not already in the $related_posts foreach ($referencing_posts as $referencing_post) { if (!in_array($referencing_post->ID, $related_posts_ids) && $referencing_post->ID != $post_id) { $related_posts_ids[] = $referencing_post->ID; $related_posts[] = array($referencing_post, $rel_entity); } } } wl_write_log("Related posts for {$post_id}"); wl_write_log($related_posts); return $related_posts; }
/** * 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(); }
/** * Save extra taxonomy fields callback function. */ function wl_entity_type_taxonomy_save_custom_meta($term_id) { if (isset($_POST['term_meta'])) { // Get the values for the term. $css_class = $_POST['term_meta']['css_class']; $uri = $_POST['term_meta']['uri']; $same_as = !empty($_POST['term_meta']['same_as']) ? preg_split("/\\r\\n|\\r|\\n/", $_POST['term_meta']['same_as']) : array(); // Update the term data. wl_entity_type_taxonomy_update_term($term_id, $css_class, $uri, $same_as); wl_write_log("wl_entity_type_save_taxonomy_custom_meta [ term id :: {$term_id} ]"); } }
/** * Save the image with the specified URL locally. To the local filename a uniqe serial is appended to ensure its uniqueness. * * @param string $url The image remote URL. * * @return array An array with information about the saved image (*path*: the local path to the image, *url*: the local * url, *content_type*: the image content type) */ function wl_save_image($url) { $parts = parse_url($url); $path = $parts['path']; // Get the bare filename (filename w/o the extension). // Sanitize filename before saving the current image as attachment // See https://codex.wordpress.org/Function_Reference/sanitize_file_name $basename = sanitize_file_name(pathinfo($path, PATHINFO_FILENAME) . '-' . uniqid(date('YmdH-'))); // Chunk the bare name to get a subpath. $chunks = chunk_split(strtolower($basename), 3, DIRECTORY_SEPARATOR); // Get the base dir. $wp_upload_dir = wp_upload_dir(); $base_dir = $wp_upload_dir['basedir']; $base_url = $wp_upload_dir['baseurl']; // Get the full path to the local filename. $image_path = '/' . $chunks; $image_full_path = $base_dir . $image_path; $image_full_url = $base_url . $image_path; // Create the folders. if (!(file_exists($image_full_path) && is_dir($image_full_path))) { if (false === mkdir($image_full_path, 0777, true)) { wl_write_log("wl_save_image : failed creating dir [ image full path :: {$image_full_path} ]\n"); } } // Request the remote file. $response = wp_remote_get($url); $content_type = wp_remote_retrieve_header($response, 'content-type'); switch ($content_type) { case 'image/jpeg': case 'image/jpg': $extension = ".jpg"; break; case 'image/svg+xml': $extension = ".svg"; break; case 'image/gif': $extension = ".gif"; break; case 'image/png': $extension = ".png"; break; default: $extension = ''; } // Complete the local filename. $image_full_path .= $basename . $extension; $image_full_url .= $basename . $extension; // Store the data locally. file_put_contents($image_full_path, wp_remote_retrieve_body($response)); // wl_write_log( "wl_save_image [ url :: $url ][ content type :: $content_type ][ image full path :: $image_full_path ][ image full url :: $image_full_url ]\n" ); // Return the path. return array('path' => $image_full_path, 'url' => $image_full_url, 'content_type' => $content_type); }
/** * Removes empty text annotations from the post content. * * @since 1.0.0 * * @param array $data The post data. * * @return array mixed The post data array. */ function wl_remove_text_annotations($data) { // <span class="textannotation" id="urn:enhancement-777cbed4-b131-00fb-54a4-ed9b26ae57ea"> // $pattern = '/<span class=\\\"textannotation\\\" id=\\\"[^\"]+\\\">([^<]+)<\/span>/i'; $pattern = '/<(\\w+)[^>]*\\sclass=\\\\"textannotation\\\\"[^>]*>([^<]+)<\\/\\1>/im'; wl_write_log("Removing text annotations [ pattern :: {$pattern} ]"); // Remove the pattern while it is found (match nested annotations). while (1 === preg_match($pattern, $data['post_content'])) { $data['post_content'] = preg_replace($pattern, '$2', $data['post_content'], -1, $count); } return $data; }
/** * Remove a given relation instance * @uses $wpdb->delete() to perform the query * * @param int $subject_id The post ID | The entity post ID. * @param string $predicate Name of the relation: 'what' | 'where' | 'when' | 'who' * @param int $object_id The entity post ID. * * @return (boolean) False for failure. True for success. */ function wl_core_delete_relation_instance($subject_id, $predicate, $object_id) { // Checks on subject and object if (!is_numeric($subject_id) || !is_numeric($object_id)) { return false; } // Checks on the given relation if (!wl_core_check_relation_predicate_is_supported($predicate)) { return false; } // Prepare interaction with db global $wpdb; wl_write_log("Going to delete relation instace [ subject_id :: {$subject_id} ] [ object_id :: {$object_id} ] [ predicate :: {$predicate} ]"); // @see ttps://codex.wordpress.org/it:Riferimento_classi/wpdb#DELETE_di_righe $wpdb->delete(wl_core_get_relation_instances_table_name(), array('subject_id' => $subject_id, 'predicate' => $predicate, 'object_id' => $object_id), array('%d', '%s', '%d')); return true; }
/** * Build the entity URI given the entity's post. * * @uses wl_sanitize_uri_path() to sanitize the post title. * @uses wl_configuration_get_redlink_dataset_uri() to get the dataset base URI. * * @param int $post_id The post ID * * @return string The URI of the entity */ function wl_build_entity_uri($post_id) { // Get the post. $post = get_post($post_id); if (null === $post) { wl_write_log("wl_build_entity_uri : error [ post ID :: {$post_id} ][ post :: null ]"); return null; } // Create an ID given the title. $path = wl_sanitize_uri_path($post->post_title); // If the path is empty, i.e. there's no title, use the post ID as path. if (empty($path)) { $path = "id/{$post->ID}"; } // Create the URL (dataset base URI has a trailing slash). $url = sprintf('%s/%s/%s', wl_configuration_get_redlink_dataset_uri(), $post->post_type, $path); // wl_write_log( "wl_build_entity_uri [ post_id :: $post->ID ][ type :: $post->post_type ][ title :: $post->post_title ][ url :: $url ]" ); return $url; }
/** * Embed the entity properties as microdata in the content. * * @param string $content A content. * @param string $uri An entity URI. * @param string $itemprop Specifies which property this entity is for another entity. Useful for recursive markup. * * @return string The content with embedded microdata. */ function wl_content_embed_item_microdata($content, $uri, $itemprop = null, $recursion_level = 0) { if ($recursion_level > wl_config_get_recursion_depth()) { wl_write_log("recursion depth limit exceeded [ level :: {$recursion_level} ][ max :: " . wl_config_get_recursion_depth() . " ]"); return ''; } $post = wl_get_entity_post_by_uri($uri); // Entity not found or not published. Delete <span> tags but leave their content on page. if (null === $post || $post->post_status !== 'publish') { // wl_write_log( "wl_content_embed_item_microdata : entity not found or not published [ uri :: $uri ]" ); // Replace the original tagging with the new tagging. $regex = wl_content_embed_build_regex_from_uri($uri); $content = preg_replace($regex, '$2', $content); return $content; } // Get the entity URI and its escaped version for the regex. $entity_uri = wl_get_entity_uri($post->ID); // Get the main type. $main_type = wl_entity_type_taxonomy_get_type($post->ID); // Set the item type if available. $item_type = null === $main_type ? '' : ' itemtype="' . esc_attr($main_type['uri']) . '"'; // Define attribute itemprop if this entity is nested. if (!is_null($itemprop)) { $itemprop = ' itemprop="' . $itemprop . '"'; } // Get additional properties (this may imply a recursion of this method on a sub-entity). $additional_properties = wl_content_embed_compile_microdata_template($post->ID, $main_type, $recursion_level); $same_as = ''; // Get the array of sameAs uris. $same_as_uris = wl_schema_get_value($post->ID, 'sameAs'); // Prepare the sameAs fragment. foreach ($same_as_uris as $same_as_uri) { $same_as .= "<link itemprop=\"sameAs\" href=\"{$same_as_uri}\">"; } // Get the entity URL. $permalink = get_permalink($post->ID); $url = '<link itemprop="url" href="' . $permalink . '" />'; // Replace the original tagging with the new tagging. $regex = wl_content_embed_build_regex_from_uri($uri); $content = preg_replace($regex, '<$1' . $itemprop . ' itemscope' . $item_type . ' itemid="' . esc_attr($entity_uri) . '">' . $same_as . $additional_properties . $url . '<a class="wl-entity-page-link" href="' . $permalink . '" itemprop="name" content="' . $post->post_title . '">' . (is_null($itemprop) ? '$2' : '') . '</a></$1>', $content); // wl_write_log( "wl_content_embed_item_microdata [ uri :: $uri ][ regex :: $regex ]" ); return $content; }
public function test_shortcode_chord_ajax() { // TODO: fix content-type tests. $this->markTestSkipped('Content Type tests are failing, needs fix'); if (!function_exists('xdebug_get_headers')) { $this->markTestSkipped('xdebug is required for this test'); } $post_id = wl_create_post('This is Post 1', 'post-1', 'Post 1', 'publish'); $entity_1_id = wl_create_post('This is Entity 1', 'entity-1', 'Entity 1', 'publish', 'entity'); wl_set_entity_main_type($entity_1_id, 'http://schema.org/Thing'); $entity_2_id = wl_create_post('This is Entity 2', 'entity-2', 'Entity 2', 'publish', 'entity'); wl_set_entity_main_type($entity_2_id, 'http://schema.org/Thing'); wl_core_add_relation_instances($post_id, WL_WHAT_RELATION, array($entity_1_id, $entity_2_id)); $_REQUEST['post_id'] = $post_id; $_REQUEST['depth'] = 3; ob_start(); wl_shortcode_chord_ajax(); $headers = xdebug_get_headers(); ob_end_clean(); wl_write_log($headers); $this->assertTrue(in_array('Content-Type: application/json', $headers)); }
/** * Analyze the provided content. The analysis will make use of the method *wl_ajax_analyze_action* * provided by the WordLift plugin. * * @since 1.0.0 * * @uses wl_configuration_get_analyzer_url() to get the API for the analysis. * * @param string $content The content to analyze. * * @return string Returns null on failure, or the WP_Error, or a WP_Response with the response. */ function wl_analyze_content($content) { // Get the analyzer URL. $url = wl_configuration_get_analyzer_url(); // Prepare the request. $args = array_merge_recursive(unserialize(WL_REDLINK_API_HTTP_OPTIONS), array('method' => 'POST', 'headers' => array('Accept' => 'application/json', 'Content-type' => 'text/plain'), 'httpversion' => '1.0', 'body' => $content)); $response = wp_remote_post($url, $args); // If an error has been raised, return the error. if (is_wp_error($response) || 200 !== (int) $response['response']['code']) { $body = is_wp_error($response) ? $response->get_error_message() : $response['body']; wl_write_log("error [ url :: {$url} ][ args :: "); wl_write_log(var_export($args, true)); wl_write_log('][ response :: '); wl_write_log("\n" . var_export($response, true)); wl_write_log("][ body :: "); wl_write_log("\n" . $body); wl_write_log("]"); return null; } wl_write_log("[ url :: {$url} ][ response code :: " . $response['response']['code'] . " ]"); return $response['body']; }
function prepareFakeGlobalPostArrayFromFile($fileName) { $json_data = file_get_contents(dirname(__FILE__) . $fileName); $json_data = preg_replace('/{{REDLINK_ENDPOINT}}/', wl_configuration_get_redlink_dataset_uri(), $json_data); wl_write_log($json_data); $data = json_decode($json_data, true); return $data; }
/** * Execute the provided query against the SPARQL SELECT Redlink end-point and return the response. * * @param string $query A SPARQL query. * @param string $accept The mime type for the response format (default = 'text/csv'). * * @return WP_Response|WP_Error A WP_Response instance in successful otherwise a WP_Error. */ function rl_sparql_select($query) { // Prepare the SPARQL statement by prepending the default namespaces. $sparql = rl_sparql_prefixes() . "\n" . $query; // Get the SPARQL SELECT URL. $url = wl_configuration_get_query_select_url('csv') . urlencode($sparql); // Prepare the request. $args = unserialize(WL_REDLINK_API_HTTP_OPTIONS); // Send the request. wl_write_log("SPARQL Select [ sparql :: {$sparql} ][ url :: {$url} ][ args :: " . var_export($args, true) . " ]"); return wp_remote_get($url, $args); }
/** * Optimize and convert retrieved content to JSON. * * @used-by wl_shortcode_chord_ajax * * @param $data * @return mixed|string|void */ function wl_shortcode_chord_get_graph($data) { // Refactor the entities array in order to provide entities relevant data (uri, url, label, type, css_class). array_walk($data['entities'], function (&$item) { $post = get_post($item); // Skip non-existing posts. if (is_null($post)) { wl_write_log("wl_shortcode_chord_get_graph : post not found [ post id :: {$item} ]"); return $item; } // Get the entity taxonomy bound to this post (if there's no taxonomy, no stylesheet will be set). $term = wl_entity_type_taxonomy_get_type($item); wl_write_log("wl_shortcode_chord_get_graph [ post id :: {$post->ID} ][ term :: " . var_export($term, true) . " ]"); $entity = array('uri' => wl_get_entity_uri($item), 'url' => get_permalink($item), 'label' => $post->post_title, 'type' => $post->post_type, 'thumbnails' => wl_get_image_urls($post->ID), 'css_class' => isset($term['css_class']) ? $term['css_class'] : ''); $item = $entity; }); // Refactor the relations. array_walk($data['relations'], function (&$item) { $relation = array('s' => wl_get_entity_uri($item[0]), 'o' => wl_get_entity_uri($item[1])); $item = $relation; }); // Return the JSON representation. return $data; }
/** * Displays the meta box contents (called by *add_meta_box* callback). * * @param WP_Post $post The current post. */ function wl_entities_box_content($post) { wl_write_log("wl_entities_box_content [ post id :: {$post->ID} ]"); // Angularjs edit-post widget wrapper echo '<div id="wordlift-edit-post-outer-wrapper"></div>'; // Angularjs edit-post widget classification boxes configuration $classification_boxes = unserialize(WL_CORE_POST_CLASSIFICATION_BOXES); // Array to store all related entities ids $all_referenced_entities_ids = array(); // Add selected entities to classification_boxes foreach ($classification_boxes as $i => $box) { // Build the proper relation name $relation_name = $box['id']; wl_write_log("Going to related of {$relation_name}"); // Get entity ids related to the current post for the given relation name (both draft and published entities) $draft_entity_ids = wl_core_get_related_entity_ids($post->ID, array('predicate' => $relation_name, 'status' => 'draft')); $publish_entity_ids = wl_core_get_related_entity_ids($post->ID, array('predicate' => $relation_name, 'status' => 'publish')); $entity_ids = array_unique(array_merge($draft_entity_ids, $publish_entity_ids)); // Store the entity ids for all the 4W $all_referenced_entities_ids = array_merge($all_referenced_entities_ids, $entity_ids); // Transform entity ids array in entity uris array array_walk($entity_ids, function (&$entity_id) { // Retrieve the entity uri for the given entity id $entity_id = wl_get_entity_uri($entity_id); }); // Enhance current box selected entities $classification_boxes[$i]['selectedEntities'] = $entity_ids; } // Json encoding for classification boxes structure $classification_boxes = json_encode($classification_boxes); // Ensure there are no repetitions of the referenced entities $all_referenced_entities_ids = array_unique($all_referenced_entities_ids); // Build the entity storage object $referenced_entities_obj = array(); foreach ($all_referenced_entities_ids as $referenced_entity) { $entity = wl_serialize_entity($referenced_entity); $referenced_entities_obj[$entity['id']] = $entity; } $referenced_entities_obj = empty($referenced_entities_obj) ? '{}' : json_encode($referenced_entities_obj); $default_thumbnail_path = WL_DEFAULT_THUMBNAIL_PATH; echo <<<EOF <script type="text/javascript"> jQuery( function() { \tif ('undefined' == typeof window.wordlift) { \twindow.wordlift = {} \twindow.wordlift.entities = {} \t\t \t} \twindow.wordlift.classificationBoxes = {$classification_boxes}; \twindow.wordlift.entities = {$referenced_entities_obj}; \twindow.wordlift.currentPostId = {$post->ID}; \t\t\twindow.wordlift.defaultThumbnailPath = '{$default_thumbnail_path}'; }); </script> EOF; }
/** * Get the cache filename. If a file is found but is expired, it is deleted and false is returned. * * @since 3.0.0 * * @uses wl_caching_get_temp_path() to get the base cache filename. * @uses wl_caching_delete_file() to delete the cached file. * * @param string $hash The hash. * @return string|false The cache filename or false if not found. */ function wl_caching_get_filename($hash) { $files = glob(wl_caching_get_temp_path($hash) . '_*'); if (!is_array($files) || 0 === sizeof($files)) { return false; } // Get the filename. $filename = $files[0]; // Return false if the filename doesn't conform. $matches = array(); if (1 !== preg_match('/_(\\d+)$/', $filename, $matches)) { return false; } // echo 'time: ' . time() . ' > expires at: ' . (int)$matches[1] . "\n"; // Delete the file and return false if it's expired. if (time() >= (int) $matches[1]) { wl_caching_delete_file($filename); return false; } wl_write_log("[ wl_caching ] Found a cached response [ filename :: {$filename} ]"); return $filename; }
* Delete post-entity relationships */ wl_write_log('Deleting post-entity relationships... '); $sql = 'DROP TABLE IF EXISTS ' . wl_core_get_relation_instances_table_name() . ';'; $wpdb->query($sql); delete_option('wl_db_version'); wl_write_log('Done.'); /* * Delete taxonomy */ wl_write_log('Cleaning entities taxonomy... '); // Delte custom taxonomy terms. // We loop over terms in this rude way because in the uninstall script // is not possible to call WP custom taxonomy functions. foreach (range(0, 100) as $index) { delete_option(WL_ENTITY_TYPE_TAXONOMY_NAME . '_' . $index); wp_delete_term($index, WL_ENTITY_TYPE_TAXONOMY_NAME); } delete_option(WL_ENTITY_TYPE_TAXONOMY_NAME . '_children'); // it's a hierarchical taxonomy wl_write_log('Done.'); /** * Delete options */ wl_write_log('Cleaning WordLift options... '); delete_option(WL_OPTIONS_NAME); delete_option('wl_option_prefixes'); delete_option('wl_general_settings'); delete_option('wl_advanced_settings'); wl_write_log('Done. WordLift successfully uninstalled.');
function wl_shortcode_faceted_search_ajax($http_raw_data = null) { // Entity ID must be defined if (!isset($_GET['entity_id'])) { wp_die('No entity_id given'); return; } $entity_id = $_GET['entity_id']; // If the current post is not an entity post an exception needs to be raised $entity = get_post($entity_id); if (Wordlift_Entity_Service::TYPE_NAME !== $entity->post_type) { wp_die('Faceted search supports only entity posts'); return; } // Which type was requested? if (isset($_GET['type'])) { $required_type = $_GET['type']; } else { $required_type = null; } // Extract filtering conditions $filtering_entity_uris = null == $http_raw_data ? file_get_contents("php://input") : $http_raw_data; $filtering_entity_uris = json_decode($filtering_entity_uris); // Set up data structures $referencing_post_ids = wl_core_get_related_post_ids($entity_id, array('status' => 'publish')); $results = array(); if ('posts' == $required_type) { // Required filtered posts. wl_write_log("Going to find related posts for the current entity [ entity ID :: {$entity_id} ]"); if (empty($filtering_entity_uris)) { // No filter, just get referencing posts foreach ($referencing_post_ids as $post_obj_id) { $post_obj = get_post($post_obj_id); $thumbnail = wp_get_attachment_url(get_post_thumbnail_id($post_obj->ID, 'thumbnail')); $post_obj->thumbnail = $thumbnail ? $thumbnail : WL_DEFAULT_THUMBNAIL_PATH; $post_obj->permalink = get_post_permalink($post_obj->ID); $results[] = $post_obj; } } else { $filtering_entity_ids = wl_get_entity_post_ids_by_uris($filtering_entity_uris); // Search posts that reference all the filtering entities. $filtered_posts = wl_core_get_posts(array('get' => 'posts', 'post__in' => $referencing_post_ids, 'related_to__in' => $filtering_entity_ids, 'post_type' => 'post', 'as' => 'subject')); foreach ($filtered_posts as $post_obj) { $thumbnail = wp_get_attachment_url(get_post_thumbnail_id($post_obj->ID, 'thumbnail')); $post_obj->thumbnail = $thumbnail ? $thumbnail : WL_DEFAULT_THUMBNAIL_PATH; $post_obj->permalink = get_post_permalink($post_obj->ID); $results[] = $post_obj; } $results = $filtered_posts; } } else { global $wpdb; wl_write_log("Going to find related entities for the current entity [ entity ID :: {$entity_id} ]"); // Retrieve Wordlift relation instances table name $table_name = wl_core_get_relation_instances_table_name(); $ids = implode(',', $referencing_post_ids); // TODO - if an entity is related with different predicates each predicate impacts on counter $query = <<<EOF SELECT object_id as ID, count( object_id ) as counter FROM {$table_name} WHERE subject_id IN ({$ids}) and object_id != {$entity_id} GROUP BY object_id; EOF; wl_write_log("Going to find related entities for the current entity [ entity ID :: {$entity_id} ] [ query :: {$query} ]"); $entities = $wpdb->get_results($query, OBJECT); wl_write_log("Entities found " . count($entities)); foreach ($entities as $obj) { $entity = get_post($obj->ID); $entity = wl_serialize_entity($entity); $entity['counter'] = $obj->counter; $results[] = $entity; } } wl_core_send_json($results); }
/** * Reindex Redlink triple store, enabling local entities to be found in future analyses. */ function wordlift_reindex_triple_store() { // Get the reindex URL. $url = wl_configuration_get_dataset_index_url(); // Post the request. // wl_write_log( "wordlift_reindex_triple_store" ); // Prepare the request. $args = array_merge_recursive(unserialize(WL_REDLINK_API_HTTP_OPTIONS), array('method' => 'POST', 'headers' => array())); $response = wp_remote_request($url, $args); // If an error has been raised, return the error. if (is_wp_error($response) || 200 !== $response['response']['code']) { $body = is_wp_error($response) ? $response->get_error_message() : $response['body']; wl_write_log("wordlift_reindex_triple_store : error [ url :: {$url} ][ args :: "); wl_write_log("\n" . var_export($args, true)); wl_write_log("[ response :: "); wl_write_log("\n" . var_export($response, true)); wl_write_log("][ body :: "); wl_write_log("\n" . $body); wl_write_log("]"); return false; } return true; }
/** * Push the post with the specified ID to Redlink. * * @since 3.0.0 * * @param int $post_id The post ID. */ function wl_linked_data_push_to_redlink($post_id) { // Get the post. $post = get_post($post_id); wl_write_log("wl_linked_data_push_to_redlink [ post id :: {$post_id} ][ post type :: {$post->post_type} ]"); // Call the method on behalf of the post type. switch ($post->post_type) { case 'entity': wl_push_entity_post_to_redlink($post); break; default: wl_push_post_to_redlink($post); } // Reindex the triple store if buffering is turned off. if (false === WL_ENABLE_SPARQL_UPDATE_QUERIES_BUFFERING) { wordlift_reindex_triple_store(); } }
function createPostThumbnail($guid, $label, $content_type, $file, $post_id) { $attachment = array('guid' => $guid, '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, $file, $post_id); wl_write_log("createPostThumbnail [ attachment ID :: {$attachment_id} ]"); wl_write_log("createPostThumbnail [ " . wp_get_attachment_image($attachment_id, 'thumbnail') . " ]"); // Set it as the featured image. $this->assertTrue(false !== set_post_thumbnail($post_id, $attachment_id)); return $attachment_id; }
/** * Set the main type for the entity using the related taxonomy. * * @param int $post_id The numeric post ID. * @param string $type_uri A type URI. */ function wl_set_entity_main_type($post_id, $type_uri) { wl_write_log("wl_set_entity_main_type [ post id :: {$post_id} ][ type uri :: {$type_uri} ]"); // If the type URI is empty we remove the type. if (empty($type_uri)) { wp_set_object_terms($post_id, null, WL_ENTITY_TYPE_TAXONOMY_NAME); return; } // Get all the terms bound to the wl_entity_type taxonomy. $terms = get_terms(WL_ENTITY_TYPE_TAXONOMY_NAME, array('hide_empty' => false, 'fields' => 'ids')); // Check which term matches the specified URI. foreach ($terms as $term_id) { // Load the type data. $type = wl_entity_type_taxonomy_get_term_options($term_id); // Set the related term ID. if ($type_uri === $type['uri'] || $type_uri === $type['css_class']) { wp_set_object_terms($post_id, (int) $term_id, WL_ENTITY_TYPE_TAXONOMY_NAME); return; } } }
/** * Get the property with the specified name. The value at the specified index will be returned. * * @since 3.0.0 * * @uses expand() to expand the property name. * * @param string $name The property name. * @param int $index The value index (default NULL, returns an array of properties). * * @return string|array The property value. */ function get_property($name, $index = NULL) { $values = $this->json_path->find($this->expand($name)); wl_write_log("[ name :: {$name} ][ index :: {$index} ][ value :: " . var_export($values, true) . " ]"); return NULL !== $index ? $values[$index] : $values; // $value = wl_jsonld_get_property( $this->graph, $name, $language, $this->suffix, $index ); // return $value; }
/** * Remove all relation instances for a given $subject_id and $predicate * If $predicate is omitted, $predicate filter is not applied * * @param int $subject_id The post ID | The entity post ID. * * @return (boolean) False for failure. True for success. */ function wl_core_delete_relation_instances($subject_id) { // Checks on subject and object if (!is_numeric($subject_id)) { return false; } // Prepare interaction with db global $wpdb; wl_write_log("Going to delete relation instances [ subject_id :: {$subject_id} ]"); // @see ttps://codex.wordpress.org/it:Riferimento_classi/wpdb#DELETE_di_righe $wpdb->delete(wl_core_get_relation_instances_table_name(), array('subject_id' => $subject_id), array('%d')); return true; }
/** * Update an entity type with the provided data. * @param int $term_id The numeric term ID. * @param string $css_class The stylesheet class. * @param string $uri The URI. * @param array $same_as An array of sameAs URIs. * @param array $custom_fields An array of custom fields and their properties mapping (with info on how to export them to the triple store). * @param array $templates * @param array $microdata_template A template string to print microdata on the frontend. * @return True if option value has changed, false if not or if update failed. */ function wl_entity_type_taxonomy_update_term($term_id, $css_class, $uri, $same_as = array(), $custom_fields = array(), $templates = array(), $microdata_template = array()) { wl_write_log("wl_entity_type_taxonomy_update_term [ term id :: {$term_id} ][ css class :: {$css_class} ][ uri :: {$uri} ][ same as :: " . implode(',', $same_as) . " ]"); return update_option(WL_ENTITY_TYPE_TAXONOMY_NAME . "_{$term_id}", array('css_class' => $css_class, 'uri' => $uri, 'same_as' => $same_as, 'custom_fields' => $custom_fields, 'templates' => $templates, 'microdata_template' => $microdata_template)); }
/** * Update the status of a post. * * @param int $post_id The post ID * @param string $status The new status */ function wl_update_post_status($post_id, $status) { wl_write_log("wl_update_post_status [ post ID :: {$post_id} ][ status :: {$status} ]"); global $wpdb; if (!($post = get_post($post_id))) { return; } if ($status === $post->post_status) { return; } $wpdb->update($wpdb->posts, array('post_status' => $status), array('ID' => $post->ID)); clean_post_cache($post->ID); $old_status = $post->post_status; $post->post_status = $status; wp_transition_post_status($status, $old_status, $post); /** This action is documented in wp-includes/post.php */ do_action('edit_post', $post->ID, $post); /** This action is documented in wp-includes/post.php */ do_action("save_post_{$post->post_type}", $post->ID, $post, true); /** This action is documented in wp-includes/post.php */ do_action('wl_linked_data_save_post', $post->ID); /** This action is documented in wp-includes/post.php */ do_action('wp_insert_post', $post->ID, $post, true); }