Ejemplo n.º 1
0
    def parse_orderby(self, orderby_raw):
        ''' Parse and sanitize 'orderby' keys passed to the term query.
    @global wpdb wpdb WordPress database abstraction object.
    @param string orderby_raw Alias for the field to order by.
    @return string|False Value to used in the ORDER clause. False otherwise.
    '''
        _orderby = Php.strtolower(orderby_raw)
        maybe_orderby_meta = False

        if Php.in_array(_orderby, array('term_id', 'name', 'slug',
                                        'term_group'), True):
            orderby = "t.$_orderby"
        elif Php.in_array(
                _orderby,
                array('count', 'parent', 'taxonomy', 'term_taxonomy_id',
                      'description'), True):
            orderby = "tt." + _orderby
        elif 'term_order' == _orderby:
            orderby = 'tr.term_order'
        if 'count' == _orderby:
            orderby = 'tt.count'
        elif 'name' == _orderby:
            orderby = 't.name'
        elif 'slug' == _orderby:
            orderby = 't.slug'

        elif 'include' == _orderby and not Php.empty(self.query_vars,
                                                     'include'):
            include = Php.implode(
                ',', WiFc.wp_parse_id_list(self.query_vars['include']))
            orderby = "FIELD( t.term_id, {} )".format(include)
        elif 'none' == _orderby:
            orderby = ''  # elif Php.empty(locals(), '_orderby') or ...
        elif not _orderby or 'id' == _orderby or 'term_id' == _orderby:
            orderby = 't.term_id'
        else:
            orderby = 't.name'

            # This may be a value of orderby related to meta.
            maybe_orderby_meta = True

        # Filters the ORDERBY clause of the terms query.
        # @param string orderby    `ORDERBY` clause of the terms query.
        # @param array  args       An array of terms query arguments.
        # @param array  taxonomies An array of taxonomies.
        orderby = WiPg.apply_filters('get_terms_orderby', orderby,
                                     self.query_vars,
                                     self.query_vars['taxonomy'])

        # Run after the 'get_terms_orderby' filter for backward compatibility.
        if maybe_orderby_meta:
            maybe_orderby_meta = self.parse_orderby_meta(_orderby)
            if maybe_orderby_meta:
                orderby = maybe_orderby_meta

        return orderby
Ejemplo n.º 2
0
Archivo: wp.py Proyecto: wordpy/wordpy
 def add_query_var(self, qv):
     ''' Add name to list of public query variables.
 # @access public
 # @param string qv Query variable name.
 '''
     if not Php.in_array(qv, self.public_query_vars):
         self.public_query_vars.append(qv)
Ejemplo n.º 3
0
    def find_compatible_table_alias(self, clause, parent_query):
        alias = False

        for sibling in parent_query:
            # If the sibling has no alias yet, there's nothing to check.
            if Php.empty(sibling, 'alias'):
                continue

            # We're only interested in siblings that are first-order clauses.
            if not Php.is_array(sibling) or not self.is_first_order_clause(
                    sibling):
                continue

            compatible_compares = array()

            # Clauses connected by OR can share joins as long as they have "positive" operators.
            if 'OR' == parent_query['relation']:
                compatible_compares = array('=', 'IN', 'BETWEEN', 'LIKE',
                                            'REGEXP', 'RLIKE', '>', '>=', '<',
                                            '<=')

            # Clauses joined by AND with "negative" operators share a join only if they also share a key.
            elif (Php.isset(sibling, 'key') and Php.isset(clause, 'key')
                  and sibling['key'] == clause['key']):
                compatible_compares = array('!=', 'NOT IN', 'NOT LIKE')

            clause_compare = clause['compare'].upper()
            sibling_compare = sibling['compare'].upper()
            if (Php.in_array(clause_compare, compatible_compares)
                    and Php.in_array(sibling_compare, compatible_compares)):
                alias = sibling['alias']
                break

        # Filters the table alias identified as compatible with the current clause.
        # @param string|bool alias        Table alias, or False if none was found.
        # @param array       clause       First-order query clause.
        # @param array       parent_query Parent of clause.
        # @param object      self         WP_Meta_Query object.
        return WiPg.apply_filters('meta_query_find_compatible_table_alias',
                                  alias, clause, parent_query, self)
Ejemplo n.º 4
0
    def parse_orderby_meta(self, orderby_raw):
        ''' Generate the ORDER BY clause for an 'orderby' param that is potentially related to a meta query.
    @param string orderby_raw Raw 'orderby' value passed to WP_Term_Query.
    @return string
    '''
        orderby = ''

        # Tell the meta query to generate its SQL, so we have access to table aliases.
        self.meta_query.get_sql('term', 't', 'term_id')
        meta_clauses = self.meta_query.get_clauses()
        if not meta_clauses or not orderby_raw:
            return orderby

        allowed_keys = array()
        primary_meta_key = None
        primary_meta_query = Php.reset(meta_clauses)
        if not Php.empty(primary_meta_query, 'key'):
            primary_meta_key = primary_meta_query['key']
            allowed_keys.append(primary_meta_key)

        allowed_keys.append('meta_value')
        allowed_keys.append('meta_value_num')
        allowed_keys = Php.array_merge(allowed_keys,
                                       Php.array_keys(meta_clauses))

        if not Php.in_array(orderby_raw, allowed_keys, True):
            return orderby

        #switch( orderby_raw ) {
        #  case primary_meta_key:
        #  case 'meta_value':
        if orderby_raw in (primary_meta_key, 'meta_value'):
            if not Php.empty(primary_meta_query, 'type'):
                orderby = "CAST({}.meta_value AS {})".format(
                    primary_meta_query['alias'], primary_meta_query['cast'])
            else:
                orderby = primary_meta_query['alias'] + ".meta_value"

        elif orderby_raw == 'meta_value_num':
            orderby = primary_meta_query['alias'] + ".meta_value+0"

        else:
            if orderby_raw in meta_clauses:
                # orderby corresponds to a meta_query clause.
                meta_clause = meta_clauses[orderby_raw]
                orderby = "CAST({}.meta_value AS {})".format(
                    meta_clause['alias'], meta_clause['cast'])

        return orderby
Ejemplo n.º 5
0
    def filter(self, args=array(), operator='AND'):
        ''' Filters the list, based on a set of key, value arguments.
    @param array  args     Optional. An array of key, value arguments to match
                            against each object. Default empty array.
    @param string operator Optional. The logical operation to perform. 'AND' means
                            all elements from the array must match. 'OR' means only
                            one element needs to match. 'NOT' means no elements may
                            match. Default 'AND'.
    @return array Array of found values.
    '''
        if Php.empty(locals(), 'args'):
            return self.output

        operator = Php.strtoupper(operator)

        if not Php.in_array(operator, array('AND', 'OR', 'NOT'), True):
            return array()

        count = Php.count(args)
        filtered = array()

        for key, obj in self.output.items():
            #print('WP_List_Util.filter key, obj=', key, obj)
            to_match = Php.Array(obj)

            matched = 0
            for m_key, m_value in args.items():
                #print('WP_List_Util.filter m_key, m_value=', m_key, m_value)
                if (Php.array_key_exists(m_key, to_match)
                        and m_value == to_match[m_key]):
                    matched += 1
                    #print('WP_List_Util.filter matched=', matched)

            if (('AND' == operator and matched == count)
                    or ('OR' == operator and matched > 0)
                    or ('NOT' == operator and 0 == matched)):
                filtered[key] = obj
                #print('WP_List_Util.filter filtered[{}]= {}'.format(key, obj))

        self.output = filtered

        return self.output
Ejemplo n.º 6
0
def doing_filter(Filter=None):
    ''' Retrieve the name of a filter currently being processed.
  The function current_filter() only returns the most recent filter or action
  being executed. did_action() returns True once the action is initially
  processed.
  This function allows detection for any filter currently being
  executed (despite not being the most recent filter to fire, in the case of
  hooks called from hook callbacks) to be verified.
  @see current_filter()
  @see did_action()
  @global array wp_current_filter Current filter.
  @param None|string Filter Optional. Filter to check. Defaults to None, which
                             checks if any filter is currently being run.
  @return bool Whether the filter is currently in the stack.
  '''
    #global var==>WpC.WB.Wj.var, except: var=WpC.WB.Wj.var=same Obj,mutable array
    wp_current_filter = WpC.WB.Wj.wp_current_filter  # global wp_current_filter

    if Filter is None:
        return not Php.empty(WpC.WB.Wj.__dict__, 'wp_current_filter')

    return Php.in_array(Filter, wp_current_filter)
Ejemplo n.º 7
0
    def set_props(self, args):
        ''' Sets post type properties.
    @param array|str args arguments for registering a post type.
    '''
        import wp.i.post as WpP
        args = WiFc.wp_parse_args(args)

        # Filters the arguments for registering a post type.
        # @param array  args      Array of arguments for registering a post type.
        # @param string post_type Post type key.
        #args = apply_filters( 'register_post_type_args', args, self.name )

        #has_edit_link = bool( args['_edit_link']) #err: '_edit_link' not in args!
        #has_edit_link = bool( args.get('_edit_link', None) )
        has_edit_link = not Php.empty(args, '_edit_link')

        # Args prefixed with an underscore are reserved for internal use.
        defaults = array(
            ('labels', array()),
            ('description', ''),
            ('public', False),
            ('hierarchical', False),
            ('exclude_from_search', None),
            ('publicly_queryable', None),
            ('show_ui', None),
            ('show_in_menu', None),
            ('show_in_nav_menus', None),
            ('show_in_admin_bar', None),
            ('menu_position', None),
            ('menu_icon', None),
            ('capability_type', 'post'),
            ('capabilities', array()),
            ('map_meta_cap', None),
            ('supports', array()),
            ('register_meta_box_cb', None),
            ('taxonomies', array()),
            ('has_archive', False),
            ('rewrite', True),
            ('query_var', True),
            ('can_export', True),
            ('delete_with_user', None),
            ('_builtin', False),
            ('_edit_link', 'post.php?post=%d'),
        )

        args = Php.array_merge(defaults, args)
        args['name'] = self.name

        # If not set, default to the setting for public.
        if None == args['publicly_queryable']:
            args['publicly_queryable'] = args['public']

        # If not set, default to the setting for public.
        if None == args['show_ui']:
            args['show_ui'] = args['public']

        # If not set, default to the setting for show_ui.
        if None == args['show_in_menu'] or not args['show_ui']:
            args['show_in_menu'] = args['show_ui']

        # If not set, default to the whether the full UI is shown.
        if None == args['show_in_admin_bar']:
            args['show_in_admin_bar'] = bool(args['show_in_menu'])

        # If not set, default to the setting for public.
        if None == args['show_in_nav_menus']:
            args['show_in_nav_menus'] = args['public']

        # If not set, default to True if public, False if publi:
        if None == args['exclude_from_search']:
            args['exclude_from_search'] = not args['public']

        # Back compat with quirky handling in version 3.0. #14122.
        if (Php.empty(args, 'capabilities') and None is args['map_meta_cap']
                and Php.in_array(args['capability_type'], array(
                    'post', 'page'))):
            args['map_meta_cap'] = True

        # If not set, default to False.
        if None == args['map_meta_cap']:
            args['map_meta_cap'] = False

        # If there's no specified edit link and no UI, remove the edit link.
        if not args['show_ui'] and not has_edit_link:
            args['_edit_link'] = ''

        #args['cap']=WpP.get_post_type_capabilities(Php.Object(args))
        args['cap'] = WpP.get_post_type_capabilities(Php.Object(args),
                                                     Wj=self.Wj)
        del args['capabilities']

        if Php.is_array(args['capability_type']):
            args['capability_type'] = args['capability_type'][0]

        if False != args['query_var']:
            if True == args['query_var']:
                args['query_var'] = self.name
            else:
                args['query_var'] = WiF.sanitize_title_with_dashes(
                    args['query_var'])

        if False != args['rewrite'] and (
                self.Wj.is_admin()
                or '' != WiO.get_option('permalink_structure')):
            if not Php.is_array(args['rewrite']):
                args['rewrite'] = array()
            if Php.empty(args['rewrite'], 'slug'):
                args['rewrite']['slug'] = self.name
            if not Php.isset(args['rewrite'], 'with_front'):
                args['rewrite']['with_front'] = True
            if not Php.isset(args['rewrite'], 'pages'):
                args['rewrite']['pages'] = True
            if not Php.isset(args['rewrite'],
                             'feeds') or not args['has_archive']:
                args['rewrite']['feeds'] = bool(args['has_archive'])
            if not Php.isset(args['rewrite'], 'ep_mask'):
                if Php.isset(args, 'permalink_epmask'):
                    args['rewrite']['ep_mask'] = args['permalink_epmask']
                else:
                    args['rewrite']['ep_mask'] = EP_PERMALINK

        for property_name, property_value in args.items():
            setattr(self, property_name, property_value)

        self.labels = WpP.get_post_type_labels(self)
        #print('\n VT self.lables =', self.labels, type(self.labels))

        self.label = self.labels.name
Ejemplo n.º 8
0
    def get_sql_for_clause(self, clause, parent_query, clause_key=''):
        ''' Generate SQL JOIN and WHERE clauses for a first-order query clause.
    "First-order" means that it's an array with a 'key' or 'value'.
    @global wpdb wpdb WordPress database abstraction object.
    @param array  clause       Query clause, passed by reference.
    @param array  parent_query Parent query array.
    @param string clause_key   Optional. The array key used to name the clause
                               in the original `meta_query` parameters. If not
                               provided, a key will be generated automatically
    @return array {
      Array containing JOIN & WHERE SQL clauses to append to a 1st-order query
      @type string join  SQL fragment to append to the main JOIN clause.
      @type string where SQL fragment to append to the main WHERE clause.
    }
    @return array clause    since clause passed by ref, need to return clause
    '''
        wpdb = WpC.WB.Wj.wpdb  # global wpdb

        sql_chunks = array(
            ('where', array()),
            ('join', array()),
        )

        if Php.isset(clause, 'compare'):
            clause['compare'] = clause['compare'].upper()
        else:
            clause['compare'] = 'IN' if (Php.isset(
                clause, 'value') and Php.is_array(clause['value'])) else '='

        if (not Php.in_array(
                clause['compare'],
                array('=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE',
                      'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'EXISTS',
                      'NOT EXISTS', 'REGEXP', 'NOT REGEXP', 'RLIKE'))):
            clause['compare'] = '='

        meta_compare = clause['compare']

        # First build the JOIN clause, if one is required.
        join = ''

        # We prefer to avoid joins if possible. Look for an existing join compatible with this clause.
        alias = self.find_compatible_table_alias(clause, parent_query)
        if False is alias:
            i = len(self.table_aliases)
            alias = 'mt' + i if i else self.meta_table

            # JOIN clauses for NOT EXISTS have their own syntax.
            if 'NOT EXISTS' == meta_compare:
                join += " LEFT JOIN self.meta_table"
                join += " AS " + alias if i else ''
                join += wpdb.prepare(
                    " ON (self.primary_table.self.primary_id_column = {} AND {} = %s )"
                    .format(alias.self.meta_id_column,
                            alias.meta_key), clause['key'])

            # All other JOIN clauses.
            else:
                join += " INNER JOIN self.meta_table"
                join += " AS alias" if i else ''
                join += " ON ( self.primary_table.self.primary_id_column = {} )".format(
                    alias.self.meta_id_column)

            self.table_aliases[None] = alias
            sql_chunks['join'][None] = join

        # Save the alias to this clause, for future siblings to find.
        clause['alias'] = alias

        # Determine the data type.
        _meta_type = clause['type'] if Php.isset(clause, 'type') else ''
        meta_type = self.get_cast_for_type(_meta_type)
        clause['cast'] = meta_type

        # Fallback for clause keys is the table alias. Key must be a string.
        if is_int(clause_key) or not clause_key:
            clause_key = clause['alias']

        # Ensure unique clause keys, so none are overwritten.
        iterator = 1
        clause_key_base = clause_key
        while Php.isset(self.clauses, clause_key):
            clause_key = clause_key_base + '-' + iterator
            iterator += 1

        # Store the clause in our flat array.
        #self.clauses[ clause_key ] =& clause
        # =& is assignment by reference, "means that both vars pointing at the
        #    same data, and nothing is copied anywhere"
        self.clauses[
            clause_key] = clause  # py array or {} are mutable same obj

        # Next, build the WHERE clause.

        # meta_key.
        if 'key' in clause:
            if 'NOT EXISTS' == meta_compare:
                sql_chunks['where'][
                    None] = alias + '.' + self.meta_id_column + ' IS NULL'
            else:
                sql_chunks['where'][None] = wpdb.prepare(
                    "alias.meta_key = %s", trim(clause['key']))

        # meta_value.
        if 'value' in clause:
            meta_value = clause['value']

            if meta_compare in ('IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'):
                if not Php.is_array(meta_value):
                    meta_value = preg_split('/[,\s]+/', meta_value)
            else:
                meta_value = trim(meta_value)

            #switch ( meta_compare ) {
            if meta_compare in ('IN', 'NOT IN'):
                meta_compare_string = '(' + substr(
                    str_repeat(',%s', len(meta_value)), 1) + ')'
                where = wpdb.prepare(meta_compare_string, meta_value)

            elif meta_compare in ('BETWEEN', 'NOT BETWEEN'):
                meta_value = Php.array_slice(meta_value, 0, 2)
                where = wpdb.prepare('%s AND %s', meta_value)

            elif meta_compare in ('LIKE', 'NOT LIKE'):
                meta_value = '%' + wpdb.esc_like(meta_value) + '%'
                where = wpdb.prepare('%s', meta_value)

            # EXISTS with a value is interpreted as '='.
            elif meta_compare == 'EXISTS':
                meta_compare = '='
                where = wpdb.prepare('%s', meta_value)

            # 'value' is ignored for NOT EXISTS.
            elif meta_compare == 'NOT EXISTS':
                where = ''

            else:
                where = wpdb.prepare('%s', meta_value)

            if where:
                if 'CHAR' == meta_type:
                    sql_chunks['where'][None] = "{} {} {}".format(
                        alias.meta_value, meta_compare, where)
                else:
                    sql_chunks['where'][None] = "CAST({} AS {}) {} {}".format(
                        alias.meta_value, meta_type, meta_compare, where)

        # Multiple WHERE clauses (for meta_key and meta_value) should
        # be joined in parentheses.
        if 1 < len(sql_chunks['where']):
            sql_chunks['where'] = array(
                '( ' + Php.implode(' AND ', sql_chunks['where']) + ' )')

        #return sql_chunks
        return sql_chunks, clause  #since clause passed by ref, need to return
Ejemplo n.º 9
0
Archivo: wp.py Proyecto: wordpy/wordpy
    def send_headers(self):
        ''' Sends additional HTTP headers for caching, content type, etc.
    Sets the Content-Type header. Sets the 'error' status (if passed) and optionally exits.
    If showing a feed, it will also send Last-Modified, ETag, and 304 status if needed.
    @since 4.4.0 `X-Pingback` header is added conditionally after posts have been queried in handle_404().
    @access public
    '''
        headers = array()  # array()
        status = None
        exit_required = False

        if is_user_logged_in():
            headers = array_merge(headers, wp_get_nocache_headers())
        if Php.empty(self.query_vars, 'error'):
            status = int(self.query_vars['error'])
            if 404 == status:
                if not is_user_logged_in():
                    headers = array_merge(headers, wp_get_nocache_headers())
                headers['Content-Type'] = get_option(
                    'html_type') + '; charset=' + get_option('blog_charset')
            elif Php.in_array(status, array(403, 500, 502, 503)):
                exit_required = True

        elif Php.empty(self.query_vars, 'feed'):
            headers['Content-Type'] = get_option(
                'html_type') + '; charset=' + get_option('blog_charset')
        else:
            # Set the correct content type for feeds
            Type = self.query_vars['feed']
            if 'feed' == self.query_vars['feed']:
                Type = get_default_feed()

            headers['Content-Type'] = feed_content_type(
                Type) + '; charset=' + get_option('blog_charset')

            # We're showing a feed, so WP is indeed the only thing that last changed
            if (not Php.empty(self.query_vars, 'withcomments')
                    #or False !== strpos( self.query_vars['feed'], 'comments-' )
                    or 'comments-' in self.query_vars['feed'] or
                (Php.empty(self.query_vars, 'withoutcomments') and
                 (not Php.empty(self.query_vars, 'p')
                  or not Php.empty(self.query_vars, 'name')
                  or not Php.empty(self.query_vars, 'page_id')
                  or not Php.empty(self.query_vars, 'pagename')
                  or not Php.empty(self.query_vars, 'attachment')
                  or not Php.empty(self.query_vars, 'attachment_id')))):
                wp_last_modified = mysql2date('D, d M Y H:i:s',
                                              get_lastcommentmodified('GMT'),
                                              False)
            else:
                wp_last_modified = mysql2date('D, d M Y H:i:s',
                                              get_lastpostmodified('GMT'),
                                              False)
            if not wp_last_modified:
                wp_last_modified = date('D, d M Y H:i:s')
            wp_last_modified += ' GMT'

            wp_etag = '"' + md5(wp_last_modified) + '"'
            headers['Last-Modified'] = wp_last_modified
            headers['ETag'] = wp_etag

            # Support for Conditional GET
            if Php.isset(_SERVER, 'HTTP_IF_NONE_MATCH'):
                client_etag = WiF.wp_unslash(_SERVER['HTTP_IF_NONE_MATCH'])
            else:
                client_etag = False

            client_last_modified = '' if Php.empty(
                _SERVER, 'HTTP_IF_MODIFIED_SINCE') else trim(
                    _SERVER['HTTP_IF_MODIFIED_SINCE'])
            # If string is empty, return 0. If not, attempt to parse into a timestamp
            client_modified_timestamp = strtotime(
                client_last_modified) if client_last_modified else 0

            # Make a timestamp for our most recent modification...
            wp_modified_timestamp = strtotime(wp_last_modified)

            if (((client_modified_timestamp >= wp_modified_timestamp) and
                 (client_etag == wp_etag)) if
                (client_last_modified and client_etag) else
                ((client_modified_timestamp >= wp_modified_timestamp) or
                 (client_etag == wp_etag))):
                status = 304
                exit_required = True

        # Filters the HTTP headers before they're sent to the browser.
        # @param array headers The list of headers to be sent.
        # @param WP    self    Current WordPress environment instance.
        headers = apply_filters('wp_headers', headers, self)

        if status:  # if not Php.empty(locals(), 'status'):
            status_header(status)

        # If Last-Modified is set to False, it should not be sent (no-cache situation).
        if (Php.isset(headers, 'Last-Modified')
                and False is headers['Last-Modified']):
            Php.unset(headers, 'Last-Modified')

            # In PHP 5.3+, make sure we are not sending a Last-Modified header.
            if function_exists('header_remove'):
                #@header_remove( 'Last-Modified' )
                header_remove('Last-Modified')
            else:
                # In PHP 5.2, send an empty Last-Modified header, but only as a
                # last resort to override a header already sent. #WP23021
                for header in headers_list():
                    if 0 is stripos(header, 'Last-Modified'):
                        headers['Last-Modified'] = ''
                        break

        for name, field_value in Php.Array(headers).items():
            #@header(name +": "+ field_value)
            header(name + ": " + field_value)

        if exit_required:
            import sys
            sys.exit()

        # Fires once the requested HTTP headers for caching, content type, etc. have been sent.
        # @param WP &self Current WordPress environment instance (passed by reference).
        # remove & from &self since self won't get changed during func call
        WiPG.do_action_ref_array('send_headers', array(self))  # ( &self )
Ejemplo n.º 10
0
Archivo: wp.py Proyecto: wordpy/wordpy
    def parse_request(self, extra_query_vars=''):
        ''' Parse request to find correct WordPress query.
    Sets up the query variables based on the request. There are also many
    filters and actions that can be used to further manipulate the result.
    @access public
    @global WP_Rewrite wp_rewrite
    @param array|string extra_query_vars Set the extra query variables.
    '''
        import wp.i.taxonomy as WiTx
        wp_rewrite = WpC.WB.Wj.wp_rewrite  # global wp_rewrite

        # Filters whether to parse the request.
        # @param bool         bool             Whether or not to parse the request. Default True.
        # @param WP           self             Current WordPress environment instance.
        # @param array|string extra_query_vars Extra passed query variables.
        if not apply_filters('do_parse_request', True, self, extra_query_vars):
            return

        self.query_vars = array()
        post_type_query_vars = array()

        if Php.is_array(extra_query_vars):
            #self.extra_query_vars = & extra_query_vars
            self.extra_query_vars = extra_query_vars  # mutable array don't need &
        elif extra_query_vars:  # elif not Php.empty(locals(),'extra_query_vars'):
            parse_str(extra_query_vars, self.extra_query_vars)
        # Process PATH_INFO, REQUEST_URI, and 404 for permalinks.

        # Fetch the rewrite rules.
        rewrite = wp_rewrite.wp_rewrite_rules()

        if rewrite:  #  if not Php.empty(locals(), 'rewrite'):
            # If we match a rewrite rule, this will be cleared.
            error = '404'
            self.did_permalink = True

            #pathinfo=_SERVER['PATH_INFO'] if Php.isset(_SERVER,'PATH_INFO') else ''
            pathinfo = getattr(_SERVER, 'PATH_INFO', '')
            #list( pathinfo ) = explode( '?', pathinfo )
            pathinfo = Php.explode('?', pathinfo)[0]
            pathinfo = Php.str_replace("%", "%25", pathinfo)

            #list( req_uri ) = explode( '?', _SERVER['REQUEST_URI'] )
            req_uri = Php.explode('?', _SERVER['REQUEST_URI'])[0]
            self = _SERVER['PHP_SELF']
            home_path = trim(parse_url(home_url(), PHP_URL_PATH), '/')
            home_path_regex = sprintf('|^%s|i', preg_quote(home_path, '|'))

            # Trim path info from the end and the leading home path from the
            # front. For path info requests, this leaves us with the requesting
            # filename, if any. For 404 requests, this leaves us with the
            # requested permalink.
            req_uri = Php.str_replace(pathinfo, '', req_uri)
            req_uri = trim(req_uri, '/')
            req_uri = preg_replace(home_path_regex, '', req_uri)
            req_uri = trim(req_uri, '/')
            pathinfo = trim(pathinfo, '/')
            pathinfo = preg_replace(home_path_regex, '', pathinfo)
            pathinfo = trim(pathinfo, '/')
            self = trim(self, '/')
            self = preg_replace(home_path_regex, '', self)
            self = trim(self, '/')

            # The requested permalink is in pathinfo for path info requests and
            #  req_uri for other requests.
            #if not Php.empty(locals(), 'pathinfo') and ...:
            if pathinfo and not Php.preg_match(
                    '|^.*' + wp_rewrite.index + '$|', pathinfo):
                requested_path = pathinfo
            else:
                # If the request uri is the index, blank it out so that we don't try to match it against a rule.
                if req_uri == wp_rewrite.index:
                    req_uri = ''
                requested_path = req_uri

            requested_file = req_uri

            self.request = requested_path

            # Look for matches.
            request_match = requested_path
            if not request_match:  #if Php.empty(locals(), 'request_match'):
                # An empty request could only match against ^$ regex
                if Php.isset(rewrite, '$'):
                    self.matched_rule = '$'
                    query = rewrite['$']
                    matches = array('')
            else:
                for match, query in Php.Array(rewrite).items():
                    # If the requested file is the anchor of the match, prepend it to the path info.
                    #if not Php.empty(locals(), 'requested_file') and ...:
                    if requested_file and Php.strpos(
                            match, requested_file
                    ) is 0 and requested_file != requested_path:
                        request_match = requested_file + '/' + requested_path

                    if (Php.preg_match("#^{}#".format(match), request_match,
                                       matches) or Php.preg_match(
                                           "#^{}#".format(match),
                                           urldecode(request_match), matches)):

                        if wp_rewrite.use_verbose_page_rules and Php.preg_match(
                                '/pagename=\$matches\[([0-9]+)\]/', query,
                                varmatch):
                            # This is a verbose page match, let's check to be sure about it.
                            page = get_page_by_path(matches[varmatch[1]])
                            if not page:
                                continue

                            post_status_obj = get_post_status_object(
                                page.post_status)
                            if (not post_status_obj.public
                                    and not post_status_obj.protected
                                    and not post_status_obj.private
                                    and post_status_obj.exclude_from_search):
                                continue

                        # Got a match.
                        self.matched_rule = match
                        break

            if Php.isset(self, 'matched_rule'):
                # Trim the query of everything up to the '?'.
                query = preg_replace("!^.+\?!", '', query)

                # Substitute the substring matches into the query.
                query = Php.addslashes(WP_MatchesMapRegex.Apply(
                    query, matches))

                self.matched_query = query

                # Parse the query.
                parse_str(query, perma_query_vars)

                # If we're processing a 404 request, clear the error var since we found something.
                if '404' == error:
                    unset(error, _GET['error'])

            # If req_uri is empty or if it is a request for ourself, unset error.
            #if Php.empty(locals(), 'requested_path') and ...:
            if not requested_path or requested_file == self or Php.strpos(
                    _SERVER['PHP_SELF'], 'wp-admin/') is not False:
                unset(error, _GET['error'])

                if (Php.isset(locals(), 'perma_query_vars') and
                        #Php.strpos(_SERVER['PHP_SELF'], 'wp-admin/') is not False ):
                        'wp-admin/' not in _SERVER['PHP_SELF']):
                    del perma_query_vars  # unset( perma_query_vars )

                self.did_permalink = False

        # Filters the query variables whitelist before processing.
        # Allows (publicly allowed) query vars to be added, removed, or changed prior
        # to executing the query. Needed to allow custom rewrite rules using your own arguments
        # to work, or any other custom query variables you want to be publicly available.
        # @param array public_query_vars The array of whitelisted query variables.
        self.public_query_vars = apply_filters('query_vars',
                                               self.public_query_vars)

        for post_type, t in get_post_types(array(), 'objects').items():
            if is_post_type_viewable(t) and t.query_var:
                post_type_query_vars[t.query_var] = post_type

        for wpvar in self.public_query_vars:
            if Php.isset(self.extra_query_vars, wpvar):
                self.query_vars[wpvar] = self.extra_query_vars[wpvar]
            elif Php.isset(_POST, wpvar):
                self.query_vars[wpvar] = _POST[wpvar]
            elif Php.isset(_GET, wpvar):
                self.query_vars[wpvar] = _GET[wpvar]
            elif Php.isset(perma_query_vars, wpvar):
                self.query_vars[wpvar] = perma_query_vars[wpvar]

            if not Php.empty(self.query_vars, wpvar):
                if not Php.is_array(self.query_vars[wpvar]):
                    self.query_vars[wpvar] = str(self.query_vars[wpvar])
                else:
                    for vkey, v in self.query_vars[wpvar].items():
                        if not is_object(v):
                            self.query_vars[wpvar][vkey] = str(v)

                if Php.isset(post_type_query_vars, wpvar):
                    self.query_vars['post_type'] = post_type_query_vars[wpvar]
                    self.query_vars['name'] = self.query_vars[wpvar]

        # Convert urldecoded spaces back into +
        for taxonomy, t in WiTx.get_taxonomies(array(), 'objects').items():
            if t.query_var and Php.isset(self.query_vars, t.query_var):
                self.query_vars[t.query_var] = Php.str_replace(
                    ' ', '+', self.query_vars[t.query_var])

        # Don't allow non-publicly queryable taxonomies to be queried from the
        #     front end.
        if not is_admin():
            for taxonomy, t in WiTx.get_taxonomies(
                    array(('publicly_queryable', False)), 'objects').items():
                # Disallow when set to the 'taxonomy' query var.
                # Non-publicly queryable taxonomies cannot register custom query
                #     vars. See register_taxonomy().
                if (Php.isset(self.query_vars, 'taxonomy')
                        and taxonomy == self.query_vars['taxonomy']):
                    unset(self.query_vars['taxonomy'], self.query_vars['term'])

        # Limit publicly queried post_types to those that are publicly_queryable
        if Php.isset(self.query_vars, 'post_type'):
            queryable_post_types = get_post_types(
                array(('publicly_queryable', True)))
            if not Php.is_array(self.query_vars['post_type']):
                if not Php.in_array(self.query_vars['post_type'],
                                    queryable_post_types):
                    unset(self.query_vars['post_type'])
            else:
                self.query_vars['post_type'] = array_intersect(
                    self.query_vars['post_type'], queryable_post_types)

        # Resolve conflicts between posts with numeric slugs and date archive queries.
        self.query_vars = wp_resolve_numeric_slug_conflicts(self.query_vars)

        for var in Php.Array(self.private_query_vars):
            if Php.isset(self.extra_query_vars, var):
                self.query_vars[var] = self.extra_query_vars[var]

        if Php.isset(locals(), 'error'):
            self.query_vars['error'] = error

        # Filters the array of parsed query variables.
        # @param array query_vars The array of requested query variables.
        self.query_vars = apply_filters('request', self.query_vars)

        # Fires once all query variables for the current request have been parsed.
        # @param WP &self Current WordPress environment instance (passed by reference).
        WiPg.do_action_ref_array('parse_request', array(self))  # &self ) )