<commit_before>/**
 * @fileOverview Pagination Middleware.
 */

var url = require('url');

var __ = require('lodash');
var async = require('async');

var sanitize = require('validator').sanitize;
var pagination = require('pagination');

/**
 * The Pagination Middleware.
 *
 * @contructor
 */
var Pagination = module.exports = function(){

};


/**
 * Prepare and configure a pagination middleware.
 *
 * @param {crude.Entity} Entity The Entity class Ctor.
 * @param {Object=} optObj a hash with options.
 * @return {Function} The middleware.
 */
Pagination.prototype.paginate = function(Entity, optOpts) {

  var defaultOpts = {
    limit: 6,
    query: null,
  };
  var opts = __.extend(defaultOpts, optOpts || {});

  this.Entity = Entity;

  return this._paginateMiddleware.bind(this, opts);

};

/**
 * First Middleware
 *
 * @param {Object} opt a hash with options.
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Function(Error=)} next passing control to the next middleware.
 * @private
 */
Pagination.prototype._paginateMiddleware = function(opts, req, res, next) {

  var page = sanitize(req.query.page).toInt() || 1;
  var limit = sanitize(req.query.show).toInt() || opts.limit;
  var skip = (page - 1) * limit;
  var entity = new this.Entity(req.user);

  this.getLimitAndCount(opts.query, skip, limit, entity, function(err, items, count){
    if (err) {
      // TODO handle this better
      return next(err);
    }

    if (!items || !__.isArray(items) || 0 === items.length) {
      // TODO handle this better
      return next('no results');
    }

    var paginator = pagination.create('search', {
      prelink: url.parse(req.url).pathname,
      current: page,
      rowsPerPage: limit,
      totalResult: count,
    });

    res.locals.pagination = paginator.render();
    res.locals.items = items;
    res.locals.count = count;
    next();
  });
};


/**
 * Get a limited set of records and the total count.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {crude.Entity} entity an entity instance.
 * @param {Function(Error=, Array, number)} done Callback will contain an
 *   Array of mongoose documents and the total count.
 */
Pagination.prototype.getLimitAndCount = function(query, skip, limit, entity, done) {
  async.parallel([
    entity.readLimit.bind(this.entity, query, skip, limit),
    entity.count.bind(this.entity),
  ], function(err, res){
    if (err) {
      return done(err);
    }
    done(null, res[0], res[1]);
  });
};<commit_msg>fix wrong binding in paginator<commit_after>/**
 * @fileOverview Pagination Middleware.
 */

var url = require('url');

var __ = require('lodash');
var async = require('async');

var sanitize = require('validator').sanitize;
var pagination = require('pagination');

/**
 * The Pagination Middleware.
 *
 * @contructor
 */
var Pagination = module.exports = function(){

};


/**
 * Prepare and configure a pagination middleware.
 *
 * @param {crude.Entity} Entity The Entity class Ctor.
 * @param {Object=} optObj a hash with options.
 * @return {Function} The middleware.
 */
Pagination.prototype.paginate = function(Entity, optOpts) {

  var defaultOpts = {
    limit: 6,
    query: null,
  };
  var opts = __.extend(defaultOpts, optOpts || {});

  this.Entity = Entity;

  return this._paginateMiddleware.bind(this, opts);

};

/**
 * First Middleware
 *
 * @param {Object} opt a hash with options.
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Function(Error=)} next passing control to the next middleware.
 * @private
 */
Pagination.prototype._paginateMiddleware = function(opts, req, res, next) {

  var page = sanitize(req.query.page).toInt() || 1;
  var limit = sanitize(req.query.show).toInt() || opts.limit;
  var skip = (page - 1) * limit;
  var entity = new this.Entity(req.user);

  this.getLimitAndCount(opts.query, skip, limit, entity, function(err, items, count){
    if (err) {
      // TODO handle this better
      return next(err);
    }

    if (!items || !__.isArray(items) || 0 === items.length) {
      // TODO handle this better
      return next('no results');
    }

    var paginator = pagination.create('search', {
      prelink: url.parse(req.url).pathname,
      current: page,
      rowsPerPage: limit,
      totalResult: count,
    });

    res.locals.pagination = paginator.render();
    res.locals.items = items;
    res.locals.count = count;
    next();
  });
};


/**
 * Get a limited set of records and the total count.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {crude.Entity} entity an entity instance.
 * @param {Function(Error=, Array, number)} done Callback will contain an
 *   Array of mongoose documents and the total count.
 */
Pagination.prototype.getLimitAndCount = function(query, skip, limit, entity, done) {
  async.parallel([
    entity.readLimit.bind(entity, query, skip, limit),
    entity.count.bind(entity),
  ], function(err, res){
    if (err) {
      return done(err);
    }
    done(null, res[0], res[1]);
  });
};
{'fraction_non_alphanumeric': 0.14460553568066278, 'fraction_numerical': 0.002259461495010356, 'mean_word_length': 3.37201646090535, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6050040', 'n_tokens_mistral': 1686, 'n_tokens_neox': 1671, 'n_words': 494}