Exemplo n.º 1
0
def extract_filters(term, app_id=amo.FIREFOX.id, opts=None):
    """
    Pulls all the filtering options out of the term and returns a cleaned term
    and a dictionary of filter names and filter values. Term filters override
    filters found in opts.
    """

    opts = opts or {}
    filters = {}

    # Type filters.
    term, addon_type = extract_from_query(term, 'type', '\w+')
    addon_type = addon_type or opts.get('addon_type')
    if addon_type:
        try:
            atype = int(addon_type)
            if atype in amo.get_addon_search_types():
                filters['type'] = atype
        except ValueError:
            # `addon_type` is not a digit. Try to find it in ADDON_SEARCH_SLUGS.
            atype = amo.ADDON_SEARCH_SLUGS.get(addon_type.lower())
            if atype:
                filters['type'] = atype

    # Platform filters.
    term, platform = extract_from_query(term, 'platform', '\w+')
    platform = platform or opts.get('platform')
    if platform:
        platform = [
            amo.PLATFORM_DICT.get(platform.lower(), amo.PLATFORM_ALL).id
        ]
        if amo.PLATFORM_ALL.id not in platform:
            platform.append(amo.PLATFORM_ALL.id)
        filters['platform__in'] = platform

    # Version filters.
    term, version = extract_from_query(term, 'version', '[0-9.]+')
    version = version or opts.get('version')
    if version:
        filters.update(filter_version(version, app_id))

    # Category filters.
    term, category = extract_from_query(term, 'category', '\w+')
    if category and 'app' in opts:
        category = (Category.objects.filter(
            slug__istartswith=category,
            application=opts['app']).values_list('id', flat=True))
        if category:
            filters['category'] = category[0]

    # Tag filters.
    term, tag = extract_from_query(term, 'tag', '\w+')
    if tag:
        tag = Tag.objects.filter(tag_text=tag).values_list('tag_text',
                                                           flat=True)
        if tag:
            filters['tags__in'] = list(tag)

    return (term, filters)
Exemplo n.º 2
0
def extract_filters(term, app_id=amo.FIREFOX.id, opts=None):
    """
    Pulls all the filtering options out of the term and returns a cleaned term
    and a dictionary of filter names and filter values. Term filters override
    filters found in opts.
    """

    opts = opts or {}
    filters = {}

    # Type filters.
    term, addon_type = extract_from_query(term, 'type', '\w+')
    addon_type = addon_type or opts.get('addon_type')
    if addon_type:
        try:
            atype = int(addon_type)
            if atype in amo.get_addon_search_types():
                filters['type'] = atype
        except ValueError:
            # `addon_type` is not a digit. Try to find it in ADDON_SEARCH_SLUGS.
            atype = amo.ADDON_SEARCH_SLUGS.get(addon_type.lower())
            if atype:
                filters['type'] = atype

    # Platform filters.
    term, platform = extract_from_query(term, 'platform', '\w+')
    platform = platform or opts.get('platform')
    if platform:
        platform = [amo.PLATFORM_DICT.get(platform.lower(),
                                          amo.PLATFORM_ALL).id]
        if amo.PLATFORM_ALL.id not in platform:
            platform.append(amo.PLATFORM_ALL.id)
        filters['platform__in'] = platform

    # Version filters.
    term, version = extract_from_query(term, 'version', '[0-9.]+')
    version = version or opts.get('version')
    if version:
        filters.update(filter_version(version, app_id))

    # Category filters.
    term, category = extract_from_query(term, 'category', '\w+')
    if category and 'app' in opts:
        category = (Category.objects.filter(slug__istartswith=category,
                                            application=opts['app'])
                    .values_list('id', flat=True))
        if category:
            filters['category'] = category[0]

    # Tag filters.
    term, tag = extract_from_query(term, 'tag', '\w+')
    if tag:
        tag = Tag.objects.filter(tag_text=tag).values_list('tag_text',
                                                           flat=True)
        if tag:
            filters['tags__in'] = list(tag)

    return (term, filters)
Exemplo n.º 3
0
    def process_request(self, query, addon_type='ALL', limit=10,
                        platform='ALL', version=None, compat_mode='strict'):
        """
        Query the search backend and serve up the XML.
        """
        limit = min(MAX_LIMIT, int(limit))
        app_id = self.request.APP.id

        filters = {
            'app': app_id,
            'status__in': amo.REVIEWED_STATUSES,
            'is_disabled': False,
            'has_version': True,
        }

        # Opts may get overridden by query string filters.
        opts = {
            'addon_type': addon_type,
            'platform': platform,
            'version': version,
        }

        if self.version < 1.5:
            # By default we show public addons only for api_version < 1.5.
            filters['status__in'] = [amo.STATUS_PUBLIC]

            # Fix doubly encoded query strings.
            try:
                query = urllib.unquote(query.encode('ascii'))
            except UnicodeEncodeError:
                # This fails if the string is already UTF-8.
                pass

        query, qs_filters = extract_filters(query, filters['app'], opts)

        qs = Addon.search().query(or_=name_query(query))
        filters.update(qs_filters)
        if 'type' not in filters:
            # Filter by ALL types, which is really all types except for apps.
            filters['type__in'] = list(amo.get_addon_search_types())
        qs = qs.filter(**filters)

        addons = qs[:limit]
        total = qs.count()

        if waffle.switch_is_active('d2c-api-search'):
            is_d2c = True
            results = []
            for addon in qs:
                compat_version = addon.compatible_version(app_id, version,
                                                          platform,
                                                          compat_mode)
                if compat_version:
                    addon.compat_version = compat_version
                    results.append(addon)
                    if len(results) == limit:
                        break
                else:
                    # We're excluding this addon because there are no
                    # compatible versions. Decrement the total.
                    total -= 1
        else:
            is_d2c = False
            results = addons

        return self.render('api/search.xml', {
            'is_d2c': is_d2c,
            'results': results,
            'total': total,
            # For caching
            'version': version,
            'compat_mode': compat_mode,
        })
Exemplo n.º 4
0
    class _SearchForm(SimpleSearchForm):

        cat = forms.ChoiceField(choices=search_groups, required=False)

        # This gets replaced by a <select> with js.
        lver = forms.ChoiceField(
            # L10n: {0} is the name of an app. Ex: Firefox
            label=_lazy(u'{0} Version').format(unicode(current_app.pretty)),
            choices=get_app_versions(current_app),
            required=False)
        appver = forms.CharField(required=False)

        atype = forms.TypedChoiceField(
            label=_lazy(u'Type'),
            choices=[(t, amo.ADDON_TYPE[t])
                     for t in amo.get_addon_search_types()],
            required=False,
            coerce=int,
            empty_value=amo.ADDON_ANY)

        pid = forms.TypedChoiceField(label=_lazy(u'Platform'),
                                     choices=[
                                         (p[0], p[1].name)
                                         for p in amo.PLATFORMS.iteritems()
                                         if p[1] != amo.PLATFORM_ANY
                                     ],
                                     required=False,
                                     coerce=int,
                                     empty_value=amo.PLATFORM_ANY.id)
        platform = forms.ChoiceField(required=False,
                                     choices=[[p.shortname, p.id]
                                              for p in amo.PLATFORMS.values()])

        sort = forms.ChoiceField(label=_lazy(u'Sort By'),
                                 choices=sort_by,
                                 required=False)

        pp = forms.TypedChoiceField(label=_lazy(u'Per Page'),
                                    choices=zip(per_page, per_page),
                                    required=False,
                                    coerce=int,
                                    empty_value=per_page[0])

        advanced = forms.BooleanField(widget=forms.HiddenInput, required=False)
        tag = forms.CharField(widget=forms.HiddenInput, required=False)
        page = forms.IntegerField(widget=forms.HiddenInput, required=False)

        # Attach these to the form for usage in the template.
        top_level_cat = dict(top_level)

        def clean_platform(self):
            p = self.cleaned_data.get('platform')
            choices = dict(self.fields['platform'].choices)
            return choices.get(p)

        # TODO(jbalogh): when we start using this form for zamboni search, it
        # should check that the appid and lver match up using app_versions.
        def clean(self):
            d = self.cleaned_data
            raw = self.data

            # Set some defaults
            if not d.get('appid'):
                d['appid'] = request.APP.id

            # Since not all categories are listed in this form, we use the raw
            # data.
            if 'cat' in raw:
                if ',' in raw['cat']:
                    try:
                        d['atype'], d['cat'] = map(int, raw['cat'].split(','))
                    except ValueError:
                        d['cat'] = None
                elif raw['cat'] == 'all':
                    d['cat'] = None

            if 'page' not in d or not d['page'] or d['page'] < 1:
                d['page'] = 1
            return d

        def full_clean(self):
            """
            Cleans all of self.data and populates self._errors and
            self.cleaned_data.
            Does not remove cleaned_data if there are errors.
            """
            self._errors = ErrorDict()
            if not self.is_bound:  # Stop further processing.
                return
            self.cleaned_data = {}
            # If the form is permitted to be empty, and none of the form data
            # has changed from the initial data, short circuit any validation.
            if self.empty_permitted and not self.has_changed():
                return
            self._clean_fields()
            self._clean_form()
Exemplo n.º 5
0
    def process_request(self,
                        query,
                        addon_type='ALL',
                        limit=10,
                        platform='ALL',
                        version=None,
                        compat_mode='strict'):
        """
        Query the search backend and serve up the XML.
        """
        limit = min(MAX_LIMIT, int(limit))
        app_id = self.request.APP.id

        filters = {
            'app': app_id,
            'status__in': amo.REVIEWED_STATUSES,
            'is_disabled': False,
            'has_version': True,
        }

        # Opts may get overridden by query string filters.
        opts = {
            'addon_type': addon_type,
            'platform': platform,
            'version': version,
        }

        if self.version < 1.5:
            # By default we show public addons only for api_version < 1.5.
            filters['status__in'] = [amo.STATUS_PUBLIC]

            # Fix doubly encoded query strings.
            try:
                query = urllib.unquote(query.encode('ascii'))
            except UnicodeEncodeError:
                # This fails if the string is already UTF-8.
                pass

        query, qs_filters = extract_filters(query, filters['app'], opts)

        qs = Addon.search().query(or_=name_query(query))
        filters.update(qs_filters)
        if 'type' not in filters:
            # Filter by ALL types, which is really all types except for apps.
            filters['type__in'] = list(amo.get_addon_search_types())
        qs = qs.filter(**filters)

        addons = qs[:limit]
        total = qs.count()

        if waffle.switch_is_active('d2c-api-search'):
            is_d2c = True
            results = []
            for addon in qs:
                compat_version = addon.compatible_version(
                    app_id, version, platform, compat_mode)
                if compat_version:
                    addon.compat_version = compat_version
                    results.append(addon)
                    if len(results) == limit:
                        break
                else:
                    # We're excluding this addon because there are no
                    # compatible versions. Decrement the total.
                    total -= 1
        else:
            is_d2c = False
            results = addons

        return self.render(
            'api/search.xml',
            {
                'is_d2c': is_d2c,
                'results': results,
                'total': total,
                # For caching
                'version': version,
                'compat_mode': compat_mode,
            })