def remove_filter(tag, function_to_remove, priority=10): ''' Removes a function from a specified filter hook. This function removes a function attached to a specified filter hook. This method can be used to remove default functions attached to a specific filter hook and possibly replace them with a substitute. To remove a hook, the function_to_remove and priority arguments must match when the hook was added. This goes for both filters and actions. No warning will be given on removal failure. @global array wp_filter Stores all of the filters @global array merged_filters Merges the filter hooks using this function. @param string tag The filter hook to which the function to be removed is hooked. @param callable function_to_remove The name of the function which should be removed. @param int priority Optional. The priority of the function. Default 10. @return bool Whether the function existed before it was removed. ''' function_to_remove = _wp_filter_build_unique_id(tag, function_to_remove, priority) #r= Php.isset( GLOBALS['wp_filter'][ tag ][ priority ], function_to_remove ) r = Php.isset(WpC.WB.Wj.wp_filter[tag][priority], function_to_remove) if r is True: del WpC.WB.Wj.wp_filter[tag][priority][function_to_remove] if Php.empty(WpC.WB.Wj.wp_filter[tag], 'priority'): del WpC.WB.Wj.wp_filter[tag][priority] if Php.empty(WpC.WB.Wj.wp_filter, 'tag'): WpC.WB.Wj.wp_filter[tag] = array() del WpC.WB.Wj.merged_filters[tag] return r
def wp_tag_cloud( args = '' ): ''' Display tag cloud. The text size is set by the 'smallest' and 'largest' arguments, which will use the 'unit' argument value for the CSS text size unit. The 'format' argument can be 'flat' (default), 'list', or 'array'. The flat value for the 'format' argument will separate tags with spaces. The list value for the 'format' argument will format the tags in a UL HTML list. The array value for the 'format' argument will return in PHP array type format. The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'. The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC'. The 'number' argument is how many tags to return. By default, the limit will be to return the top 45 tags in the tag cloud list. The 'topic_count_text' argument is a nooped plural from _n_noop() to generate the text for the tooltip of the tag link. The 'topic_count_text_callback' argument is a function, which given the count of the posts with that tag returns a text for the tooltip of the tag link. The 'post_type' argument is used only when 'link' is set to 'edit'. It determines the post_type passed to edit.php for the popular tags edit links. The 'exclude' and 'include' arguments are used for the get_tags() function. Only one should be used, because only one will be used and the other ignored, if they are both set. @param array|string|None args Optional. Override default arguments. @return void|array Generated tag cloud, only if no failures and 'array' is set for the 'format' argument. Otherwise, this function outputs the tag cloud. ''' defaults = array( ('smallest', 8), ('largest', 22), ('unit', 'pt'), ('number', 45), ('format', 'flat'), ('separator', "\n"), ('orderby', 'name'), ('order', 'ASC'), ('exclude', ''), ('include', ''), ('link', 'view'), ('taxonomy', 'post_tag'), ('post_type', ''), ('echo', True), ) args = wp_parse_args( args, defaults ) tags = get_terms( args['taxonomy'], array_merge( args, [ 'orderby', 'count', 'order', 'DESC' ] ) ); # Always query top tags if Php.empty( tags ) or WpC.WB.Wj.is_wp_error( tags ): return for key, tag in tags.items(): if 'edit' == args['link']: link = get_edit_term_link( tag.term_id, tag.taxonomy, args['post_type'] ) else: link = get_term_link( intval(tag.term_id), tag.taxonomy ) if WpC.WB.Wj.is_wp_error( link ): return tags[ key ].link = link tags[ key ].id = tag.term_id Return = wp_generate_tag_cloud( tags, args ); # Here's where those top tags get sorted according to args # Filters the tag cloud output. # @param string Return HTML output of the tag cloud. # @param array args An array of tag cloud arguments. Return = WiPg.apply_filters( 'wp_tag_cloud', Return, args ) if 'array' == args['format'] or Php.empty(args['echo']): return Return Php.echo( Return)
def parse_orderby_meta(self, orderby_raw): ''' Generate the ORDER BY clause for an 'orderby' param that is potentially related to a meta query. @param string orderby_raw Raw 'orderby' value passed to WP_Term_Query. @return string ''' orderby = '' # Tell the meta query to generate its SQL, so we have access to table aliases. self.meta_query.get_sql('term', 't', 'term_id') meta_clauses = self.meta_query.get_clauses() if not meta_clauses or not orderby_raw: return orderby allowed_keys = array() primary_meta_key = None primary_meta_query = Php.reset(meta_clauses) if not Php.empty(primary_meta_query, 'key'): primary_meta_key = primary_meta_query['key'] allowed_keys.append(primary_meta_key) allowed_keys.append('meta_value') allowed_keys.append('meta_value_num') allowed_keys = Php.array_merge(allowed_keys, Php.array_keys(meta_clauses)) if not Php.in_array(orderby_raw, allowed_keys, True): return orderby #switch( orderby_raw ) { # case primary_meta_key: # case 'meta_value': if orderby_raw in (primary_meta_key, 'meta_value'): if not Php.empty(primary_meta_query, 'type'): orderby = "CAST({}.meta_value AS {})".format( primary_meta_query['alias'], primary_meta_query['cast']) else: orderby = primary_meta_query['alias'] + ".meta_value" elif orderby_raw == 'meta_value_num': orderby = primary_meta_query['alias'] + ".meta_value+0" else: if orderby_raw in meta_clauses: # orderby corresponds to a meta_query clause. meta_clause = meta_clauses[orderby_raw] orderby = "CAST({}.meta_value AS {})".format( meta_clause['alias'], meta_clause['cast']) return orderby
def get_error_codes(self): ''' Retrieve all error codes. return array List of error codes, if available. ''' if Php.empty(self, 'errors'): # if empty return array() # [] return Php.array_keys(self.errors)
def sort(self, orderby=array(), order='ASC', preserve_keys=False): ''' Sorts the list, based on one or more orderby arguments. @param str|array orderby Optional. Either the field name to order by or an array of multiple orderby fields as orderby, order. @param str order Optional. Either 'ASC' or 'DESC'. Only used if orderby is a string. @param bool preserve_keys Optional. Whether to preserve keys.Default False @return array The sorted array. ''' if Php.empty(locals(), 'orderby'): return self.output if is_string(orderby): orderby = array((orderby, order)) for field, direction in orderby.items(): orderby[field] = ('DESC' if 'DESC' == Php.strtoupper(direction) else 'ASC') self.orderby = orderby if preserve_keys: #uasort( self.output, array( self, 'sort_callback' ) ) Php.uasort(self.output, self.sort_callback) else: #usort( self.output, array( self, 'sort_callback' ) ) Php.usort(self.output, self.sort_callback) self.orderby = array() return self.output
def get_instance(post_id): ''' Retrieve WP_Post instance. @static @access public @global wpdb wpdb WordPress database abstraction object. @param int post_id Post ID. @return WP_Post|False Post object, False otherwise. ''' wpdb = WpC.WB.Wj.wpdb # global wpdb import wp.i.post as WpP if (not Php.is_numeric(post_id) or post_id != Php.floor(post_id) or not post_id): return False post_id = int(post_id) _post = WiCc.wp_cache_get(post_id, 'posts') #print('WP_Post.get_instance 1 _post=', _post) if not _post: _post = wpdb.get_row( wpdb.prepare( "SELECT * FROM {} WHERE ID = %s LIMIT 1".format( wpdb.posts), post_id)) # PyMySQL %d->%s if not _post: return False _post = WpP.sanitize_post(_post, 'raw') #print("WP_Post.get_instance _post.ID={} _post = {}" # .format(_post.ID, _post)) WiCc.wp_cache_add(_post.ID, _post, 'posts') elif Php.empty(_post, 'filter'): _post = WpP.sanitize_post(_post, 'raw') return WP_Post(_post)
def get_the_term_list( Id, taxonomy, before = '', sep = '', after = '' ): ''' Retrieve a post's terms as a list with specified format. @param int Id Post ID. @param string taxonomy Taxonomy name. @param string before Optional. Before list. @param string sep Optional. Separate items using this. @param string after Optional. After list. @return string|False|WP_Error A list of terms on success, False if there are no terms, WP_Error on failure. ''' terms = get_the_terms( Id, taxonomy ) if WpC.WB.Wj.is_wp_error( terms ): return terms if Php.empty( terms ): return False links = array() for term in terms: link = get_term_link( term, taxonomy ) if WpC.WB.Wj.is_wp_error( link ): return link Php.ArrayAppend(links, '<a href="' + esc_url( link ) + '" rel="tag">' + term.name + '</a>') # Filters the term links for a given taxonomy. # The dynamic portion of the filter name, `taxonomy`, refers # to the taxonomy slug. # @param array links An array of term links. term_links = WiPg.apply_filters( "term_links-"+ taxonomy, links ) return before + join( sep, term_links ) + after
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 wp_load_core_site_options(site_id=None): ''' Loads and caches certain often requested site options if WpC.WB.Wj.is_multisite() and a persistent cache is not being used. @global wpdb wpdb WordPress database abstraction object. @param int site_id Optional site ID for which to query the options. Defaults to the current site. ''' wpdb = WpC.WB.Wj.wpdb # global wpdb if WpC.WB.Wj.is_multisite() or wp_using_ext_object_cache( ) or wp_installing(): return if Php.empty(locals(), 'site_id'): site_id = wpdb.siteid core_options = array('site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'can_compress_scripts', 'global_terms_enabled', 'ms_files_rewriting') core_options_in = "'" + Php.implode("', '", core_options) + "'" options = wpdb.get_results( wpdb.prepare( "SELECT meta_key, meta_value FROM {} WHERE meta_key IN ({}) AND site_id = %d" .format(wpdb.sitemeta, core_options_in), site_id)) for option in options: key = option.meta_key cache_key = site_id + ":" + key option.meta_value = maybe_unserialize(option.meta_value) WiCa.wp_cache_set(cache_key, option.meta_value, 'site-options')
def parse_orderby(self, orderby_raw): ''' Parse and sanitize 'orderby' keys passed to the term query. @global wpdb wpdb WordPress database abstraction object. @param string orderby_raw Alias for the field to order by. @return string|False Value to used in the ORDER clause. False otherwise. ''' _orderby = Php.strtolower(orderby_raw) maybe_orderby_meta = False if Php.in_array(_orderby, array('term_id', 'name', 'slug', 'term_group'), True): orderby = "t.$_orderby" elif Php.in_array( _orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id', 'description'), True): orderby = "tt." + _orderby elif 'term_order' == _orderby: orderby = 'tr.term_order' if 'count' == _orderby: orderby = 'tt.count' elif 'name' == _orderby: orderby = 't.name' elif 'slug' == _orderby: orderby = 't.slug' elif 'include' == _orderby and not Php.empty(self.query_vars, 'include'): include = Php.implode( ',', WiFc.wp_parse_id_list(self.query_vars['include'])) orderby = "FIELD( t.term_id, {} )".format(include) elif 'none' == _orderby: orderby = '' # elif Php.empty(locals(), '_orderby') or ... elif not _orderby or 'id' == _orderby or 'term_id' == _orderby: orderby = 't.term_id' else: orderby = 't.name' # This may be a value of orderby related to meta. maybe_orderby_meta = True # Filters the ORDERBY clause of the terms query. # @param string orderby `ORDERBY` clause of the terms query. # @param array args An array of terms query arguments. # @param array taxonomies An array of taxonomies. orderby = WiPg.apply_filters('get_terms_orderby', orderby, self.query_vars, self.query_vars['taxonomy']) # Run after the 'get_terms_orderby' filter for backward compatibility. if maybe_orderby_meta: maybe_orderby_meta = self.parse_orderby_meta(_orderby) if maybe_orderby_meta: orderby = maybe_orderby_meta return orderby
def __get(self, key): ''' Getter. @param string key Key to get. @return mixed ''' if key == '_obj': # VT Added as a subclass of Php.stdClass return super().__getattribute__(key) #try: return self._obj[name] #except KeyError: pass import wp.i.post as WpP import wp.i.taxonomy as WpTx if 'page_template' == key and self.__isset(key): return WpP.get_post_meta(self.ID, '_wp_page_template', True) if 'post_category' == key: if WpTx.is_object_in_taxonomy(self.post_type, 'category'): terms = WiCT.get_the_terms(self, 'category') if Php.empty(locals(), 'terms'): return array() return WiFc.wp_list_pluck(terms, 'term_id') if 'tags_input' == key: if WpTx.is_object_in_taxonomy(self.post_type, 'post_tag'): terms = WiCT.get_the_terms(self, 'post_tag') if Php.empty(locals(), 'terms'): return array() return WiFc.wp_list_pluck(terms, 'name') # Rest of the values need filtering. if 'ancestors' == key: value = get_post_ancestors(self) else: value = WpP.get_post_meta(self.ID, key, True) if self.filter: value = WpP.sanitize_post_field(key, value, self.ID, self.filter) return value
def walk_category_dropdown_tree( *AllArgs ): ''' Retrieve HTML dropdown (select) content for category list. @uses Walker_CategoryDropdown to create HTML dropdown content. @see Walker_CategoryDropdown::walk() for parameters and return description. @return string ''' args = Php.func_get_args( AllArgs ) # = array( *AllArgs ) # the user's options are the third parameter if Php.empty( args[2]['walker'] ) or not isinstance( args[2]['walker'], Walker ): walker = Walker_CategoryDropdown() else: walker = args[2]['walker'] return Php.call_user_func_array( array( walker, 'walk' ), args )
def add_supports(self): ''' Sets the features support for the post type. ''' import wp.i.post as WpP if not Php.empty(self, 'supports'): #WpP.add_post_type_support(self.name, self.supports ) WpP.add_post_type_support(self.name, self.supports, Wj=self.Wj) del self.supports elif False != self.supports: # Add default features #WpP.add_post_type_support(self.name, array('title','editor') ) WpP.add_post_type_support(self.name, array('title', 'editor'), Wj=self.Wj)
def delete_option(option): ''' Removes option by name. Prevents removal of protected WordPress options. @global wpdb wpdb WordPress database abstraction object. @param string option Name of option to remove. Expected to not be SQL-escaped @return bool True, if option is successfully deleted. False on failure. ''' wpdb = WpC.WB.Wj.wpdb # global wpdb option = Php.trim(option) if Php.empty(locals(), 'option'): return False wp_protect_special_option(option) # Get the ID, if no ID then return row = wpdb.get_row( wpdb.prepare( "SELECT autoload FROM {} WHERE option_name" " = %s".format(wpdb.options), option)) if Php.is_null(row): return False # Fires immediately before an option is deleted. # @param string option Name of the option to delete. WiPg.do_action('delete_option', option) result = wpdb.delete(wpdb.options, array(('option_name', option))) if not wp_installing(): if 'yes' == row.autoload: alloptions = wp_load_alloptions() if Php.is_array(alloptions) and Php.isset(alloptions, option): del (alloptions[option]) WiCa.wp_cache_set('alloptions', alloptions, 'options') else: WiCa.wp_cache_delete(option, 'options') if result: # Fires after a specific option has been deleted. # The dynamic portion of the hook name, `option`, refers to the option name # @param string option Name of the deleted option. WiPg.do_action("delete_option_" + option, option) # Fires after an option has been deleted. # @param string option Name of the deleted option. WiPg.do_action('deleted_option', option) return True return False
def in_category( category, post = None ): ''' Check if the current post in within any of the given categories. The given categories are checked against the post's categories' term_ids, names and slugs. Categories given as integers will only be checked against the post's categories' term_ids. Prior to v2.5 of WordPress, category names were not supported. Prior to v2.7, category slugs were not supported. Prior to v2.7, only one category could be compared: in_category( single_category ). Prior to v2.7, this function could only be used in the WordPress Loop. As of 2.7, the function can be used anywhere if it is provided a post ID or post object. @param int|string|array category Category ID, name or slug, or array of said. @param int|object post Optional. Post to check instead of the current post. (since 2.7.0) @return bool True if the current post is in any of the given categories. ''' if Php.empty( category ): return False return has_category( category, post )
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 get_sql_clauses(self): ''' Generate SQL clauses to be appended to a main query. Called by the public WP_Meta_Query::get_sql(), this method is abstracted out to maintain parity with the other Query classes. @return array { Array containing JOIN and WHERE SQL clauses to append to the main query. @type string join SQL fragment to append to the main JOIN clause. @type string where SQL fragment to append to the main WHERE clause. } ''' # queries are passed by reference to get_sql_for_query() for recursion. # To keep self.queries unaltered, pass a copy. queries = self.queries sql = self.get_sql_for_query(queries) if not Php.empty(sql, 'where'): sql['where'] = ' AND ' + sql['where'] return sql
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 _get_meta_table(Type): '''Retrieve the name of the metadata table for the specified object Type. @param str Type Type of object to get metadata table for (e.g., comment, post, or user) @return str|False Metadata table name, or False if no metadata table exists ''' #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 wpdb: # print("wpdb in _get_meta_table is empty") # import sys; sys.exit() table_name = Type + 'meta' print("_get_meta_table Type={}; wpdb.{} = {}".format( Type, table_name, getattr(wpdb, table_name, False))) #return getattr(wpdb, table_name, False) #same as: if Php.empty(wpdb, table_name): return False return getattr(wpdb, table_name)
def find_compatible_table_alias(self, clause, parent_query): alias = False for sibling in parent_query: # If the sibling has no alias yet, there's nothing to check. if Php.empty(sibling, 'alias'): continue # We're only interested in siblings that are first-order clauses. if not Php.is_array(sibling) or not self.is_first_order_clause( sibling): continue compatible_compares = array() # Clauses connected by OR can share joins as long as they have "positive" operators. if 'OR' == parent_query['relation']: compatible_compares = array('=', 'IN', 'BETWEEN', 'LIKE', 'REGEXP', 'RLIKE', '>', '>=', '<', '<=') # Clauses joined by AND with "negative" operators share a join only if they also share a key. elif (Php.isset(sibling, 'key') and Php.isset(clause, 'key') and sibling['key'] == clause['key']): compatible_compares = array('!=', 'NOT IN', 'NOT LIKE') clause_compare = clause['compare'].upper() sibling_compare = sibling['compare'].upper() if (Php.in_array(clause_compare, compatible_compares) and Php.in_array(sibling_compare, compatible_compares)): alias = sibling['alias'] break # Filters the table alias identified as compatible with the current clause. # @param string|bool alias Table alias, or False if none was found. # @param array clause First-order query clause. # @param array parent_query Parent of clause. # @param object self WP_Meta_Query object. return WiPg.apply_filters('meta_query_find_compatible_table_alias', alias, clause, parent_query, self)
def doing_filter(Filter=None): ''' Retrieve the name of a filter currently being processed. The function current_filter() only returns the most recent filter or action being executed. did_action() returns True once the action is initially processed. This function allows detection for any filter currently being executed (despite not being the most recent filter to fire, in the case of hooks called from hook callbacks) to be verified. @see current_filter() @see did_action() @global array wp_current_filter Current filter. @param None|string Filter Optional. Filter to check. Defaults to None, which checks if any filter is currently being run. @return bool Whether the filter is currently in the stack. ''' #global var==>WpC.WB.Wj.var, except: var=WpC.WB.Wj.var=same Obj,mutable array wp_current_filter = WpC.WB.Wj.wp_current_filter # global wp_current_filter if Filter is None: return not Php.empty(WpC.WB.Wj.__dict__, 'wp_current_filter') return Php.in_array(Filter, wp_current_filter)
def parse_query_vars(self, qv): ''' Constructs a meta query based on 'meta_*' query vars @param array qv The query variables ''' meta_query = array() # ODict() # array() # For orderby=meta_value to work correctly, simple query needs to be # first (so that its table join is against an unaliased meta table) and # needs to be its own clause (so it doesn't interfere with the logic of # the rest of the meta_query). primary_meta_query = array() # ODict() # array() for key in ('key', 'compare', 'type'): if not Php.empty(qv, "meta_" + key): primary_meta_query[key] = qv["meta_" + key] # WP_Query sets 'meta_value' = '' by default. if Php.isset(qv, 'meta_value') and '' != qv['meta_value'] and ( not Php.is_array(qv['meta_value']) or qv['meta_value']): primary_meta_query['value'] = qv['meta_value'] existing_meta_query = qv['meta_query'] if ( Php.isset(qv, 'meta_query') and Php.is_array( qv['meta_query'])) else array() # ODict() # array() #if not Php.empty(locals(), 'primary_meta_query') and existing_meta_query: if primary_meta_query and existing_meta_query: meta_query = array( # Supports array( ('a',11), 22, 33, (2,22) ) ('relation', 'AND'), primary_meta_query, existing_meta_query, ) elif primary_meta_query: #not Php.empty(locals(),'primary_meta_query'): meta_query = array( # Supports array( ('a',11), 22, 33, (2,22) ) primary_meta_query) elif existing_meta_query: #not Php.empty(locals(),'existing_meta_query'): meta_query = existing_meta_query self.__init__(meta_query)
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 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 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 )
def set_props(self, args): ''' Sets post type properties. @param array|str args arguments for registering a post type. ''' import wp.i.post as WpP args = WiFc.wp_parse_args(args) # Filters the arguments for registering a post type. # @param array args Array of arguments for registering a post type. # @param string post_type Post type key. #args = apply_filters( 'register_post_type_args', args, self.name ) #has_edit_link = bool( args['_edit_link']) #err: '_edit_link' not in args! #has_edit_link = bool( args.get('_edit_link', None) ) has_edit_link = not Php.empty(args, '_edit_link') # Args prefixed with an underscore are reserved for internal use. defaults = array( ('labels', array()), ('description', ''), ('public', False), ('hierarchical', False), ('exclude_from_search', None), ('publicly_queryable', None), ('show_ui', None), ('show_in_menu', None), ('show_in_nav_menus', None), ('show_in_admin_bar', None), ('menu_position', None), ('menu_icon', None), ('capability_type', 'post'), ('capabilities', array()), ('map_meta_cap', None), ('supports', array()), ('register_meta_box_cb', None), ('taxonomies', array()), ('has_archive', False), ('rewrite', True), ('query_var', True), ('can_export', True), ('delete_with_user', None), ('_builtin', False), ('_edit_link', 'post.php?post=%d'), ) args = Php.array_merge(defaults, args) args['name'] = self.name # If not set, default to the setting for public. if None == args['publicly_queryable']: args['publicly_queryable'] = args['public'] # If not set, default to the setting for public. if None == args['show_ui']: args['show_ui'] = args['public'] # If not set, default to the setting for show_ui. if None == args['show_in_menu'] or not args['show_ui']: args['show_in_menu'] = args['show_ui'] # If not set, default to the whether the full UI is shown. if None == args['show_in_admin_bar']: args['show_in_admin_bar'] = bool(args['show_in_menu']) # If not set, default to the setting for public. if None == args['show_in_nav_menus']: args['show_in_nav_menus'] = args['public'] # If not set, default to True if public, False if publi: if None == args['exclude_from_search']: args['exclude_from_search'] = not args['public'] # Back compat with quirky handling in version 3.0. #14122. if (Php.empty(args, 'capabilities') and None is args['map_meta_cap'] and Php.in_array(args['capability_type'], array( 'post', 'page'))): args['map_meta_cap'] = True # If not set, default to False. if None == args['map_meta_cap']: args['map_meta_cap'] = False # If there's no specified edit link and no UI, remove the edit link. if not args['show_ui'] and not has_edit_link: args['_edit_link'] = '' #args['cap']=WpP.get_post_type_capabilities(Php.Object(args)) args['cap'] = WpP.get_post_type_capabilities(Php.Object(args), Wj=self.Wj) del args['capabilities'] if Php.is_array(args['capability_type']): args['capability_type'] = args['capability_type'][0] if False != args['query_var']: if True == args['query_var']: args['query_var'] = self.name else: args['query_var'] = WiF.sanitize_title_with_dashes( args['query_var']) if False != args['rewrite'] and ( self.Wj.is_admin() or '' != WiO.get_option('permalink_structure')): if not Php.is_array(args['rewrite']): args['rewrite'] = array() if Php.empty(args['rewrite'], 'slug'): args['rewrite']['slug'] = self.name if not Php.isset(args['rewrite'], 'with_front'): args['rewrite']['with_front'] = True if not Php.isset(args['rewrite'], 'pages'): args['rewrite']['pages'] = True if not Php.isset(args['rewrite'], 'feeds') or not args['has_archive']: args['rewrite']['feeds'] = bool(args['has_archive']) if not Php.isset(args['rewrite'], 'ep_mask'): if Php.isset(args, 'permalink_epmask'): args['rewrite']['ep_mask'] = args['permalink_epmask'] else: args['rewrite']['ep_mask'] = EP_PERMALINK for property_name, property_value in args.items(): setattr(self, property_name, property_value) self.labels = WpP.get_post_type_labels(self) #print('\n VT self.lables =', self.labels, type(self.labels)) self.label = self.labels.name
def get_sql_for_query(self, query, depth=0): ''' Generate SQL clauses for a single query array. If nested subqueries are found, this method recurses the tree to produce the properly nested SQL. @param array query Query to parse, passed by reference. @param int depth Optional. Number of tree levels deep we currently are. Used to calculate indentation. Default 0. @return array { Array containing JOIN and WHERE SQL clauses to append to a single query array. @type string join SQL fragment to append to the main JOIN clause. @type string where SQL fragment to append to the main WHERE clause. } ''' sql_chunks = array( ('join', array()), ('where', array()), ) sql = array( ('join', ''), ('where', ''), ) indent = '' #for ( i = 0; i < depth; i++ ) { for i in range(depth): indent += " " for key, clause in query.items(): if 'relation' == key: relation = query['relation'] elif Php.is_array(clause): # This is a first-order clause. if self.is_first_order_clause(clause): clause_sql = self.get_sql_for_clause(clause, query, key) where_count = len(clause_sql['where']) if not where_count: sql_chunks['where'][None] = '' elif 1 is where_count: sql_chunks['where'][None] = clause_sql['where'][0] else: sql_chunks['where'][None] = '( ' + Php.implode( ' AND ', clause_sql['where']) + ' )' sql_chunks['join'] = Php.array_merge( sql_chunks['join'], clause_sql['join']) # This is a subquery, so we recurse. else: clause_sql = self.get_sql_for_query(clause, depth + 1) sql_chunks['where'][None] = clause_sql['where'] sql_chunks['join'][None] = clause_sql['join'] # Filter to remove empties. sql_chunks['join'] = Php.array_filter(sql_chunks['join']) sql_chunks['where'] = Php.array_filter(sql_chunks['where']) if Php.empty(locals(), 'relation'): relation = 'AND' # Filter duplicate JOIN clauses and combine into a single string. if not Php.empty(sql_chunks, 'join'): sql['join'] = Php.implode(' ', Php.array_unique(sql_chunks['join'])) # Generate a single WHERE clause with proper brackets and indentation. if not Php.empty(sql_chunks, 'where'): sql['where'] = '( ' + "\n " + indent + Php.implode( ' ' + "\n " + indent + relation + ' ' + "\n " + indent, sql_chunks['where']) + "\n" + indent + ')' return sql
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 handle_404(self): ''' Set the Headers for 404, if nothing is found for requested URL. Issue a 404 if a request doesn't match any posts and doesn't match any object (e.g. an existing-but-empty category, tag, author) and a 404 was not already issued, and if the request was not a search or the homepage. Otherwise, issue a 200. This sets headers after posts have been queried. handle_404() really means "handle status." By inspecting the result of querying posts, seemingly successful requests can be switched to a 404 so that canonical redirection logic can kick in. # @access public @global WP_Query wp_query ''' wp_query = WpC.WB.Wj.wp_query # global wp_query # Filters whether to short-circuit default header status handling. # Returning a non-False value from the filter will short-circuit the handling # and return early. # @param bool preempt Whether to short-circuit default header status handling. Default False. # @param WP_Query wp_query WordPress Query object. if False is not apply_filters('pre_handle_404', False, wp_query): return # If we've already issued a 404, bail. if is_404(): return # Never 404 for the admin, robots, or if we found posts. if is_admin() or is_robots() or wp_query.posts: success = True if is_singular(): p = False import wp.i.cls.post as WcP if isinstance(wp_query.post, WcP.WP_Post): p = Php.clone(wp_query.post) # Only set X-Pingback for single posts that allow pings. if p and pings_open(p): #@header( 'X-Pingback: ' + get_bloginfo( 'pingback_url' ) ) header('X-Pingback: ' + get_bloginfo('pingback_url', 'display')) # check for paged content that exceeds the max number of pages Next = '<!--nextpage-->' #if (p and False !== Php.strpos( p.post_content, Next ) and # self.query_vars['page']): if (p and Next in p.post_content and not Php.empty(self.query_vars, 'page')): page = trim(self.query_vars['page'], '/') success = int(page) <= ( substr_count(p.post_content, Next) + 1) if success: status_header(200) return # We will 404 for paged queries, as no posts were found. if not is_paged(): # Don't 404 for authors without posts as long as they matched an author on self site. author = get_query_var('author') if is_author() and is_numeric( author) and author > 0 and is_user_member_of_blog(author): status_header(200) return # Don't 404 for these queries if they matched an object. if (is_tag() or is_category() or is_tax() or is_post_type_archive()) and get_queried_object(): status_header(200) return # Don't 404 for these queries either. if is_home() or is_search() or is_feed(): status_header(200) return # Guess it's time to 404. wp_query.set_404() status_header(404) nocache_headers()
def wp_initial_constants(self): #global blog_id # VT change to self.blog_id # Constants for expressing human-readable data sizes in their respective number of bytes. self.define('KB_IN_BYTES', 1024) self.define('MB_IN_BYTES', 1024 * self.KB_IN_BYTES) self.define('GB_IN_BYTES', 1024 * self.MB_IN_BYTES) self.define('TB_IN_BYTES', 1024 * self.GB_IN_BYTES) #current_limit = @ini_get( 'memory_limit' ) #current_limit_int = wp_convert_hr_to_bytes( current_limit ) ## Define memory limits. #if not self.defined( 'WP_MEMORY_LIMIT' ): # if False is wp_is_ini_value_changeable( 'memory_limit' ): # self.define( 'WP_MEMORY_LIMIT', current_limit ) # elif WB.Wj.is_multisite(): # self.define( 'WP_MEMORY_LIMIT', '64M' ) # else: # self.define( 'WP_MEMORY_LIMIT', '40M' ) #if not self.defined( 'WP_MAX_MEMORY_LIMIT' ): # if False is wp_is_ini_value_changeable( 'memory_limit' ): # self.define( 'WP_MAX_MEMORY_LIMIT', current_limit ) # elif -1 == current_limit_int or current_limit_int > 268435456: # self.define( 'WP_MAX_MEMORY_LIMIT', current_limit ) #268435456 = 256M # else: # self.define( 'WP_MAX_MEMORY_LIMIT', '256M' ) ## Set memory limits. #wp_limit_int = wp_convert_hr_to_bytes( self.WP_MEMORY_LIMIT ) #if -1 != current_limit_int and ( -1 == wp_limit_int or wp_limit_int > current_limit_int ): # @ini_set( 'memory_limit', self.WP_MEMORY_LIMIT ) #if not isset(blog_id): if not Php.isset(self, 'blog_id'): self.blog_id = 1 if not self.defined('WP_CONTENT_DIR'): self.define('WP_CONTENT_DIR', self.ABSPATH + 'wp-content') # no trailing slash, full paths only - WP_CONTENT_URL is self.defined further down # Add self.define('WP_DEBUG', True); to wp-config.php to enable display of notices during development. if not self.defined('WP_DEBUG'): self.define('WP_DEBUG', False) # Add self.define('WP_DEBUG_DISPLAY', null); to wp-config.php use the globally configured setting for # display_errors and not force errors to be displayed. Use False to force display_errors off. if not self.defined('WP_DEBUG_DISPLAY'): self.define('WP_DEBUG_DISPLAY', True) # Add self.define('WP_DEBUG_LOG', True); to enable error logging to wp-content/debug.log. if not self.defined('WP_DEBUG_LOG'): self.define('WP_DEBUG_LOG', False) if not self.defined('WP_CACHE'): self.define('WP_CACHE', False) # Add self.define('SCRIPT_DEBUG', True); to wp-config.php to enable loading of non-minified, # non-concatenated scripts and stylesheets. if not self.defined('SCRIPT_DEBUG'): #if not empty( GLOBALS['wp_version'] ): if not Php.empty(self, 'wp_version'): #develop_src = False !== strpos( GLOBALS['wp_version'], '-src' ) develop_src = '-src' in self.wp_version else: develop_src = False self.define('SCRIPT_DEBUG', develop_src) # Private if not self.defined('MEDIA_TRASH'): self.define('MEDIA_TRASH', False) if not self.defined('SHORTINIT'): self.define('SHORTINIT', False) # Constants for features added to WP that should short-circuit their plugin implementations self.define('WP_FEATURE_BETTER_PASSWORDS', True) # Constants for expressing human-readable intervals # in their respective number of seconds. # Please note that these values are approximate and are provided for convenience. # For example, MONTH_IN_SECONDS wrongly assumes every month has 30 days and # YEAR_IN_SECONDS does not take leap years into account. # If you need more accuracy please consider using the DateTime class (https://secure.php.net/manual/en/class.datetime.php). self.define('MINUTE_IN_SECONDS', 60) self.define('HOUR_IN_SECONDS', 60 * self.MINUTE_IN_SECONDS) self.define('DAY_IN_SECONDS', 24 * self.HOUR_IN_SECONDS) self.define('WEEK_IN_SECONDS', 7 * self.DAY_IN_SECONDS) self.define('MONTH_IN_SECONDS', 30 * self.DAY_IN_SECONDS) self.define('YEAR_IN_SECONDS', 365 * self.DAY_IN_SECONDS)