示例#1
0
    def sort_callback(self, a, b):
        ''' Callback to sort the list by specific fields.
    @access private
    @see WP_List_Util::sort()
    @param object|array a One object to compare.
    @param object|array b The other object to compare.
    @return int 0 if both objects equal.
               -1 if second object should come first, 1 otherwise.
    '''
        if Php.empty(self, 'orderby'):
            return 0

        a = Php.Array(a)
        b = Php.Array(b)

        for field, direction in self.orderby.items():
            if not Php.isset(a, field) or not Php.isset(b, field):
                continue
            if a[field] == b[field]:
                continue

            #results = 'DESC' === direction ? array( 1, -1 ) : array( -1, 1 )
            results = array(1, -1) if 'DESC' == direction else array(-1, 1)

            if Php.is_numeric(a[field]) and Php.is_numeric(b[field]):
                #return ( a[ field ] < b[ field ] ) ? results[0] : results[1]
                return results[0] if (a[field] < b[field]) else results[1]

            #return 0 > strcmp( a[ field ], b[ field ] ) ? results[0] : results[1]
            return results[0] if (
                0 > Php.strcmp(a[field], b[field])) else results[1]

        return 0
示例#2
0
文件: wp.py 项目: wordpy/wordpy
    def build_query_string(self):
        ''' Sets the query string property based off of the query variable property.
    The {@see 'query_string'} filter is deprecated, but still works. Plugins should
    use the {@see 'request'} filter instead.
    @access public
    '''
        self.query_string = ''
        for wpvar in Php.Array(Php.array_keys(self.query_vars)):
            if '' != self.query_vars[wpvar]:
                self.query_string += '' if (
                    strlen(self.query_string) < 1) else '&'
                if not is_scalar(
                        self.query_vars[wpvar]):  # Discard non-scalars.
                    continue
                self.query_string += wpvar + '=' + rawurlencode(
                    self.query_vars[wpvar])

        if has_filter(
                'query_string'
        ):  # Don't bother filtering and parsing if no plugins are hooked in.
            # Filters the query string before parsing.
            # @deprecated 2.1.0 Use 'query_vars' or 'request' filters instead.
            # @param string query_string The query string to modify.
            self.query_string = apply_filters('query_string',
                                              self.query_string)
            parse_str(self.query_string, self.query_vars)
示例#3
0
文件: wp.py 项目: wordpy/wordpy
    def register_globals(self):
        ''' Set up the WordPress Globals.
    The query_vars property will be extracted to the GLOBALS. So care should
    be taken when naming global variables that might interfere with the
    WordPress environment.
    @access public
    @global WP_Query     wp_query
    @global string       query_string Query string for the loop.
    @global array        posts The found posts.
    @global WP_Post|None post The current post, if available.
    @global string       request The SQL statement for the request.
    @global int          more Only set, if single page or post.
    @global int          single If single page or post. Only set, if single page or post.
    @global WP_User      authordata Only set, if author archive.
    '''
        wp_query = WpC.WB.Wj.wp_query  # global wp_query
        GLOBALS = WpC.WB.Wj.__dict__  # global GLOBALS

        # Extract updated query vars back into global namespace.
        for key, value in Php.Array(wp_query.query_vars).items():
            GLOBALS[key] = value

        GLOBALS['query_string'] = self.query_string
        #GLOBALS['posts'] = & wp_query.posts
        GLOBALS['posts'] = wp_query.posts  # array is mutable so won't need &
        #GLOBALS['post'] = wp_query.post if Php.isset(wp_query,'post') else None
        GLOBALS['post'] = getattr(wp_query, 'post', None)
        GLOBALS['request'] = wp_query.request

        if wp_query.is_single() or wp_query.is_page():
            GLOBALS['more'] = 1
            GLOBALS['single'] = 1

        if wp_query.is_author() and Php.isset(wp_query, 'post'):
            GLOBALS['authordata'] = get_userdata(wp_query.post.post_author)
示例#4
0
文件: option.py 项目: wordpy/wordpy
def wp_load_alloptions():
    ''' Loads and caches all autoloaded options, if available or all options.
  @global wpdb wpdb WordPress database abstraction object.
  @return array List of all options.
  '''
    wpdb = WpC.WB.Wj.wpdb  # global wpdb

    if not wp_installing() or not WpC.WB.Wj.is_multisite():
        alloptions = WiCa.wp_cache_get('alloptions', 'options')
    else:
        alloptions = False

    if not alloptions:
        suppress = wpdb.suppress_errors()
        alloptions_db = wpdb.get_results(
            "SELECT option_name, option_value FROM "
            "{} WHERE autoload = 'yes'".format(wpdb.options))
        if not alloptions_db:
            alloptions_db = wpdb.get_results(
                "SELECT option_name, option_value FROM " + wpdb.options)
        wpdb.suppress_errors(suppress)
        alloptions = array()
        for o in Php.Array(alloptions_db):
            alloptions[o.option_name] = o.option_value
        if not wp_installing() or not WpC.WB.Wj.is_multisite():
            WiCa.wp_cache_add('alloptions', alloptions, 'options')

    return alloptions
示例#5
0
文件: plugin.py 项目: wordpy/wordpy
def _wp_call_all_hook(args):
    ''' Call the 'all' hook, which will process the functions hooked into it.
  The 'all' hook passes all of the arguments or parameters that were used for
  the hook, which this function was called for.
  This function is used internally for apply_filters(), do_action(), and
  do_action_ref_array() and is not meant to be used from outside those
  functions. This function does not check for the existence of the all hook, so
  it will fail unless the all hook exists prior to this function call.
  @global array wp_filter  Stores all of the filters
  @param array args The collected parameters from the hook that was called.
  '''
    #global var==>WpC.WB.Wj.var, except: var=WpC.WB.Wj.var=same Obj,mutable array
    wp_filter = WpC.WB.Wj.wp_filter  # global wp_filter

    # No need to reset in py since for loop alawys starts at elem#1 in list
    #reset( wp_filter['all'] )

    #do {
    #Php: the first iteration of a do-while loop is guaranteed to run
    #    (the truth expression is only checked at the end of the iteration)
    for Tag in [True, *wp_filter['all']]:
        if Tag is False:
            break
        for the_ in Php.Array(Php.current(wp_filter['all'])):
            if not Php.is_null(the_['function']):
                Php.call_user_func_array(the_['function'], args)
示例#6
0
文件: plugin.py 项目: wordpy/wordpy
def apply_filters_ref_array(tag, args, *OtherArgs):  #Orig: ( tag, args ):
    ''' Execute functions hooked on a specific filter hook, specifying arguments in an array.
  @see apply_filters() This function is identical, but the arguments passed to the
  functions hooked to `tag` are supplied using an array.
  @global array wp_filter         Stores all of the filters
  @global array merged_filters    Merges the filter hooks using this function.
  @global array wp_current_filter Stores the list of current filters with the current one last
  @param string tag  The name of the filter hook.
  @param array  args The arguments supplied to the functions hooked to tag.
  @return mixed The filtered value after all hooked functions are applied to it.
  '''
    #global var==>WB.Wj.var, except: var=WB.Wj.var=same Obj,mutable array
    wp_filter = WpC.WB.Wj.wp_filter  # global wp_filter
    merged_filters = WpC.WB.Wj.merged_filters  # global merged_filters
    wp_current_filter = WpC.WB.Wj.wp_current_filter  # global wp_current_filter

    AllArgs = tag, args, *OtherArgs

    # Do 'all' actions first
    if Php.isset(wp_filter, 'all'):
        wp_current_filter.append(tag)
        # php2python.com/wiki/function.func-get-args/
        all_args = Php.func_get_args(AllArgs)
        _wp_call_all_hook(all_args)

    if not Php.isset(wp_filter, tag):
        if Php.isset(wp_filter, 'all'):
            wp_current_filter.popitem()
        return args[0]

    if not Php.isset(wp_filter, 'all'):
        wp_current_filter.append(tag)

    # Sort
    if not Php.isset(merged_filters, tag):
        wp_filter[tag] = Php.ksort(wp_filter[tag])
        merged_filters[tag] = True

    # No need to reset in py since for loop alawys starts at elem#1 in list
    #reset( wp_filter[ tag ] )

    #do {
    #Php: the first iteration of a do-while loop is guaranteed to run
    #    (the truth expression is only checked at the end of the iteration)
    for Tag in [True, *wp_filter[tag]]:
        if Tag is False:
            break
        for the_ in Php.Array(Php.current(wp_filter[tag])):
            if not Php.is_null(the_['function']):
                args[0] = Php.call_user_func_array(
                    the_['function'],
                    Php.array_slice(args, 0, int(the_['accepted_args'])))
    #} while ( next(wp_filter[tag]) is not False )

    wp_current_filter.popitem()

    return args[0]
示例#7
0
文件: error.py 项目: wordpy/wordpy
 def get_error_messages(self, code=''):
     ''' Retrieve all error messages or error messages matching code.
     @param string|int code Optional.
            Retrieve messages matching code, if exists.
     @return array Error strings on success, or empty array on failure
             (if using code parameter).
             Return all messages if no code specified.
 '''
     if not code:  # if empty
         all_messages = array()  # []
         for code, messages in Php.Array(self.errors.items()):
             all_messages = Php.array_merge(all_messages, messages)
         return all_messages
     if Php.isset(self.errors, code):
         return self.errors[code]
     else:
         return array()
示例#8
0
    def parse_query(self, query=''):
        ''' Parse arguments passed to the term query with default query parameters
    @param string|array query WP_Term_Query arguments. See WP_Term_Query::__construct()
    '''
        if not query:  # if Php.empty(locals(), 'query'):
            query = self.query_vars

        print("WcTQ.parse_query: query=", query)
        taxonomies = Php.Array(query['taxonomy']) if Php.isset(
            query, 'taxonomy') else None
        print("WcTQ.parse_query: taxonomies=", taxonomies)

        # Filters the terms query default arguments.
        # Use {@see 'get_terms_args'} to filter the passed arguments.
        # @param array defaults   An array of default get_terms() arguments.
        # @param array taxonomies An array of taxonomies.
        self.query_var_defaults = WiPg.apply_filters('get_terms_defaults',
                                                     self.query_var_defaults,
                                                     taxonomies)

        query = WiFc.wp_parse_args(query, self.query_var_defaults)
        print("WcTQ.parse_query: query=", query)

        query['number'] = Php.absint(query['number'])
        query['offset'] = Php.absint(query['offset'])

        # 'parent' overrides 'child_of'.
        #must use Php.intval or int(''): invalid literal for int() with base 10: ''
        if 0 < Php.intval(query['parent']):
            query['child_of'] = False

        if 'all' == query['get']:
            query['childless'] = False
            query['child_of'] = 0
            query['hide_empty'] = 0
            query['hierarchical'] = False
            query['pad_counts'] = False

        query['taxonomy'] = taxonomies
        print("WcTQ.parse_query: taxonomies=", taxonomies)

        self.query_vars = query

        # Fires after term query vars have been parsed.
        # @param WP_Term_Query self Current instance of WP_Term_Query.
        WiPg.do_action('parse_term_query', self)
示例#9
0
文件: plugin.py 项目: wordpy/wordpy
def has_filter(tag, function_to_check=False):
    ''' Check if any filter has been registered for a hook.
  @global array wp_filter Stores all of the filters.
  @param string        tag               The name of the filter hook.
  @param callable|bool function_to_check Optional. The callback to check for.
                       Default False.
  @return False|int If function_to_check is omitted, returns boolean for
     whether the hook has anything registered. When checking a specific
     function, the priority of that hook is returned, or False if the function
     is not attached. When using the function_to_check argument, this function
     may return a non-boolean value that evaluates to False (e.g.) 0, so use
     the === operator for testing the return value.
  '''
    # Don't reset the internal array pointer  #VT Need to implement pointer!!!
    wp_filter = WpC.WB.Wj.wp_filter  # = GLOBALS['wp_filter'] = globals()['wp_filter']
    #VT# Since wp_filter shares the same mutable array, need to shallow copy it
    #VT# But there is no array pointer in py, and wp_filter is not modifed below
    #VT# So comment out:  import copy #shallow copy only if array can be changed
    #VT# wp_filter = copy.copy(wp_filter)

    has = not Php.empty(wp_filter, tag)

    # Make sure at least one priority has a filter callback
    if has:
        exists = False
        for callbacks in wp_filter[tag]:
            if callbacks:  # not Php.empty(locals(), 'callbacks'):
                exists = True
                break

        if not exists:
            has = False

    if function_to_check is False or has is False:
        return has

    idx = _wp_filter_build_unique_id(tag, function_to_check, False)
    if not idx:
        return False

    for priority in Php.Array(array_keys(wp_filter[tag])):
        if Php.isset(wp_filter[tag][priority], idx):
            return priority

    return False
示例#10
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
示例#11
0
文件: plugin.py 项目: wordpy/wordpy
def register_uninstall_hook(File, callback):
    ''' Set the uninstallation hook for a plugin.
  Registers the uninstall hook that will be called when the user clicks on the
  uninstall link that calls for the plugin to uninstall itself. The link won't
  be active unless the plugin hooks into the action.
  The plugin should not run arbitrary code outside of functions, when
  registering the uninstall hook. In order to run using the hook, the plugin
  will have to be included, which means that any code laying outside of a
  function will be run during the uninstall process. The plugin should not
  hinder the uninstall process.
  If the plugin can not be written without running code within the plugin, then
  the plugin should create a file named 'uninstall.php' in the base plugin
  folder. This file will be called, if it exists, during the uninstall process
  bypassing the uninstall hook. The plugin, when using the 'uninstall.php'
  should always check for the 'WP_UNINSTALL_PLUGIN' constant, before
  executing.
  @param string   File     Plugin file.
  @param callable callback The callback to run when the hook is called. Must be
                            a static method or function.
  '''
    import wp.i.option as WiO
    if Php.is_array(callback) and Php.is_object(callback[0]):
        _doing_it_wrong(
            register_uninstall_hook.__name__,  # __FUNCTION__,
            __('Only a static class method or function can be used in an uninstall hook.'
               ),
            '3.1.0')
        return

    # The option should not be autoloaded, because it is not needed in most
    # cases. Emphasis should be put on using the 'uninstall.php' way of
    # uninstalling the plugin.
    uninstallable_plugins = Php.Array(WiO.get_option('uninstall_plugins'))
    uninstallable_plugins[plugin_basename(File)] = callback

    WiO.update_option('uninstall_plugins', uninstallable_plugins)
示例#12
0
文件: wp.py 项目: 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 ) )
示例#13
0
文件: plugin.py 项目: wordpy/wordpy
def do_action(tag, arg='', *OtherArgs, Wj=None):
    ''' Execute functions hooked on a specific action hook.
  This function invokes all functions attached to action hook `tag`. It is
  possible to create new action hooks by simply calling this function,
  specifying the name of the new hook using the `tag` parameter.
  You can pass extra arguments to the hooks, much like you can with apply_filters().
  @global array wp_filter         Stores all of the filters
  @global array wp_actions        Increments the amount of times action was triggered.
  @global array merged_filters    Merges the filter hooks using this function.
  @global array wp_current_filter Stores the list of current filters with the current one last
  @param string tag     The name of the action to be executed.
  @param mixed  arg,... Optional. Additional arguments which are passed on to the
                         functions hooked to the action. Default empty.
  '''
    #global var==>WpC.WB.Wj.var, except: var=WpC.WB.Wj.var=same Obj,mutable array
    if Wj is None:
        Wj = WpC.WB.Wj
    wp_filter = Wj.wp_filter  # global wp_filter
    wp_actions = Wj.wp_actions  # global wp_actions
    merged_filters = Wj.merged_filters  # global merged_filters
    wp_current_filter = Wj.wp_current_filter  # global wp_current_filter

    AllArgs = tag, arg, *OtherArgs

    if not Php.isset(wp_actions, tag):
        wp_actions[tag] = 1
    else:
        wp_actions[tag] += 1

    # Do 'all' actions first
    if Php.isset(wp_filter, 'all'):
        wp_current_filter.append(tag)
        # php2python.com/wiki/function.func-get-args/
        all_args = Php.func_get_args(AllArgs)
        _wp_call_all_hook(all_args)

    if not Php.isset(wp_filter, tag):
        if Php.isset(wp_filter, 'all'):
            wp_current_filter.popitem()
        return

    if not Php.isset(wp_filter, 'all'):
        wp_current_filter.append(tag)

    args = array()
    # 1 == len(arg) #implies: isset(arg[0])
    if Php.is_array(arg) and 1 == len(arg) and Php.is_object(
            arg[0]):  # array(&this)
        #args.append(& arg[0])    # & <<== Check!!  # & not needed for object?
        args.append(arg[0])
    else:
        args.append(arg)
    #for ( a = 2, num = func_num_args(); a < num; a++ )
    for a in range(2, Php.func_num_args(AllArgs)):
        args[None] = Php.func_get_arg(AllArgs, a)  # differ from func_get_args

    # Sort
    if not Php.isset(merged_filters, tag):
        wp_filter[tag] = Php.ksort(wp_filter[tag])
        merged_filters[tag] = True

    # No need to reset in py since for loop alawys starts at elem#1 in list
    #reset( wp_filter[ tag ] )

    #do {
    #Php: the first iteration of a do-while loop is guaranteed to run
    #    (the truth expression is only checked at the end of the iteration)
    for Tag in [True, *wp_filter[tag]]:
        if Tag is False:
            break
        for the_ in Php.Array(Php.current(wp_filter[tag])):
            if not Php.is_null(the_['function']):
                Php.call_user_func_array(
                    the_['function'],
                    Php.array_slice(args, 0, int(the_['accepted_args'])))

    #} while ( next(wp_filter[tag]) is not False )

    wp_current_filter.popitem()
示例#14
0
    def set_props(self, object_type, args):
        ''' Sets taxonomy properties.
    @access public
    @param array|str object_type Name of the object type for the taxonomy obj
    @param array|str args        Array or query string of arguments for
                                 registering a taxonomy.
    '''
        Wj = self.Wj
        import wp.i.taxonomy as WiTx
        args = WiFc.wp_parse_args(args)

        # Filters the arguments for registering a taxonomy.
        # @param array args        Array of arguments for registering a taxonomy.
        # @param str   taxonomy    Taxonomy key.
        # @param array object_type Array of names of object types for the taxonomy
        args = WiPg.apply_filters('register_taxonomy_args',
                                  args,
                                  self.name,
                                  Php.Array(object_type),
                                  Wj=self.Wj)

        defaults = array(
            ('labels', array()),
            ('description', ''),
            ('public', True),
            ('publicly_queryable', None),
            ('hierarchical', False),
            ('show_ui', None),
            ('show_in_menu', None),
            ('show_in_nav_menus', None),
            ('show_tagcloud', None),
            ('show_in_quick_edit', None),
            ('show_admin_column', False),
            ('meta_box_cb', None),
            ('capabilities', array()),
            ('rewrite', True),
            ('query_var', self.name),
            ('update_count_callback', ''),
            ('_builtin', False),
        )

        args = Php.array_merge(defaults, args)

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

        if False is not args['query_var'] and (
                Wj.is_admin() or False is not args['publicly_queryable']):
            if True is args['query_var']:
                args['query_var'] = self.name
            else:
                args['query_var'] = WiF.sanitize_title_with_dashes(
                    args['query_var'])
        else:
            # Force query_var to False for non-public taxonomies.
            args['query_var'] = False

        if False is not args['rewrite'] and (
                Wj.is_admin() or '' != WiO.get_option('permalink_structure')):
            args['rewrite'] = WiFc.wp_parse_args(
                args['rewrite'],
                array(
                    ('with_front', True),
                    ('hierarchical', False),
                    ('ep_mask', 'EP_NONE'),
                ))

            if Php.empty(args['rewrite'], 'slug'):
                args['rewrite']['slug'] = WiF.sanitize_title_with_dashes(
                    self.name)

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

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

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

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

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

        default_caps = array(
            ('manage_terms', 'manage_categories'),
            ('edit_terms', 'manage_categories'),
            ('delete_terms', 'manage_categories'),
            ('assign_terms', 'edit_posts'),
        )

        args['cap'] = Php.Object(
            Php.array_merge(default_caps, args['capabilities']))
        Php.unset(args, 'capabilities')

        args['object_type'] = Php.array_unique(Php.Array(object_type))

        # If not set, use the default meta box
        if None is args['meta_box_cb']:
            if args['hierarchical']:
                args['meta_box_cb'] = 'post_categories_meta_box'
            else:
                args['meta_box_cb'] = 'post_tags_meta_box'

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

        self.labels = WiTx.get_taxonomy_labels(self)  # pass self.Wj
        self.label = self.labels.name
示例#15
0
文件: plugin.py 项目: wordpy/wordpy
def _wp_filter_build_unique_id(tag, function, priority, Wj=None):
    ''' Build Unique ID for storage and retrieval.
  The old way to serialize the callback caused issues and this function is the
  solution. It works by checking for objects and creating a new property in
  the class to keep track of the object and new objects of the same class that
  need to be added.
  It also allows for the removal of actions and filters for objects after they
  change class properties. It is possible to include the property wp_filter_id
  in your class and set it to "None" or a number to bypass the workaround.
  However this will prevent you from adding new classes and any new classes
  will overwrite the previous hook by the same class.
  Functions and static method callbacks are just returned as strings and
  shouldn't have any speed penalty.
  @link https://core.trac.wordpress.org/ticket/3875
  @global array wp_filter Storage for all of the filters and actions.
  @staticvar int filter_id_count
  @param string   tag      Used in counting how many hooks were applied
  @param callable function Used for creating unique id
  @param int|bool priority Used in counting how many hooks were applied. If === False
                            and function is an object reference, we return the unique
                            id only if it already has one, False otherwise.
  @return string|False Unique ID for usage as array key or False if priority === False
                       and function is an object reference, and it does not already have
                       a unique id.
  '''
    #global var==>WpC.WB.Wj.var, except: var=WpC.WB.Wj.var=same Obj,mutable array
    if Wj is None:
        Wj = WpC.WB.Wj
    wp_filter = Wj.wp_filter  # global wp_filter
    #static filter_id_count = 0

    if Php.is_string(function):
        return function

    if Php.is_object(function):
        # Closures are currently implemented as objects
        function = array(function, '')
    else:
        function = Php.Array(function)

    if Php.is_object(function[0]):
        # Object Class Calling
        if Php.function_exists('spl_object_hash'):
            return spl_object_hash(function[0]) + function[1]
        else:
            obj_idx = get_class(function[0]).function[1]
            if not Php.isset(function[0], 'wp_filter_id'):
                if priority is False:
                    return False
                obj_idx += (len(Php.Array(wp_filter[tag][priority]))
                            if Php.isset(wp_filter[tag], priority) else
                            _wp_filter_build_unique_id.filter_id_count)
                function[
                    0].wp_filter_id = _wp_filter_build_unique_id.filter_id_count
                _wp_filter_build_unique_id.filter_id_count += 1
            else:
                obj_idx += function[0].wp_filter_id

            return obj_idx

    elif Php.is_string(function[0]):
        # Static Calling
        return function[0] + '::' + function[1]
示例#16
0
def wp_generate_tag_cloud( tags, args = '' ):
  ''' Generates a tag cloud (heatmap) from provided data.
  @todo Complete functionality.
  @param array tags List of tags.
  @param string|array args {
      Optional. Array of string of arguments for generating a tag cloud.
      @type int      smallest                   Smallest font size used to display tags. Paired
                                                 with the value of `unit`, to determine CSS text
                                                 size unit. Default 8 (pt).
      @type int      largest                    Largest font size used to display tags. Paired
                                                 with the value of `unit`, to determine CSS text
                                                 size unit. Default 22 (pt).
      @type string   unit                       CSS text size unit to use with the `smallest`
                                                 and `largest` values. Accepts any valid CSS text
                                                 size unit. Default 'pt'.
      @type int      number                     The number of tags to return. Accepts any
                                                 positive integer or zero to return all.
                                                 Default 0.
      @type string   format                     Format to display the tag cloud in. Accepts 'flat'
                                                 (tags separated with spaces), 'list' (tags displayed
                                                 in an unordered list), or 'array' (returns an array).
                                                 Default 'flat'.
      @type string   separator                  HTML or text to separate the tags. Default "\n" (newline).
      @type string   orderby                    Value to order tags by. Accepts 'name' or 'count'.
                                                 Default 'name'. The {@see 'tag_cloud_sort'} filter
                                                 can also affect how tags are sorted.
      @type string   order                      How to order the tags. Accepts 'ASC' (ascending),
                                                 'DESC' (descending), or 'RAND' (random). Default 'ASC'.
      @type int|bool filter                     Whether to enable filtering of the final output
                                                 via {@see 'wp_generate_tag_cloud'}. Default 1|True.
      @type string   topic_count_text           Nooped plural text from _n_noop() to supply to
                                                 tag tooltips. Default None.
      @type callable topic_count_text_callback  Callback used to generate nooped plural text for
                                                 tag tooltips based on the count. Default None.
      @type callable topic_count_scale_callback Callback used to determine the tag count scaling
                                                 value. Default default_topic_count_scale().
  }
  @return string|array Tag cloud as a string or an array, depending on 'format' argument.
  '''
  defaults = array(
    ('smallest', 8), ('largest', 22), ('unit', 'pt'), ('number', 0),
    ('format','flat'), ('separator',"\n"), ('orderby','name'),('order','ASC'),
    ('topic_count_text', None), ('topic_count_text_callback', None),
    ('topic_count_scale_callback', 'default_topic_count_scale'), ('filter',1),
  )

  args = wp_parse_args( args, defaults )

  Return = array() if ( 'array' == args['format'] ) else ''

  if Php.empty( tags ):
    return Return

  # Juggle topic count tooltips:
  if Php.isset( args, 'topic_count_text' ):
    # First look for nooped plural support via topic_count_text.
    translate_nooped_plural = args['topic_count_text']
  elif not Php.empty( args['topic_count_text_callback'] ):
    # Look for the alternative callback style. Ignore the previous default.
    if args['topic_count_text_callback'] == 'default_topic_count_text':
      translate_nooped_plural = _n_noop( '%s topic', '%s topics' )
    else:
      translate_nooped_plural = False

  elif Php.isset( args, 'single_text' ) and Php.isset( args, 'multiple_text' ):
    # If no callback exists, look for the old-style single_text and multiple_text arguments.
    translate_nooped_plural = _n_noop( args['single_text'], args['multiple_text'] )
  else:
    # This is the default for when no callback, plural, or argument is passed in.
    translate_nooped_plural = _n_noop( '%s topic', '%s topics' )

  # Filters how the items in a tag cloud are sorted.
  # @param array tags Ordered array of terms.
  # @param array args An array of tag cloud arguments.
  tags_sorted = WiPg.apply_filters( 'tag_cloud_sort', tags, args )
  if Php.empty( tags_sorted ):
    return Return

  if tags_sorted != tags:
    tags = tags_sorted
    unset( tags_sorted )
  else:
    if 'RAND' == args['order']:
      shuffle( tags )
    else:
      # SQL cannot save you; this is a second (potentially different) sort on a subset of data.
      if 'name' == args['orderby']:
        uasort( tags, '_wp_object_name_sort_cb' )
      else:
        uasort( tags, '_wp_object_count_sort_cb' )

      if 'DESC' == args['order']:
        tags = array_reverse( tags, True )

  if args['number'] > 0:
    tags = array_slice( tags, 0, args['number'] )

  counts = array()
  real_counts = array(); # For the alt tag
  for key, tag in Php.Array(tags).items():
    real_counts[ key ] = tag.count
    counts[ key ] = Php.call_user_func( args['topic_count_scale_callback'], tag.count )

  # Php min() = Php.Min() here is is different from the py builtin min() !!
  min_count = Php.Min( counts )
  # Php max() = Php.Max() here is is different from the py builtin max() !!
  spread = Php.Max( counts ) - min_count
  if spread <= 0:
    spread = 1
  font_spread = args['largest'] - args['smallest']
  if font_spread < 0:
    font_spread = 1
  font_step = font_spread / spread

  # Assemble the data that will be used to generate the tag cloud markup.
  tags_data = array()
  for key, tag in tags.items():
    tag_id = tag.id if Php.isset( tag, id ) else key

    count = counts[ key ]
    real_count = real_counts[ key ]

    if translate_nooped_plural:
      title = Php.sprintf( translate_nooped_plural( translate_nooped_plural, real_count ), number_format_i18n( real_count ) )
    else:
      title = Php.call_user_func( args['topic_count_text_callback'], real_count, tag, args )

    Php.ArrayAppend( tags_data, array(
      ('id'        , tag_id),
      ('url'       , tag.link if '#' != tag.link else '#'),
      ('name'	     , tag.name),
      ('title'     , title),
      ('slug'      , tag.slug),
      ('real_count', real_count),
      ('class'	   , 'tag-link-' + tag_id),
      ('font_size' , args['smallest'] + ( count - min_count ) * font_step),
    ) )

  # Filters the data used to generate the tag cloud.
  # @param array tags_data An array of term data for term used to generate the tag cloud.
  tags_data = WiPg.apply_filters( 'wp_generate_tag_cloud_data', tags_data )

  a = array()

  # generate the output links array
  for key, tag_data in tags_data.items():
    Class = tag_data['class'] + ' tag-link-position-' + ( key + 1 )
    Php.ArrayAppend(a, "<a href='" + esc_url( tag_data['url'] ) + "' class='" + esc_attr( Class ) + "' title='" + esc_attr( tag_data['title'] ) + "' style='font-size: " + esc_attr( str_replace( ',', '.', tag_data['font_size'] ) + args['unit'] ) + ";'>" + esc_html( tag_data['name'] ) + "</a>")

  #switch ( args['format'] ) {
  if   args['format'] == 'array' :
    Return = a    # no need for php: & a, since a is a mutable array
  elif args['format'] == 'list' :
    Return = "<ul class='wp-tag-cloud'>\n\t<li>"
    Return += join( "</li>\n\t<li>", a )
    Return += "</li>\n</ul>\n"
  else:
    Return = join( args['separator'], a )

  if args['filter']:
    # Filters the generated output of a tag cloud.
    # The filter is only evaluated if a True value is passed
    # to the filter argument in wp_generate_tag_cloud().
    # @see wp_generate_tag_cloud()
    # @param array|string Return String containing the generated HTML tag cloud output
    #                             or an array of tag links if the 'format' argument
    #                             equals 'array'.
    # @param array        tags   An array of terms used in the tag cloud.
    # @param array        args   An array of wp_generate_tag_cloud() arguments.
    return WiPg.apply_filters( 'wp_generate_tag_cloud', Return, tags, args )

  else:
    return Return
示例#17
0
文件: meta.py 项目: wordpy/wordpy
def delete_metadata(meta_type,
                    object_id,
                    meta_key,
                    meta_value='',
                    delete_all=False):
    ''' Delete metadata for the specified object.
  @global wpdb wpdb WordPress database abstraction object.
  @param string meta_type  Type of object metadata is for (e.g., comment, post, or user)
  @param int    object_id  ID of the object metadata is for
  @param string meta_key   Metadata key
  @param mixed  meta_value Optional. Metadata value. Must be serializable if
                           non-scalar. If specified, only delete metadata
                           entries with this value. Otherwise, delete all
                           entries with the specified meta_key.
                           Pass `None, `False`, or an empty string to skip
                           this check.
  @param bool   delete_all Optional, default is False. If True, delete
                           matching metadata entries for all objects,
                           ignoring the specified object_id. Otherwise, only
                           delete matching metadata entries for
                           the specified object_id.
  @return bool True on successful delete, False on failure.
  '''
    #global var==>WpC.WB.Wj.var, except: var=WpC.WB.Wj.var=same Obj,mutable array
    wpdb = WpC.WB.Wj.wpdb  # global wpdb

    if (not meta_type or not meta_key
            or not isinstance(object_id, int) and not delete_all):
        return False

    object_id = abs(object_id)
    if not object_id and not delete_all:
        return False

    table = _get_meta_table(meta_type)
    if not table:
        return False

    type_column = WiF.sanitize_key(meta_type + '_id')
    id_column = 'umeta_id' if 'user' == meta_type else 'meta_id'
    # expected_slashed (meta_key)
    meta_key = WiF.wp_unslash(meta_key)
    meta_value = WiF.wp_unslash(meta_value)

    # Filter whether to delete metadata of a specific type.
    # The dynamic portion of the hook, `meta_type`, refers to the meta
    # object type (comment, post, or user). Returning a non-None value
    # will effectively short-circuit the function.
    # @param None|bool delete  Whether to allow metadata deletion of given type
    # @param int    object_id  Object ID.
    # @param string meta_key   Meta key.
    # @param mixed  meta_value Meta value. Must be serializable if non-scalar.
    # @param bool   delete_all Whether to delete the matching metadata entries
    #         for all objects, ignoring the specified object_id.  Default False
    check = WiPg.apply_filters("delete_{}_metadata".format(meta_type), None,
                               object_id, meta_key, meta_value, delete_all)
    if check is not None:
        return bool(check)

    _meta_value = meta_value
    meta_value = WiFc.maybe_serialize(meta_value)

    Sql = "SELECT {} FROM {} WHERE meta_key = %s".format(id_column, table)
    #SqlDict= (meta_key,)
    query = wpdb.prepare(Sql, meta_key)

    if not delete_all:
        # PyMySQL convert int & all to formatted quoted str. Can only use %s!!
        #Sql    += " AND {} = %s".format(type_column)   # changed from %d to %s
        query += wpdb.prepare(" AND {} = %s".format(type_column), object_id)
        #SqlDict+= (object_id, )
    #if '' != meta_value and meta_value is not None and False is not meta_value:
    if meta_value:
        Sql += wpdb.prepare(" AND meta_value = %s", meta_value)
        #SqlDict+= (meta_value, )

    #RowDicts = wDB.GetDB(MetaC, table).Exec(Sql, SqlDict)
    #meta_ids = [ Row(id_column) for Row in RowDicts ]
    meta_ids = wpdb.get_col(query)
    print(RowDicts, "\n meta_ids=", meta_ids)
    if not Php.count(meta_ids):  #if not meta_ids:
        return False

    if delete_all:
        value_clause = ''
        #value_tuple  = ()
        #if '' != meta_value and meta_value is not None and False != meta_value:
        if meta_value:
            value_clause = wpdb.prepare(" AND meta_value = %s", meta_value)
            #value_tuple  = (meta_value, )

        Sql = ("SELECT {} FROM {} WHERE meta_key = %s {}".format(
            type_column, table, value_clause))
        #RowDicts = wDB.GetDB(MetaC, table).Exec(Sql, (meta_key,)+ value_tuple )
        #object_ids = [ Row(id_column) for Row in RowDicts ]
        object_ids = wpdb.get_col(wpdb.prepare(Sql, meta_key))

    # Fires immediately before deleting metadata of a specific type.
    # The dynamic portion of the hook, `meta_type`, refers to the meta
    # object type (comment, post, or user).
    # @param array  meta_ids   An array of metadata entry IDs to delete.
    # @param int    object_id  Object ID.
    # @param string meta_key   Meta key.
    # @param mixed  meta_value Meta value.
    WiPg.do_action("delete_{}_meta".format(meta_type), Php.Array(meta_ids),
                   object_id, meta.meta_key, meta._meta_value)

    # Old-style action.
    if 'post' == meta_type:
        # Fires immediately before deleting metadata for a post.
        # @since 2.9.0
        # @param array meta_ids An array of post metadata entry IDs to delete.
        WiPg.do_action('delete_postmeta', meta_ids)

    query = ("DELETE FROM {} WHERE {} IN( {} )".format(table, id_column,
                                                       ','.join(meta_ids)))
    #count= wDB.GetDB(MetaC, table).Exec(query)
    count = wpdb.query(query)

    if not count:
        return False

    if delete_all:
        for o_id in Php.Array(object_ids):
            WiCa.wp_cache_delete(o_id, meta_type + '_meta')
    else:
        WiCa.wp_cache_delete(object_id, meta_type + '_meta')

    # Fires immediately after deleting metadata of a specific type.
    # The dynamic portion of the hook name, `meta_type`, refers to the meta
    # object type (comment, post, or user).
    # @param array  meta_ids   An array of deleted metadata entry IDs.
    # @param int    object_id  Object ID.
    # @param string meta_key   Meta key.
    # @param mixed  meta_value Meta value.
    WiPg.do_action("deleted_{}_meta".format(meta_type), Php.Array(meta_ids),
                   object_id, meta.meta_key, meta._meta_value)
    return True
示例#18
0
文件: plugin.py 项目: wordpy/wordpy
def apply_filters(tag, value, *OtherArgs, Wj=None):
    ''' Call the functions added to a filter hook.
  The callback functions attached to filter hook tag are invoked by calling
  this function. This function can be used to create a new filter hook by
  simply calling this function with the name of the new hook specified using
  the tag parameter.
  The function allows for additional arguments to be added and passed to hooks.
      # Our filter callback function
      function example_callback( string, arg1, arg2 ) {
          # (maybe) modify string
          return string
      }
      add_filter( 'example_filter', 'example_callback', 10, 3 )
      /*
       * Apply the filters by calling the 'example_callback' function we
       * "hooked" to 'example_filter' using the add_filter() function above.
       * - 'example_filter' is the filter hook tag
       * - 'filter me' is the value being filtered
       * - arg1 and arg2 are the additional arguments passed to the callback.
      value = apply_filters( 'example_filter', 'filter me', arg1, arg2 )

  @global array wp_filter         Stores all of the filters.
  @global array merged_filters    Merges the filter hooks using this function.
  @global array wp_current_filter Stores the list of current filters with the current one last.
  @param string tag     The name of the filter hook.
  @param mixed  value   The value on which the filters hooked to `tag` are applied on.
  @param mixed  var,... Additional variables passed to the functions hooked to `tag`.
  @return mixed The filtered value after all hooked functions are applied to it.
  '''
    #global var==>WB.Wj.var, except: var=WB.Wj.var=same Obj,mutable array
    if Wj is None:
        Wj = WpC.WB.Wj
    wp_filter = Wj.wp_filter  # global wp_filter
    merged_filters = Wj.merged_filters  # global merged_filters
    wp_current_filter = Wj.wp_current_filter  # global wp_current_filter

    AllArgs = tag, value, *OtherArgs
    #print("WiPg.apply_filters:", tag, value, OtherArgs)

    args = array()

    # Do 'all' actions first.
    if Php.isset(wp_filter, 'all'):
        wp_current_filter.append(tag)
        args = Php.func_get_args(AllArgs)
        _wp_call_all_hook(args)

    if not Php.isset(wp_filter, tag):
        if Php.isset(wp_filter, 'all'):
            wp_current_filter.popitem()
        return value

    if not Php.isset(wp_filter, 'all'):
        wp_current_filter.append(tag)

    # Sort.
    if not Php.isset(merged_filters, tag):
        wp_filter[tag] = Php.ksort(wp_filter[tag])
        merged_filters[tag] = True

    # No need to reset in py since for loop alawys starts at elem#1 in list
    Php.reset(wp_filter[tag])

    if not args:  # Php.empty(locals(), 'args'):
        args = Php.func_get_args(AllArgs)

    #do {
    #Php: the first iteration of a do-while loop is guaranteed to run
    #    (the truth expression is only checked at the end of the iteration)
    #for Tag in [True, *wp_filter[tag] ]:
    #  if Tag is False:
    #    break
    for Tag in wp_filter[tag]:
        if Tag is False:
            break
        #for the_ in Php.Array( Php.current(wp_filter[tag])):
        for the_ in Php.Array(Tag):
            if not Php.is_null(the_['function']):
                args[1] = value
                value = Php.call_user_func_array(
                    the_['function'],
                    Php.array_slice(args, 1, int(the_['accepted_args'])))

    #} while ( next(wp_filter[tag]) is not False )

    wp_current_filter.popitem()

    return value
示例#19
0
    def get_terms(self):
        ''' Get terms, based on query_vars.
    @global wpdb wpdb WordPress database abstraction object.
    @return array
    '''
        import wp.i.taxonomy as WiTx
        wpdb = WpC.WB.Wj.wpdb  # global wpdb

        self.parse_query(self.query_vars)
        args = self.query_vars
        #pprint(self.query_vars)  # TypeError: unhashable type: 'instancemethod'
        # userdata is array, inspect.ismethod(A.__repr__) is True
        print('WP_Term_Query.get_terms: self.query_vars=', self.query_vars)

        # Set up meta_query so it's available to 'pre_get_terms'.
        self.meta_query = WcMQ.WP_Meta_Query()
        self.meta_query.parse_query_vars(args)

        # Fires before terms are retrieved.
        # @param WP_Term_Query self Current instance of WP_Term_Query.
        WiPg.do_action('pre_get_terms', self)

        taxonomies = args['taxonomy']
        print("WcTQ.get_terms: taxonomies=", taxonomies)

        # Save queries by not crawling the tree in the case of multiple taxes or a flat tax.
        has_hierarchical_tax = False
        if taxonomies:
            for _tax in taxonomies:
                if WiTx.is_taxonomy_hierarchical(_tax):
                    has_hierarchical_tax = True

        if not has_hierarchical_tax:
            args['hierarchical'] = False
            args['pad_counts'] = False

        # 'parent' overrides 'child_of'.
        if 0 < Php.intval(args['parent']):
            args['child_of'] = False

        if 'all' == args['get']:
            args['childless'] = False
            args['child_of'] = 0
            args['hide_empty'] = 0
            args['hierarchical'] = False
            args['pad_counts'] = False

        # Filters the terms query arguments.
        # @param array args       An array of get_terms() arguments.
        # @param array taxonomies An array of taxonomies.
        args = WiPg.apply_filters('get_terms_args', args, taxonomies)
        #pprint(args)  # TypeError: unhashable type: 'instancemethod'
        # userdata is array, inspect.ismethod(A.__repr__) is True
        print('WP_Term_Query.get_terms: args=', args)

        # Avoid the query if the queried parent/child_of term has no descendants.
        child_of = args['child_of']
        parent = args['parent']

        if child_of:
            _parent = child_of
        elif parent:
            _parent = parent
        else:
            _parent = False

        if _parent:
            in_hierarchy = False
            for _tax in taxonomies:
                hierarchy = WiTx._get_term_hierarchy(_tax)

                if Php.isset(hierarchy, _parent):
                    in_hierarchy = True

            if not in_hierarchy:
                return array()

        # 'term_order' is a legal sort order only when joining the relationship
        #    table.
        _orderby = self.query_vars['orderby']
        if 'term_order' == _orderby and Php.empty(self.query_vars,
                                                  'object_ids'):
            _orderby = 'term_id'
        orderby = self.parse_orderby(_orderby)

        if orderby:
            orderby = "ORDER BY " + orderby

        order = self.parse_order(self.query_vars['order'])

        if taxonomies:
            self.sql_clauses['where']['taxonomy'] = (
                "tt.taxonomy IN ('" +
                Php.implode("', '", Php.array_map(WiF.esc_sql, taxonomies)) +
                "')")

        exclude = args['exclude']
        exclude_tree = args['exclude_tree']
        include = args['include']

        inclusions = ''
        if include:  # if not Php.empty(locals(), 'include'):
            exclude = ''
            exclude_tree = ''
            inclusions = Php.implode(',', WiFc.wp_parse_id_list(include))

        if inclusions:  # if not Php.empty(locals(), 'inclusions'):
            self.sql_clauses['where']['inclusions'] = ('t.term_id IN ( ' +
                                                       inclusions + ' )')

        exclusions = array()  # Php.array_map( int, exclusions=List)
        if exclude_tree:  # if not Php.empty(locals(), 'exclude_tree'):
            exclude_tree = WiFc.wp_parse_id_list(exclude_tree)
            excluded_children = exclude_tree
            for extrunk in exclude_tree:
                excluded_children = Php.array_merge(
                    excluded_children,
                    Php.Array(
                        get_terms(
                            taxonomies[0],
                            array(
                                ('child_of', Php.intval(extrunk)),
                                ('fields', 'ids'),
                                ('hide_empty', 0),
                            ))))
            exclusions = Php.array_merge(excluded_children, exclusions)

        if exclude:  # if not Php.empty(locals(), 'exclude'):
            exclusions = Php.array_merge(WiFc.wp_parse_id_list(exclude),
                                         exclusions)

        # 'childless' terms are those without an entry in the flattened term hierarchy.
        childless = bool(args['childless'])
        if childless:
            for _tax in taxonomies:
                term_hierarchy = WiTx._get_term_hierarchy(_tax)
                exclusions = Php.array_merge(Php.array_keys(term_hierarchy),
                                             exclusions)

        if exclusions:  # if not Php.empty(locals(), 'exclusions'):
            exclusions = 't.term_id NOT IN (' + Php.implode(
                ',', Php.array_map(Php.intval, exclusions)) + ')'
        else:
            exclusions = ''

        # Filters the terms to exclude from the terms query.
        # @param string exclusions `NOT IN` clause of the terms query.
        # @param array  args       An array of terms query arguments.
        # @param array  taxonomies An array of taxonomies.
        exclusions = WiPg.apply_filters('list_terms_exclusions', exclusions,
                                        args, taxonomies)

        if exclusions:  # if not Php.empty(locals(), 'exclusions'):
            # Must do string manipulation here for backward compatibility with filter.
            self.sql_clauses['where']['exclusions'] = preg_replace(
                '/^\s*AND\s*/', '', exclusions)

        print("\n WcTQ.get_terms: args['name'] =", args['name'])

        print("WcTQ.get_terms: taxonomies=", taxonomies)
        if not Php.empty(args, 'name'):
            names = Php.Array(args['name'])
            print("WcTQ.get_terms: names=", names, taxonomies)
            #foreach ( names as &_name ) {
            #modify list entries during for loop stackoverflow.com/questions/4081217
            for k, _name in names.items(
            ):  #use enumerate(names) if type(names)=list
                # `sanitize_term_field()` returns slashed data.
                #_name = Php.stripslashes( WiTx.sanitize_term_field(
                #                      'name', _name, 0, Php.reset(taxonomies), 'db'))
                names[k] = Php.stripslashes(
                    WiTx.sanitize_term_field('name', _name, 0,
                                             Php.reset(taxonomies), 'db'))

            print("WcTQ.get_terms: names=", names, taxonomies)
            self.sql_clauses['where']['name'] = "t.name IN ('" + Php.implode(
                "', '", Php.array_map(WiF.esc_sql, names)) + "')"

        if not Php.empty(args, 'slug'):
            if Php.is_array(args['slug']):
                slug = Php.array_map(WiF.sanitize_title, args['slug'])
                self.sql_clauses['where'][
                    'slug'] = "t.slug IN ('" + Php.implode("', '", slug) + "')"
            else:
                slug = WiF.sanitize_title(args['slug'])
                self.sql_clauses['where']['slug'] = "t.slug = 'slug'"

        if not Php.empty(args, 'term_taxonomy_id'):
            if Php.is_array(args['term_taxonomy_id']):
                tt_ids = Php.implode(
                    ',', Php.array_map(Php.intval, args['term_taxonomy_id']))
                self.sql_clauses['where']['term_taxonomy_id'] = \
                                            "tt.term_taxonomy_id IN ({})".format(tt_ids)
            else:
                self.sql_clauses['where']['term_taxonomy_id'] = wpdb.prepare(
                    "tt.term_taxonomy_id = %s",
                    args['term_taxonomy_id'])  # PyMySQL %d->%s

        if not Php.empty(args, 'name__like'):
            self.sql_clauses['where']['name__like'] = wpdb.prepare(
                "t.name LIKE %s",
                '%' + wpdb.esc_like(args['name__like']) + '%')

        if not Php.empty(args, 'description__like'):
            self.sql_clauses['where']['description__like'] = wpdb.prepare(
                "tt.description LIKE %s",
                '%' + wpdb.esc_like(args['description__like']) + '%')

        if not Php.empty(args, 'object_ids'):
            object_ids = args['object_ids']
            if not Php.is_array(object_ids):
                object_ids = array(object_ids)

            object_ids = Php.implode(', ',
                                     Php.array_map(Php.intval, object_ids))
            self.sql_clauses['where'][
                'object_ids'] = "tr.object_id IN ({})".format(object_ids)

        # When querying for object relationships, the 'count > 0' check
        # added by 'hide_empty' is superfluous.
        if not Php.empty(args['object_ids']):
            args['hide_empty'] = False

        if '' != parent:
            parent = Php.intval(parent)
            self.sql_clauses['where']['parent'] = "tt.parent = 'parent'"

        hierarchical = args['hierarchical']
        if 'count' == args['fields']:
            hierarchical = False
        if args['hide_empty'] and not hierarchical:
            self.sql_clauses['where']['count'] = 'tt.count > 0'

        number = args['number']
        offset = args['offset']

        # Don't limit the query results when we have to descend the family tree.
        if number and not hierarchical and not child_of and '' == parent:
            if offset:
                limits = 'LIMIT ' + offset + ',' + number
            else:
                limits = 'LIMIT ' + number
        else:
            limits = ''

        if not Php.empty(args, 'search'):
            self.sql_clauses['where']['search'] = self.get_search_sql(
                args['search'])

        # Meta query support.
        join = ''
        distinct = ''

        # Reparse meta_query query_vars, in case they were modified in a 'pre_get_terms' callback.
        self.meta_query.parse_query_vars(self.query_vars)
        mq_sql = self.meta_query.get_sql('term', 't', 'term_id')
        meta_clauses = self.meta_query.get_clauses()

        if not Php.empty(args, 'meta_clauses'):
            join += mq_sql['join']
            self.sql_clauses['where']['meta_query'] = preg_replace(
                '/^\s*AND\s*/', '', mq_sql['where'])
            distinct += "DISTINCT"

        selects = array()
        #switch ( args['fields'] ) {
        #  case 'all':
        AF = args['fields']
        if AF in ('all', 'all_with_object_id', 'tt_ids', 'slugs'):
            selects = array('t.*', 'tt.*')
            if ('all_with_object_id' == args['fields']
                    and not Php.empty(args, 'object_ids')):
                selects[None] = 'tr.object_id'

        #elif AF in ('ids', 'id=>parent'):
        elif AF in ('ids', 'id=>parent', 'id.parent'):
            selects = array('t.term_id', 'tt.parent', 'tt.count',
                            'tt.taxonomy')
        elif AF == 'names':
            selects = array('t.term_id', 'tt.parent', 'tt.count', 't.name',
                            'tt.taxonomy')
        elif AF == 'count':
            orderby = ''
            order = ''
            selects = array('COUNT(*)', )
        #elif AF == 'id=>name':
        elif AF in ('id=>name', 'id.name'):
            selects = array('t.term_id', 't.name', 'tt.count', 'tt.taxonomy')
        #elif AF == 'id=>slug':
        elif AF in ('id=>slug', 'id.slug'):
            selects = array('t.term_id', 't.slug', 'tt.count', 'tt.taxonomy')

        _fields = args['fields']

        # Filters the fields to select in the terms query.
        # Field lists modified using this filter will only modify the term fields returned
        # by the function when the `fields` parameter set to 'count' or 'all'. In all other
        # cases, the term fields in the results array will be determined by the `fields`
        # parameter alone.
        # Use of this filter can result in unpredictable behavior, and is not recommended.
        # @param array selects    An array of fields to select for the terms query.
        # @param array args       An array of term query arguments.
        # @param array taxonomies An array of taxonomies.
        fields = Php.implode(
            ', ',
            WiPg.apply_filters('get_terms_fields', selects, args, taxonomies))
        join += (" INNER JOIN " + wpdb.term_taxonomy +
                 " AS tt ON t.term_id = tt.term_id")

        if not Php.empty(self.query_vars, 'object_ids'):
            join += (" INNER JOIN {} AS tr ON tr.term_taxonomy_id = "
                     "tt.term_taxonomy_id".format(wpdb.term_relationships))
        where = Php.implode(' AND ', self.sql_clauses['where'])

        # Filters the terms query SQL clauses.
        # @param array pieces     Terms query SQL clauses.
        # @param array taxonomies An array of taxonomies.
        # @param array args       An array of terms query arguments.
        pieces = ('fields', 'join', 'where', 'distinct', 'orderby', 'order',
                  'limits')
        clauses = WiPg.apply_filters('terms_clauses',
                                     Php.compact(locals(), pieces), taxonomies,
                                     args)

        #fields = isset( clauses[ 'fields' ] ) ? clauses[ 'fields' ] : ''
        fields = clauses.get('fields', '')
        join = clauses.get('join', '')
        where = clauses.get('where', '')
        distinct = clauses.get('distinct', '')
        orderby = clauses.get('orderby', '')
        order = clauses.get('order', '')
        limits = clauses.get('limits', '')

        if where:
            where = "WHERE " + where

        self.sql_clauses['select'] = "SELECT {} {}".format(distinct, fields)
        self.sql_clauses['from'] = "FROM {} AS t {}".format(wpdb.terms, join)
        self.sql_clauses['orderby'] = orderby + " " + order if orderby else ''
        self.sql_clauses['limits'] = limits

        #self.request = "{self.sql_clauses['select']} {self.sql_clauses['from']} {where} {self.sql_clauses['orderby']} {self.sql_clauses['limits']}"
        self.request = "{} {} {} {} {}".format(self.sql_clauses['select'],
                                               self.sql_clauses['from'], where,
                                               self.sql_clauses['orderby'],
                                               self.sql_clauses['limits'])

        # args can be anything. Only use the args defined in defaults to compute the key.
        key = Php.md5(
            Php.serialize(
                WiFc.wp_array_slice_assoc(
                    args, Php.array_keys(self.query_var_defaults))) +
            Php.serialize(taxonomies) + self.request)
        last_changed = WiFc.wp_cache_get_last_changed('terms')
        cache_key = "get_terms:{}:{}".format(key, last_changed)
        cache = WiCa.wp_cache_get(cache_key, 'terms')
        if False != cache:
            if 'all' == _fields:
                cache = Php.array_map(WiTx.get_term, cache)

            self.terms = cache
            print("WcTQ get_terms 1 self.terms=", self.terms)
            return self.terms

        if 'count' == _fields:
            count = wpdb.get_var(self.request)
            WiCa.wp_cache_set(cache_key, count, 'terms')
            return count

        terms = wpdb.get_results(self.request)
        print("WcTQ get_terms 2 terms=", terms)
        if 'all' == _fields or 'all_with_object_id' == _fields:
            WiTx.update_term_cache(terms)
        print("WcTQ get_terms 3 terms=", terms)

        # Prime termmeta cache.
        if args['update_term_meta_cache']:
            term_ids = WiFc.wp_list_pluck(terms, 'term_id')
            WiTx.update_termmeta_cache(term_ids)

        print("WcTQ get_terms 4 terms=", terms)
        if not terms:  # if Php.empty(locals(), 'terms'):
            WiCa.wp_cache_add(cache_key, array(), 'terms',
                              WpC.WB.Wj.DAY_IN_SECONDS)
            return array()

        print("WcTQ get_terms 5 terms=", terms)
        if child_of:
            for _tax in taxonomies:
                children = WiTx._get_term_hierarchy(_tax)
                if children:  # if not Php.empty(locals(), 'children'):
                    terms = _get_term_children(child_of, terms, _tax)
                    print("WcTQ get_terms 6 terms=", terms)

        # Update term counts to include children.
        if args['pad_counts'] and 'all' == _fields:
            for _tax in taxonomies:
                _pad_term_counts(terms, _tax)

        # Make sure we show empty categories that have children.
        if hierarchical and args['hide_empty'] and Php.is_array(terms):
            for k, term in terms.items():
                Continue2 = False  #VT added to translate php: continue 2
                if not term.count:
                    children = get_term_children(term.term_id, term.taxonomy)
                    if Php.is_array(children):
                        for child_id in children:
                            child = WiTx.get_term(child_id, term.taxonomy)
                            if child.count:
                                #continue 2
                                Continue2 = True  #VT added to translate php: continue 2
                                continue  #VT added to translate php: continue 2
                    # It really is empty.
                    del terms[k]
                if Continue2:  #VT added to translate php: continue 2
                    continue  #VT added to translate php: continue 2

        print("WcTQ get_terms 7 terms=", terms)

        # When querying for terms connected to objects, we may get
        # duplicate results. The duplicates should be preserved if
        # `fields` is 'all_with_object_id', but should otherwise be
        # removed.
        if not Php.empty(args,
                         'object_ids') and 'all_with_object_id' != _fields:
            _tt_ids = array()  # need to be sperate mutable obj
            _terms = array()  # need to be sperate mutable obj
            for term in terms:
                if Php.isset(_tt_ids, getattr(term, 'term_id', None)):
                    continue
                _tt_ids[term.term_id] = 1
                _terms[None] = term

            terms = _terms

        _terms = array()  # array()
        #if 'id=>parent' == _fields:
        if _fields in ('id=>parent', 'id.parent'):
            for term in terms:
                _terms[term.term_id] = term.parent
        elif 'ids' == _fields:
            #for i,term in enumerate(terms):
            #  _terms[i] = int(term.term_id)
            for term in terms:
                _terms[None] = int(term.term_id)
        elif 'tt_ids' == _fields:
            for term in terms:
                _terms[None] = int(term.term_taxonomy_id)
        elif 'names' == _fields:
            #for i,term in enumerate(terms):
            #  _terms[i] = term.name
            for term in terms:
                _terms[None] = term.name
        elif 'slug' == _fields:
            for term in terms:
                _terms[None] = term.slug
        #elif 'id=>name' == _fields:
        elif _fields in ('id=>name', 'id.name'):
            for term in terms:
                _terms[term.term_id] = term.name
        #elif 'id=>slug' == _fields:
        elif _fields in ('id=>slug', 'id.slug'):
            for term in terms:
                _terms[term.term_id] = term.slug

        if _terms:  # if not Php.empty(locals(), '_terms'):
            terms = _terms

        # Hierarchical queries are not limited, so 'offset' and 'number' must be handled now.
        if hierarchical and number and Php.is_array(terms):
            if offset >= len(terms):
                terms = array()  # array()
            else:
                terms = Php.array_slice(terms, offset, number, True)

        WiCa.wp_cache_add(cache_key, terms, 'terms', WpC.WB.Wj.DAY_IN_SECONDS)

        if 'all' == _fields or 'all_with_object_id' == _fields:
            terms = Php.array_map(WiTx.get_term, terms)

        self.terms = terms
        return self.terms
示例#20
0
文件: wp.py 项目: 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 )