/**
 * 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);
}
/**
 * Adds the entities meta box (called from *add_meta_boxes* hook).
 *
 * @param string $post_type The type of the current open post.
 */
function wl_admin_add_entities_meta_box($post_type)
{
    wl_write_log("wl_admin_add_entities_meta_box [ post type :: {$post_type} ]");
    // Add meta box for related entities (separated from the others for historical reasons)
    add_meta_box('wordlift_entities_box', __('Wordlift', 'wordlift'), 'wl_entities_box_content', $post_type, 'side', 'high');
    // Add meta box for specific type of entities
    $entity_id = get_the_ID();
    $entity_type = wl_entity_type_taxonomy_get_type($entity_id);
    if (isset($entity_id) && is_numeric($entity_id) && isset($entity_type['custom_fields'])) {
        // In some special case, properties must be grouped in one metabox (e.g. coordinates) or dealed with custom methods.
        $metaboxes = wl_entities_metaboxes_group_properties_by_input_field($entity_type['custom_fields']);
        $simple_metaboxes = $metaboxes[0];
        $grouped_metaboxes = $metaboxes[1];
        // Loop over simple entity properties
        foreach ($simple_metaboxes as $key => $property) {
            // Don't present to the user the full schema name, just the slug
            $property_slug_name = explode('/', $property['predicate']);
            $property_slug_name = end($property_slug_name);
            // Metabox title
            $title = __('Edit', 'wordlift') . ' ' . get_the_title() . ' ' . __($property_slug_name, 'wordlift');
            // Info passed to the metabox
            $info = array();
            $info[$key] = $property;
            $unique_metabox_name = uniqid('wl_metabox_');
            add_meta_box($unique_metabox_name, $title, 'wl_entities_' . $property['type'] . '_box_content', $post_type, 'normal', 'high', $info);
        }
        // Loop over grouped properties
        foreach ($grouped_metaboxes as $key => $property) {
            // Metabox title
            $title = __('Edit', 'wordlift') . ' ' . get_the_title() . ' ' . __($key, 'wordlift');
            $unique_metabox_name = uniqid('wl_metabox_');
            add_meta_box($unique_metabox_name, $title, 'wl_entities_' . $key . '_box_content', $post_type, 'normal', 'high');
        }
    }
}
/**
 * Delete the specified post from the triple store.
 *
 * @param array|int $post An array of post data
 */
function rl_delete_post($post)
{
    $post_id = is_numeric($post) ? $post : $post->ID;
    // hide all entities that are not referenced by any published post.
    foreach (wl_core_get_related_entity_ids($post_id) as $entity_id) {
        // check if there is at least one referencing post published.
        $is_published = array_reduce(wl_core_get_related_post_ids($entity_id), function ($carry, $item) {
            $post = get_post($item);
            return $carry || 'publish' === $post->post_status;
        });
        // set the entity to draft if no referencing posts are published.
        if (!$is_published) {
            wl_update_post_status($entity_id, 'draft');
        }
    }
    // get the entity URI (valid also for posts)
    $uri_esc = wl_sparql_escape_uri(wl_get_entity_uri($post_id));
    wl_write_log("rl_delete_post [ post id :: {$post_id} ][ uri esc :: {$uri_esc} ]");
    // create the SPARQL statement by joining the SPARQL prefixes and deleting any known predicate.
    $stmt = rl_sparql_prefixes();
    foreach (wl_predicates() as $predicate) {
        $stmt .= "DELETE { <{$uri_esc}> {$predicate} ?o . } WHERE { <{$uri_esc}> {$predicate} ?o . };\n" . "DELETE { ?s {$predicate} <{$uri_esc}> . } WHERE { ?s {$predicate} <{$uri_esc}> . };\n";
    }
    // if the post is an entity and has exported properties, delete the related predicates.
    if (WL_ENTITY_TYPE_NAME === $post->post_type) {
        $type = wl_entity_type_taxonomy_get_type($post->ID);
        if (isset($type['custom_fields'])) {
            foreach ($type['custom_fields'] as $field => $params) {
                // TODO: enclose in <> only if predicate starts with http(s)://
                $predicate = '<' . $params['predicate'] . '>';
                $stmt .= "DELETE { <{$uri_esc}> {$predicate} ?o . } WHERE { <{$uri_esc}> {$predicate} ?o . };\n";
            }
        }
    }
    // finally execute the query.
    rl_execute_sparql_update_query($stmt);
}
/**
 * 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;
}
/**
 * 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);
}
 /**
  * Calculate rating for a given entity
  * Rating depends from following criteria
  *
  * 1. Is the current entity related to at least 1 post?
  * 2. Is the current entity content post not empty?
  * 3. Is the current entity related to at least 1 entity?
  * 4. Is the entity published? 
  * 5. There is a a thumbnail associated to the entity?
  * 6. Has the entity a sameas defined?
  * 7. Are all schema.org required metadata compiled?
  *
  * Each positive check means +1 in terms of rating score
  *
  * @since 3.3.0
  *
  * @param int $post_id The entity post id.
  *
  * @return int An array representing the rating obj.
  */
 public function calculate_rating_for($post_id)
 {
     // If it's not an entity, return.
     if (!$this->is_entity($post_id)) {
         return;
     }
     // Retrieve the post object
     $post = get_post($post_id);
     // Rating value
     $score = 0;
     // Store warning messages
     $warnings = array();
     // Is the current entity related to at least 1 post?
     0 < count(wl_core_get_related_post_ids($post->ID)) ? $score++ : array_push($warnings, __(self::RATING_WARNING_HAS_RELATED_POSTS, 'wordlift'));
     // Is the post content not empty?
     !empty($post->post_content) ? $score++ : array_push($warnings, __(self::RATING_WARNING_HAS_CONTENT_POST, 'wordlift'));
     // Is the current entity related to at least 1 entity?
     // Was the current entity already disambiguated?
     0 < count(wl_core_get_related_entity_ids($post->ID)) ? $score++ : array_push($warnings, __(self::RATING_WARNING_HAS_RELATED_ENTITIES, 'wordlift'));
     // Is the entity published?
     'publish' === get_post_status($post->ID) ? $score++ : array_push($warnings, __(self::RATING_WARNING_IS_PUBLISHED, 'wordlift'));
     // Has a thumbnail?
     has_post_thumbnail($post->ID) ? $score++ : array_push($warnings, __(self::RATING_WARNING_HAS_THUMBNAIL, 'wordlift'));
     // Get all post meta keys for the current post
     global $wpdb;
     $query = $wpdb->prepare("SELECT DISTINCT(meta_key) FROM {$wpdb->postmeta}  WHERE post_id = %d", $post->ID);
     // Check intersection between available meta keys
     // and expected ones arrays to detect missing values
     $available_meta_keys = $wpdb->get_col($query);
     // If each expected key is contained in available keys array ...
     in_array(Wordlift_Schema_Service::FIELD_SAME_AS, $available_meta_keys) ? $score++ : array_push($warnings, __(self::RATING_WARNING_HAS_SAME_AS, 'wordlift'));
     $schema = wl_entity_type_taxonomy_get_type($post_id);
     $expected_meta_keys = null === $schema['custom_fields'] ? array() : array_keys($schema['custom_fields']);
     $intersection = array_intersect($expected_meta_keys, $available_meta_keys);
     // If each expected key is contained in available keys array ...
     count($intersection) === count($expected_meta_keys) ? $score++ : array_push($warnings, __(self::RATING_WARNING_HAS_COMPLETED_METADATA, 'wordlift'));
     // Finally return score and warnings
     return array('raw_score' => $score, 'traffic_light_score' => $this->convert_raw_score_to_traffic_light($score), 'percentage_score' => $this->convert_raw_score_to_percentage($score), 'warnings' => $warnings);
 }
/**
 * Retrieve entity type custom fields.
 *
 * @param int $entity_id id of the entity, if any.
 *
 * @return array|null if $entity_id was specified, return custom_fields for that entity's type. Otherwise returns all custom_fields
 */
function wl_entity_taxonomy_get_custom_fields($entity_id = null)
{
    if (is_null($entity_id)) {
        // Return all custom fields.
        // Get taxonomy terms
        $terms = get_terms(Wordlift_Entity_Types_Taxonomy_Service::TAXONOMY_NAME, array('hide_empty' => 0));
        if (is_wp_error($terms)) {
            return null;
        }
        $custom_fields = array();
        foreach ($terms as $term) {
            // Get custom_fields
            $term_options = Wordlift_Schema_Service::get_instance()->get_schema($term->slug);
            $custom_fields[$term_options['uri']] = $term_options['custom_fields'];
        }
        return $custom_fields;
    }
    // Return custom fields for this specific entity's type.
    $type = wl_entity_type_taxonomy_get_type($entity_id);
    return $type['custom_fields'];
}
/**
 * Retrieves the entity types for the specified post ID, where
 *
 * @param $post_id numeric The numeric post ID.
 *
 * @return array Array of type(s) (e.g. Type, for the http://schema.org/Type)
 * or NULL in case of no values (or error).
 */
function wl_schema_get_types($post_id)
{
    // Some checks on the parameters
    if (!is_numeric($post_id)) {
        return null;
    }
    $type = wl_entity_type_taxonomy_get_type($post_id);
    if (isset($type['uri'])) {
        return array($type['uri']);
    }
    return null;
}
 function testWlEntityTaxonomyMicrodataTemplateInheritance()
 {
     // Create entity and set type
     $business_id = wl_create_post("Entity 1 Text", 'entity-1', "Entity 1 Title", 'publish', 'entity');
     wl_set_entity_main_type($business_id, 'http://schema.org/LocalBusiness');
     // Get microdata template
     $entity_type_details = wl_entity_type_taxonomy_get_type($business_id);
     $microdata_template = $entity_type_details['microdata_template'];
     // Check inherited microdata templates:
     // latitude from Place with 'itemtype="http://schema.org/GeoCoordinates"' markup
     $this->assertContains('itemtype="http://schema.org/GeoCoordinates"', $microdata_template);
     $this->assertContains('{{latitude}}', $microdata_template);
     // founder from Organization
     $this->assertContains('{{founder}}', $microdata_template);
     // negative test
     $this->assertNotContains('{{startDate}}', $microdata_template);
 }
/**
 * 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);
}
/**
 * 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);
    if (null === $main_type) {
        $item_type = '';
    } else {
        $item_type = ' itemtype="' . esc_attr($main_type['uri']) . '"';
        // Append the stylesheet if the enable color coding flag is set to true.
        if (wl_configuration_get_enable_color_coding() && is_null($itemprop)) {
            $item_type .= ' class="' . esc_attr($main_type['css_class']) . '"';
        }
    }
    // 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="$2">' . (is_null($itemprop) ? '$2' : '') . '</a></$1>', $content);
    wl_write_log("wl_content_embed_item_microdata [ uri :: {$uri} ][ regex :: {$regex} ]");
    return $content;
}
/**
 * Retrieve entity type custom fields
 *
 * @param int $entity_id id of the entity, if any
 *
 * @return mixed if $entity_id was specified, return custom_fields for that entity's type. Otherwise returns all custom_fields
 */
function wl_entity_taxonomy_get_custom_fields($entity_id = null)
{
    if (is_null($entity_id)) {
        // Return all custom fields.
        // Get taxonomy terms
        $terms = get_terms(WL_ENTITY_TYPE_TAXONOMY_NAME, array('hide_empty' => 0));
        if (is_wp_error($terms)) {
            return null;
        }
        $custom_fields = array();
        foreach ($terms as $term) {
            // Get custom_fields
            $term_options = wl_entity_type_taxonomy_get_term_options($term->term_id);
            $custom_fields[$term_options['uri']] = $term_options['custom_fields'];
        }
        return $custom_fields;
    } else {
        // Return custom fields for this specific entity's type.
        $type = wl_entity_type_taxonomy_get_type($entity_id);
        return $type['custom_fields'];
    }
}