如何正确地覆盖撇号的方法“self.list”

问题描述 投票:1回答:1

我正在尝试通过模拟您可以找到它的语言环境的字段自动过滤一个片段。为了做到这一点,我已经覆盖了我的作品的self.list方法,它可以工作,但我真的不知道我是否以最好的方式完成了它。

我知道我可以使用撇号工作流管理我的项目的不同区域设置,我也可以添加一个过滤器到我的文件并使用它过滤,但这些替代方案都没有解决我的问题,因为我想在片段模式时自动列出它们,它只显示我正在谈论的领域中具有混凝土价值的碎片。

我向您展示了字段声明代码。

{
  name: 'locale',
  label: 'Locale',
  type: 'string',
  contextual: true
}   

我还显示了self.list方法的覆盖。

self.list = function(req, options, callback) {
        var cursor;
        var filters = options.filters || options;
        if (options.chooser) {
          cursor = self.find(req);
        } else {
          cursor = self.findForEditing(req);
        }
        if (options.format === 'allIds') {
          cursor.projection({ _id: 1 });
        } else {
          cursor.perPage(self.options.perPage || 10);
        }
        cursor.queryToFilters(filters);

        var results = {};

        return async.series({

        toCount: function(callback) {
            if (options.format === 'allIds') {
              return callback(null);
            }
            return cursor
            .toCount(function(err, count) {
                if (err) {
                  return callback(err);
                }
                results.total = count;
                results.totalPages = cursor.get('totalPages');
                return callback(null);
            });
        },

        populateFilters: function(callback) {
            if (options.format === 'allIds') {
              return callback(null);
            }

            // Populate manage view filters by the same technique used
            // for the `piecesFilters` option of `apostrophe-pieces-pages`

            var allowedFilters = options.chooser ? _.filter(self.filters, function(item) {
              return item.allowedInChooser !== false;
            }) : self.filters;
            results.filters = {
              options: [],
              q: filters.search,
              choices: {}
            };

            return async.eachSeries(allowedFilters, function(filter, callback) {
            // The choices for each filter should reflect the effect of all filters
            // except this one (filtering by topic pares down the list of categories and
            // vice versa)
              var _cursor = cursor.clone();
              // The default might not be good for our purposes. Set it to
              // `null`, which appropriate filters, like `trash`, understand to mean
              // "I am interested in things that are ignored by default and also live things"
              _cursor[filter.name](null);
              return _cursor.toChoices(filter.name, { legacyFilterChoices: true }, function(err, choices) {
                  if (err) {
                    return callback(err);
                  }
                  // Array of all filter objects allowed in this context:
                  //
                  // results.filters.options = [ { name: 'published', choices: [ ... usual ... ], def: ... } ]
                  //
                  // Single object with a property containing the PRESENT value of EACH filter:
                  //
                  // results.filters.choices = {
                  //   published: true
                  // }
                  var _filter = _.clone(filter);
                  results.filters.options.push(_.assign(_filter, { choices: choices }));
                  // These are the "choices you have made," not the "choices you can make."
                  results.filters.choices[_filter.name] = filters[_filter.name];
                  return callback(null);
              });
            }, callback);

        },

        toArray: function(callback) {
            return cursor
            .toArray(function(err, pieces) {
                if (err) {
                  return callback(err);
                }
                if (options.format === 'allIds') {
                  results.ids = _.pluck(pieces, '_id');
                  return callback(null);
                }
                results.skip = cursor.get('skip');
                results.limit = cursor.get('limit');
                results.page = cursor.get('page');
                for( var i = 0; i < pieces.length; i++){
                  if (typeof pieces[i].locale != 'undefined') {
                    if(pieces[i].locale != req.locale) {
                      pieces.splice(i, 1);
                      i--;
                    }
                    else {
                      if(!self.apos.permissions.can(req, 'admin')) {
                        if(pieces[i].userId != req.user._id) {
                          pieces.splice(i, 1);
                          i--;
                        }
                      }
                    }
                  }
                }
                results.pieces = pieces;
                return callback(null);
            });
        }

        }, function(err) {
        if (err) {
            return callback(err);
        }
        // Helps the frontend display the active sort and filter states
        results.cursor = cursor;
        return callback(null, results);
        });
      };

如您所见,我只重写了toArray函数。我对此有两个主要的疑问。

  1. 它适用于少量碎片,但我不知道它是否能够与大量碎片一起正常工作。
  2. 有没有办法只覆盖toArray函数而不必覆盖所有的self.list方法?

提前致谢!

apostrophe-cms
1个回答
1
投票

首先,我应该注意到apostrophe-workflow确实这样做 - 它只会用适当的workflowLocale获取文档。所以我不确定你是否因为正当理由而拒绝使用该模块。我建议你先给它一个严肃的试驾,并确保你明白它已经提供了什么。

继续讨论你的问题的细节,覆盖整个list方法绝对是最不向前兼容的方法,并没有解决用户可能在前端看到的内容。

此外,在这样的toArray调用之后过滤会破坏分页。前端将要求第1页,并且将查询页面的价值,并且其中只有一半用于语言环境,因此您将获得半页。

您可能会做的是从apostrophe-workflow借用,这说明了这一点(为您的用例简化):

// in lib/modules/YOUR-PIECES-MODULE/lib/cursor.js
module.exports = {
  construct: function(self, options) {
    self.addFilter('workflowLocale', {
      def: true,
      finalize: function() {
        var setting = self.get('workflowLocale');
        if (setting === null) {
          return;
        }
        if (setting === true) {
          setting = self.get('req').locale;
        }
        self.and({ locale: setting });
      }
    }
  }
});

此代码为您的片段类型的游标添加了一个新的游标过滤器方法,以便默认情况下它将通过req.locale自动过滤它们。

尽管如此,这也是工作流为您做的一部分,所以也要考虑到这一点。也许你想要本地化,但根本不想要新的变更提交过程;这可能是这样做的一个很好的理由。

© www.soinside.com 2019 - 2024. All rights reserved.