add secondary orderby ID to items query #337

This commit is contained in:
leogermani 2019-11-29 18:34:38 -03:00
parent fbd6e105ce
commit f1dc8cc77e
3 changed files with 219 additions and 98 deletions

View File

@ -100,7 +100,7 @@ class Item extends Entity {
];
$attachments = get_posts( $attachments_query );
return apply_filters("tainacan-item-get-attachments", $attachments, $exclude, $this);
}
@ -123,11 +123,11 @@ class Item extends Entity {
* @return array
*/
function get_thumbnail() {
$sizes = get_intermediate_image_sizes();
array_unshift($sizes, 'full');
foreach ( $sizes as $size ) {
$thumbs[$size] = wp_get_attachment_image_src( $this->get__thumbnail_id(), $size );
}
@ -226,7 +226,7 @@ class Item extends Entity {
function get_description() {
return $this->get_mapped_property( 'description' );
}
/**
* Return the item document type
*
@ -235,7 +235,7 @@ class Item extends Entity {
function get_document_type() {
return $this->get_mapped_property( 'document_type' );
}
/**
* Return the item document
*
@ -263,7 +263,7 @@ class Item extends Entity {
public function get_capabilities() {
return $this->get_collection()->get_items_capabilities();
}
/**
* Checks if comments are allowed for the current Collection.
* @return string "open"|"closed"
@ -294,6 +294,17 @@ class Item extends Entity {
$this->set_mapped_property( 'order', $value );
}
/**
* Define the creation date
*
* @param [string] $value
*
* @return void
*/
function set_creation_date( $value ) {
$this->set_mapped_property( 'creation_date', $value );
}
/**
* Define the parent ID
*
@ -315,7 +326,7 @@ class Item extends Entity {
function set_document_type( $value ) {
$this->set_mapped_property( 'document_type', $value );
}
/**
* Define the document
*
@ -326,7 +337,7 @@ class Item extends Entity {
function set_document( $value ) {
$this->set_mapped_property( 'document', $value );
}
/**
* Define the description
*
@ -363,7 +374,7 @@ class Item extends Entity {
$this->cap = $item_collection->get_items_capabilities();
}
}
/**
* Sets if comments are allowed for the current Item.
*
@ -397,7 +408,7 @@ class Item extends Entity {
$arrayItemMetadata = $this->get_metadata();
if ( $arrayItemMetadata ) {
foreach ( $arrayItemMetadata as $itemMetadata ) {
// skip validation for Compound Metadata
if ( $itemMetadata->get_metadatum()->get_metadata_type() == 'Tainacan\Metadata_Types\Compound' ) {
continue;
@ -435,29 +446,29 @@ class Item extends Entity {
return parent::validate();
}
public function _toHtml() {
$return = '';
$id = $this->get_id();
if ( $id ) {
$link = get_permalink( (int) $id );
if (is_string($link)) {
$return = "<a data-linkto='item' data-id='$id' href='$link'>";
$return.= $this->get_title();
$return .= "</a>";
}
}
return $return;
}
/**
@ -470,25 +481,25 @@ class Item extends Entity {
*
* @param array|string $args {
* Optional. Array or string of arguments.
*
*
* @type mixed $metadata Metadatum object, ID or slug to retrieve only one metadatum. empty returns all metadata
*
*
* @type array $metadata__in Array of metadata IDs or Slugs to be retrieved. Default none
*
*
* @type array $metadata__not_in Array of metadata IDs (slugs not accepted) to excluded. Default none
*
*
* @type bool $exclude_title Exclude the Core Title Metadata from result. Default false
*
*
* @type bool $exclude_description Exclude the Core Description Metadata from result. Default false
*
*
* @type bool $exclude_core Exclude Core Metadata (title and description) from result. Default false
*
*
* @type bool $hide_empty Wether to hide or not metadata the item has no value to
* Default: true
* @type string $before String to be added before each metadata block
* Default '<div class="metadata-type-$type">' where $type is the metadata type slug
* @type string $after String to be added after each metadata block
* Default '</div>'
* Default '</div>'
* @type string $before_title String to be added before each metadata title
* Default '<h3>'
* @type string $after_title String to be added after each metadata title
@ -503,12 +514,12 @@ class Item extends Entity {
* @throws \Exception
*/
public function get_metadata_as_html($args = array()) {
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::get_instance();
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$return = '';
$defaults = array(
'metadata' => null,
'metadata__in' => null,
@ -527,9 +538,9 @@ class Item extends Entity {
$args = wp_parse_args($args, $defaults);
if (!is_null($args['metadata'])) {
$metadatum_object = null;
if ( $metadatum instanceof \Tainacan\Entities\Metadatum ) {
$metadatum_object = $metadatum;
} elseif ( is_int($metadatum) ) {
@ -540,10 +551,10 @@ class Item extends Entity {
$metadatum_object = $metadatum[0];
}
}
if ( $metadatum_object instanceof \Tainacan\Entities\Metadatum ) {
if ( is_array($args['metadata__not_in'])
if ( is_array($args['metadata__not_in'])
&& (
in_array($metadatum_object->get_slug(), $args['metadata__not_in']) ||
in_array($metadatum_object->get_id(), $args['metadata__not_in'])
@ -551,23 +562,23 @@ class Item extends Entity {
) {
return $return;
}
$mto = $metadatum_object->get_metadata_type_object();
$before = str_replace('$type', $mto->get_slug(), $args['before']);
$return .= $before;
$item_meta = new \Tainacan\Entities\Item_Metadata_Entity($this, $metadatum_object);
if ($item_meta->has_value() || !$args['hide_empty']) {
$return .= $args['before_title'] . $metadatum_object->get_name() . $args['after_title'];
$return .= $args['before_value'] . $item_meta->get_value_as_html() . $args['after_value'];
}
$return .= $args['after'];
}
return $return;
}
@ -604,13 +615,13 @@ class Item extends Entity {
$query_args['post__name_in'] = $post__name_in;
}
$metadata = $this->get_metadata($query_args);
foreach ( $metadata as $item_meta ) {
$fto = $item_meta->get_metadatum()->get_metadata_type_object();
$before = str_replace('$type', $fto->get_slug(), $args['before']);
$return .= $before;
@ -628,21 +639,21 @@ class Item extends Entity {
$return .= $args['before_title'] . $item_meta->get_metadatum()->get_name() . $args['after_title'];
$return .= $args['before_value'] . $item_meta->get_value_as_html() . $args['after_value'];
}
$return .= $args['after'];
}
return $return;
}
public function get_document_as_html($img_size = 'large') {
$type = $this->get_document_type();
$output = '';
if ( $type == 'url' ) {
global $wp_embed;
$_embed = $wp_embed->autoembed($this->get_document());
@ -653,47 +664,47 @@ class Item extends Entity {
} elseif ( $type == 'text' ) {
$output .= $this->get_document();
} elseif ( $type == 'attachment' ) {
if ( wp_attachment_is_image($this->get_document()) ) {
$img = wp_get_attachment_image($this->get_document(), $img_size);
$img_full = wp_get_attachment_url($this->get_document());
$image_attributes = wp_get_attachment_image_src( $this->get_document(), $img_size );
$img = "<img style='max-width: 100%;' src='" . $image_attributes[0] . "' />";
$output .= sprintf("<a href='%s' target='blank'>%s</a>", $img_full, $img);
} else {
global $wp_embed;
$url = wp_get_attachment_url($this->get_document());
$embed = $wp_embed->autoembed($url);
if ( $embed == $url ) {
$output .= sprintf("<a href='%s' target='blank'>%s</a>", $url, $url);
} else {
$output .= $embed;
}
}
}
return apply_filters("tainacan-item-get-document-as-html", $output, $img_size, $this);
}
/**
* Gets the url to the edit page for this item
* Gets the url to the edit page for this item
*/
public function get_edit_url() {
$collection_id = $this->get_collection_id();
$id = $this->get_id();
return admin_url("?page=tainacan_admin#/collections/$collection_id/items/$id/edit");
}
}
}

View File

@ -172,16 +172,16 @@ class Items extends Repository {
$collection->register_collection_item_post_type();
}
// register taxonomies
// register taxonomies
if ( is_array( $taxonomies ) && sizeof( $taxonomies ) > 0 ) {
foreach ( $taxonomies as $taxonomy ) {
$taxonomy->tainacan_register_taxonomy();
}
}
// register taxonomies to collections considering metadata inheritance
$Tainacan_Taxonomies->register_taxonomies_for_all_collections();
}
public function insert( $item ) {
@ -195,7 +195,7 @@ class Items extends Repository {
* to learn all args accepted in the $args parameter (@see https://developer.wordpress.org/reference/classes/wp_query/)
* You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
* appropriate WP_Query argument
*
*
* If a number is passed to $args, it will return a \Tainacan\Entities\Item object. But if the post is not found or
* does not match the entity post type, it will return an empty array
*
@ -213,7 +213,7 @@ class Items extends Repository {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
if ( is_numeric( $args ) ) {
$existing_post = get_post( $args );
if ( $existing_post instanceof \WP_Post ) {
try {
@ -285,7 +285,24 @@ class Items extends Repository {
$args = $this->parse_fetch_args( $args );
$args['post_type'] = $cpt;
// If no orderby was passed, or if only one orderby parameter is passed
// we add a second criteria to order by ID and make sure items are always returned in the same order
// See #337
if ( ! isset($args['orderby']) ) {
$args['orderby'] = 'post_date';
}
if ( ! isset($args['order']) ) {
$args['order'] = 'DESC';
}
if ( is_string( $args['orderby'] ) ) {
$new_order = [
$args['orderby'] => $args['order'],
'ID' => 'DESC'
];
$args['orderby'] = $new_order;
}
$args = apply_filters( 'tainacan_fetch_args', $args, 'items' );
$wp_query = new \WP_Query( $args );
@ -375,7 +392,7 @@ class Items extends Repository {
return $where;
}
/**
* generate a content of document to index.
*
@ -480,23 +497,23 @@ class Items extends Repository {
}
/**
* Return if comment are open for this item (post_id) and the collection too
*
* Return if comment are open for this item (post_id) and the collection too
*
* @param bool $open_comment
* @param integer $post_id Item id
* @return bool
*/
public function hook_comments_open($open_comment, $post_id) {
$item = self::get_entity_by_post($post_id);
if($item != false && $item instanceof Entities\Item) {
$collection = $item->get_collection();
if( $collection->get_allow_comments() !== 'open' ) return false;
}
return $open_comment;
}
/**
* Filter to handle special permissions
*
@ -506,9 +523,9 @@ class Items extends Repository {
public function map_meta_cap( $caps, $cap, $user_id, $args ) {
// Filters meta caps edit_tainacan-collection and check if user is moderator
if ( $cap == 'read_post' && is_array( $args ) && array_key_exists( 0, $args ) ) {
if ( $cap == 'read_post' && is_array( $args ) && array_key_exists( 0, $args ) ) {
$entity = $args[0];
if ( is_numeric( $entity ) || $entity instanceof Entities\Item ) {
@ -518,24 +535,24 @@ class Items extends Repository {
}
if ( $entity instanceof Entities\Item ) {
$collection = $entity->get_collection();
if ( $collection instanceof Entities\Collection ) {
$status_obj = get_post_status_object( $collection->get_status() );
if ( ! $status_obj->public ) {
$caps[] = $entity->get_capabilities()->read_private_posts;
}
}
}
}
}
return $caps;
}
/**
* Check if $user can read the item based on the colletion
*
@ -546,37 +563,37 @@ class Items extends Repository {
* @throws \Exception
*/
public function can_read( Entities\Entity $entity, $user = null ) {
if ( ! $entity instanceof Entities\Item) {
throw new InvalidArgumentException('Items::can_read() expects an Item entity as the first parameter');
}
// can read the item looking only to the item
$can_read = parent::can_read($entity, $user);
if ( $can_read ) {
$collection = $entity->get_collection();
$status_obj = get_post_status_object( $collection->get_status() );
if ( $status_obj->public ) {
return $can_read;
}
}
if ( is_null($user) ) {
$user = get_current_user_id();
}
if ( ! $user ) {
return false;
} elseif ( is_object( $user ) ) {
$user = $user->ID;
}
$entity_cap = $entity->get_capabilities();
return user_can( $user, $entity_cap->read_private_posts, $entity->get_id() );
}
}

View File

@ -449,4 +449,97 @@ class Items extends TAINACAN_UnitTestCase {
}
function test_order_by_date_same_date() {
$date = '2019-10-10 10:10:10';
$ItemRepo = \Tainacan\Repositories\Items::get_instance();
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste1',
'description' => 'adasdasdsa',
'status' => 'publish'
),
true
);
$item1 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem',
'collection' => $collection,
'status' => 'publish',
'creation_date' => $date
),
true
);
$item2 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem',
'collection' => $collection,
'status' => 'publish',
'creation_date' => $date
),
true
);
$item3 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem',
'collection' => $collection,
'status' => 'publish',
'creation_date' => $date
),
true
);
$item4 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem',
'collection' => $collection,
'status' => 'publish',
'creation_date' => $date
),
true
);
$item5 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem',
'collection' => $collection,
'status' => 'publish',
'creation_date' => $date
),
true
);
// should always return in the same order
for ($i=1; $i<20; $i++) {
$items = $ItemRepo->fetch([], $collection, 'OBJECT');
$this->assertEquals($item5->get_id(), $items[0]->get_id());
$this->assertEquals($item1->get_id(), $items[4]->get_id());
}
// also when ordering by metadata
for ($i=1; $i<20; $i++) {
$items = $ItemRepo->fetch([
'meta_key' => 'collection_id',
'orderby' => 'meta_value'
], $collection, 'OBJECT');
$this->assertEquals($item5->get_id(), $items[0]->get_id());
$this->assertEquals($item1->get_id(), $items[4]->get_id());
}
}
}