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
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)
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)
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
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)
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]
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()
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)
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
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
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)
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 ) )
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()
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
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]
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
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
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
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
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 )