3

I have a view showing nodes of two different types sorted by date. I want to limit the maximum number of nodes shown of the one type by, say, 25% percent of the total nodes per page.

How would I go about that?

6
  • Do you have a limit on the number of items being displayed in the view?
    – goron
    Jul 30, 2012 at 23:30
  • Yes. Say the view is limited to 4 nodes, I want maximum 25%/one of them to be of a certain type.
    – 0skar
    Jul 31, 2012 at 8:17
  • Do the results need to be displayed in a single sorted list?
    – Citricguy
    Aug 1, 2012 at 0:14
  • 1
    What should happen to nodes that aren't displayed on for example the first page? Should they be displayed on the second page or left out completely? Aug 2, 2012 at 12:56
  • Good point @zwirbeltier it looks like the only way of doing this is a bit of a template hack, but if you are setting up a display like this you must know you can't have pagination.
    – Duncanmoo
    Aug 7, 2012 at 6:29

2 Answers 2

2
+50

This might be a job for _views_pre_render(). In it, you can go through your views results and modify them to your module's content. The issue here is creating a view result big enough to make your percentages work. For example, let's say you want to have that view of 4 nodes, but only 1 of which is of a certain type. Since you are sorting by date, if the first 4 are all of that type, you grab one but need to keep looking for 3 of the other type.

In a dull ax approach, you could, though, create a view that returned 100, or however many is reasonable on your site based upon what you actually see re mix of nodes, of both types sorted by date and then do something like:

function YOURMODULE_views_pre_render(&$view) {

  if ($view->name=='NAMEOFTHEVIEW') {

    //  drupal_set_message('<pre>' . print_r($view->result[0], true) . '</pre>'); // just the first row
    //  drupal_set_message('<pre>' . print_r($view->result, true) . '</pre>');    // all of them

    $max=1;    // hardcoded for example purposes
    $total=4;  // hardcoded for example purposes

    $new_result=array();

    foreach ($view->result as $result) {

      if ($max && $result->FIELDTHATHASTHENODETYPEINIT==NODETYPEWEARELOOKINGFOR) {
        $new_result[]=$result;
        $max--; $total--;
      } elseif (--$total) {
        $new_result[]=$result;
      }

    }

    $view->result=$new_result;

  }

  // any other views_pre_render()ing here

}

which if my logic gene is in gear today will cycle through your view results and pick out at most $max nodes of one type and then fill up $new_results up to $total with the rest of the view results and then replace the results of the view with that.

The issue, again, is that if all the results are of one node type, or there aren't enough of the other node type to fill up $new_result, you will have less than $total results returned.

(One or both of the drupal_set_message()s will/might be helpful for figuring out FIELDTHATHASTHENODETYPEINIT. If there isn't one in your view already, you can put one in and then not display/hide it if necessary.)

4
  • I love hook_views_pre_render, and at first I even thought this would be the right approach. On a second thought however, the issue with the pre render hook is that you are altering the result set after the fact - after the fact that the results have been returned from the database. The user's date sort means that you could potentially end up with 4 nodes of only one type in the result set, while there are still nodes of the other type that could potentially be returned in the result set. What then? At that point the 25% node type constraint is out of the window. Aug 1, 2012 at 16:51
  • BTW, I would not guarantee a perfect response to that question. When it comes to relatively close answers (those that might require the user to alter some of his requirements), I think this answer is a good starting point, +1 for that. Also hook_views_query_alter might be another good starting point. Aug 1, 2012 at 17:08
  • I think I addressed your first comment's point about 4 nodes of only one type by artificially inflating the number of nodes returned by the view. Dull ax I know but allows for one view and some reasonable sorting to occur.
    – Jimajamma
    Aug 1, 2012 at 17:31
  • I agree that this dull ax provides a reasonable sorting (and 1+'d for that). That it will meet the user's hard requirements, that's a completely different subject ;) Aug 1, 2012 at 18:00
2

A simple way will be to:

  1. create a view that will show X amount of 1 type of nodes that is equivalent to the 25% of the total nodes you want to display.

  2. Then add an attachment (not EVA) view and attach it after the first one, but overwrite the filter indicating the content type selected for the attachment view only.

  3. Repeat the step 2 as many times as needed to show the 100% of the total nodes from 25% of different content types.

Note: if you add footer and header HTML or text to the main view when adding the attachment view they will be copy over, but you can overwrite them so they will not show.

End result width a limit of 4 node will be like:

  1. Node title (content type A) {main view}
  2. Node title (content type B) {attachment view 1 => attached after main view}
  3. Node title (content type C) {attachment view 2 => attached after attachment view 1}
  4. Node title (content type D) {attachment view 3 => attached after attachment view 2}

Thank you.

5
  • Are these views appended to one another or merged together? Will sorting by date as a single list be an option?
    – Citricguy
    Aug 1, 2012 at 0:08
  • At the end it is going to look like a single list I can see an issue with the day sorting. They will be sorting by day, but the sort order will not look right
    – Emil Orol
    Aug 1, 2012 at 0:10
  • This seems like it's on the right track. I'm sure there is a way to do this with views, but you could throw all the values into an array, sort and re-display as a single list. I didn't realize views had the attachment feature. Way cool. :)
    – Citricguy
    Aug 1, 2012 at 0:13
  • Just an idea after you do the view with the attachments as I recommended you might be able to sort properly by date by creating a template (tpl.php) file for the view and before printing it sort the results by the date field.
    – Emil Orol
    Aug 1, 2012 at 0:15
  • @redhatlab I would have initially done it by creating two views and merging the results at template level. I may be wrong but I would prefer to keep the logic out of the template so _views_pre_render might be better method.
    – Duncanmoo
    Aug 7, 2012 at 6:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.