WordPress 'Custom Post Type' gets set to wrong Taxonomy Term IDs - mysql

First and foremost, I need to stress how greatly I appreciate anyone who takes the time to respond - In advance, thank you, thank you, THANK YOU!
I feel pictures are of great service to explaining things, so to start off, here's something of an illustration of the issue:
http://i.stack.imgur.com/b9OXR.png
Preface:
My site has about 400 Posts under the "dir_listing" Custom Post Type
Each "dir_listing" Post can be associated with Terms from the "listing category" Custom Taxonomy and/or "listing_region" Custom Taxonomy
I have about 210 "listing_category" Terms, and 155 "listing region" Terms
The Issue in Summary:
When Publishing or Updating a "dir_listing" Post Type, sometimes the Term IDs get recorded into the 'term_relationships' table without issue, and other times are recorded erroneously.
Even so, when I go back to edit one of the "dir_listing" Post Types the checkboxes for the desired Parent/Child Terms are correctly marked.
Actions that could be Related?
A number of the "listing_category" terms have been shuffled around. (e.g. A Parent term has become a Child term, or vice-versa, or a Child term has been moved to another Parent.)
Both Parent & Child Terms have been renamed without making any changes to the "dir_listing" Post types. (I don't think this matters, since Posts are supposed to be related to Terms by ID #)
A number of Parent Terms and Child Terms may have been deleted by another Admin-level user. This also seems to happen with Child-Terms of the "listing_regions" taxonomy.
How I've Investigated / Tried to Fix It:
Extensively searched WordPress trac (No similar issues reported)
Searched Google for things like *"wordpress tax_input bug"*, "wordpress taxonomy id bug", "wordpress custom taxonomy bug", etc. and found no matching issues
Disabled all plugins, custom rewrites, and other taxonomies
Ensured the checkbox inputs had the correct Taxonomy as their 'name' and Term ID as their 'value'
Hacked the /wp-admin/includes/post.php core file to try to fix it myself. (No luck.)
Posted issue to [WordPress "How-To and Troubleshooting" forum][3] this morning (No replies)
Posted issue to Reddit /r/web_design this afternoon (Also no replies)
I've spent the better part of 8 hours trying to determine the cause of this, or if I'm missing a step by using a custom MySQL query to directly get a list of Posts related to a particular Term ID.
Again, any thoughts or suggestions anyone might have are VERY MUCH appreciated - Thanks!

This info might help you with how the term_id and and term_taxonomy_id work. It seems like there are a lot of conditions that effect the final outcome of how the ids are set.
See the full reference here: http://phpxref.com/xref/wordpress/wp-includes/taxonomy.php.html#wp_insert_term
Also have a look at this trac ticket regarding the need for a posts relationship table and some of the use cases.
get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') X-Ref
Get all Term data from database by Term ID.
The usage of the get_term function is to apply filters to a term object. It
is possible to get a term object from the database before applying the
filters.
$term ID must be part of $taxonomy, to get from the database. Failure, might
be able to be captured by the hooks. Failure would be the same value as $wpdb
returns for the get_row method.
There are two hooks, one is specifically for each term, named 'get_term', and
the second is for the taxonomy name, 'term_$taxonomy'. Both hooks gets the
term object, and the taxonomy name as parameters. Both hooks are expected to
return a Term object.
'get_term' hook - Takes two parameters the term Object and the taxonomy name.
Must return term object. Used in get_term() as a catch-all filter for every
$term.
'get_$taxonomy' hook - Takes two parameters the term Object and the taxonomy
name. Must return term object. $taxonomy will be the taxonomy name, so for
example, if 'category', it would be 'get_category' as the filter name. Useful
for custom taxonomies or plugging into default taxonomies.
param: int|object $term If integer, will get from database. If object will apply filters and return $term.
param: string $taxonomy Taxonomy name that $term is part of.
param: string $output Constant OBJECT, ARRAY_A, or ARRAY_N
param: string $filter Optional, default is raw or no WordPress defined filter will applied.
return: mixed|null|WP_Error Term Row from database. Will return null if $term is empty. If taxonomy does not
get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw') X-Ref
Get all Term data from database by Term field and data.
Warning: $value is not escaped for 'name' $field. You must do it yourself, if
required.
The default $field is 'id', therefore it is possible to also use null for
field, but not recommended that you do so.
If $value does not exist, the return value will be false. If $taxonomy exists
and $field and $value combinations exist, the Term will be returned.
param: string $field Either 'slug', 'name', or 'id'
param: string|int $value Search for this term value
param: string $taxonomy Taxonomy Name
param: string $output Constant OBJECT, ARRAY_A, or ARRAY_N
param: string $filter Optional, default is raw or no WordPress defined filter will applied.
return: mixed Term Row from database. Will return false if $taxonomy does not exist or $term was not found.
get_term_children( $term_id, $taxonomy ) X-Ref
Merge all term children into a single array of their IDs.
This recursive function will merge all of the children of $term into the same
array of term IDs. Only useful for taxonomies which are hierarchical.
Will return an empty array if $term does not exist in $taxonomy.
param: string $term ID of Term to get children
param: string $taxonomy Taxonomy Name
return: array|WP_Error List of Term Objects. WP_Error returned if $taxonomy does not exist

Related

Semantic Mediawiki: aggregation similar to SQL GROUP BY like #ask query

I've implemented a page with a long list of subojects.
Every object contains one article (title + url) and N tags. I'd like to group by tag and show the count of articles related to that tag.
Something like:
SELECT tag, count(distinct article)
GROUP BY tag
I found an answer but it's very generic and I'd also like to document the solution for other user with the same problem.
As you know from previous answers to this question, you cannot have a "distinct" function from an SMW ask query.
My preferred solution is to use the "arrays" extension, that allows you to access PHP array manipulation functions in wiki code. Further than "distinct" list of value, its an irreplaceable tool for handling semantic data from queries.
You can create an array with the following function :
{{#arraydefine: *identifier* | *data* | *delimiter* | *parameters* }}
Identifier is the variable name you want.
Data is the array content, in SMW context, you load it with a query result content.
Delimiter specify the array delimiter relative to data. This have to be
coherent with the delimiter chosen in the ask query.
Parameters is where the magic appends. You can set a "unique" parameter, reducing the data list to unique values, thus, emulating the "distinct" function.
In tour case, you may do something like :
{{#arraydefine:tags
| {{#ask:[[-Has subobject::{{FULLPAGENAME}}]]
|?Tags#-=
| mainlabel=-
|limit = 1000
}}
|,
|unique
}}
Note that SMW ask query are, by default, limited to 50 results. Adding "limit=" adjusts the maximum result size.
At this point, you defined an array called "tags" containing all distinct values of this property.
You can use arrayprint function for any further data treatment or display.

Neo4j gem - Checking each object against a relationship effecient?

Just wanted an opinion on this in terms of design and efficiency.
Let's say you have a social network for liking music.
If you have query like music.users and out of those users you want to identify your friends. Visually you want to add a feature to identify these friends, maybe all your friends have a star on their profile and non friends are left alone.
Is it really inefficient/expensive to be checking each user to see if they are a friend? Alternate methods?
result = music.users(:user)
.optional(:friends, :friend)
.where(neo_id: current_user.neo_id)
.pluck(:user, is_friend: 'friend IS NOT NULL')
This would return an array of tuples: Each user from the association, and a boolean stating if they are friends of the current user
The .optional(:friends, :friend) is like calling .friends(:friend), but is uses an OPTIONAL MATCH instead of a MATCH in cypher for querying the association.
For the is_friend part, that translates to RETURN friend IS NOT NULL AS is_friend. Actually, since this is a pluck, the AS isn't necessary, so it could just be .pluck(:user, 'friend IS NOT NULL'). Since it's doing an OPTIONAL MATCH, the friend variable in the query (which is the current_user) will only be there if the user from the result row is friends with the current_user.
One thing that you can do to help with understanding of what the query chain would do is to call to_cypher to see what query would be generated. In this case, that would be:
puts music.users(:user)
.optional(:friends, :friend)
.where(neo_id: current_user.neo_id)
.return(:user, is_friend: 'friend IS NOT NULL')
.to_cypher
The pluck is a method that returns an array instead of a query chain object, so I replaced it with return in this case.

Connecting one dropdown list to another perl

In Perl, I have script that creates a dropdown list based on a database that contains a list of vendors. I would like to use the selection of the first list to populate the second list with values of different contacts given that specific vendor.
ie. Haliburton is vendor....once this is chosen contact Jim, Paul, George are available in contact list that is next to it.
Currently I am getting the list of vendors and the list of contacts separately. How do I get the list of contacts based on the vendor in the database to be populated in the CGI popup_menu?
The following is my current code:
#!c:\perl\bin\perl.exe
use CGI;
use strict;
use warnings;
require ("data_eXchangeSubs.pm");
$query = new CGI;
print $query->header(-expires=>'-1d');
print $query->start_html(-title=>'Dex Vendor Testing',
-bgcolor=>'white'
);
my $dataX = ${ConnectToDatabase($main::DB1, $main::DBEnv)};
$resultSet = $dataX->Execute("select vendor from vendor_info group by vendor");
my #list_of_vendors;
while(!$resultSet->EOF) {
push #list_of_vendors, $resultSet->Fields("vendor")->Value;
$resultSet->MoveNext;
}
From here, I would like to populate another dropdown list with contacts from the vendor_info data table. Currently I'm making a separate query execution but I would like to take a given vendor from the previous array and populate only those contacts specific to the chosen vendor.
I know I have to change the values of the contacts but don't know how to :(
$resultContact = $dataX->Execute("select contact from vendor_info");
my #list_of_contacts;
while(!$resultContact->EOF) {
push #list_of_contacts, $resultContact->Fields("contact")->Value;
$resultContact->MoveNext;
}
print $query->popup_menu(
-name => 'vendors'
, -values =>\#list_of_vendors
, -default => $default_vendor
, -style=> 'width:200px'
);
print $query->popup_menu(
-name => 'contacts'
, -values => \#list_of_contacts
, -default => $default_vendor
);
print $query->end_html;
This is a very broad question. You have a couple of simple options.
1) Create an HTML form with the list of vendors, take (and sanitize!) the user's selection, and return the list of contacts. This is a traditional dynamic CGI form.
2) Use JavaScript. This only works for a reasonable amount of data. There are several ways to do it but the gist of the idea is: a) associate each contact with the correct vendor, b) hide all the contacts initially, c) when a vendor is selected, display the correct contacts.
JQuery is a handy JavaScript tool for this kind of manipulation and magically hides many browser incompatibility problems.
3) You could create a fancy, modern AJAX-ified form, but from your question, this is probably overkill.
Sorry there is no quick-and-dirty solution but I'm hoping to give you enough here to start Googling in the right direction! Best!
With CGI, you need to use CGI::param method.
# I know the name of the select is "vendors",
# but it makes more sense calling it here with 'vendor'
# *you would have to change the name of the element*
my $vendor_name = $query->param( 'vendor' );
And I'm not sure how your database object works (kind of looks like the Microsoft iteration model), but using the proper way of parameterized queries in DBI, it looks like this:
my $stmt = $dbh->prepare( 'select contact from vendor_info where vendor_name=?' );
$stmt->execute( $vendor_name ); # binds the variable to the query.
Then you step through the rows of the query and build your list of contacts. Of course, you'd mostly likely use fetchrow_array or fetchrow_arrayref methods to walk through them.
Although this might be better off utilizing a more modern strategy by getting a combined list of vendors and contacts for JavaScript or using Ajax to query the contacts for a vendor.
There is no "connecting" structure in basic Perl CGI. You would have to use a more modern web framework for that.

Categories and Keywords access via Razor Template in Tridion

I am attempting to access values in the Categories and Keywords information for a Tridion Publication via a Razor TBB in Tridion 2011. The Razor documentation lists the following example code:
<ul>
#foreach (var keyword in Publication.MetaData.SomeKeywordFields) {
<li>#keyword.Title (#keyword.Id)</li>
}
</ul>
I have a Keyword inside of a Category though... in fact, that's the only way I am myself aware that you can even have a Keyword in Tridion, but correct me if I am wrong. Extrapolating from the example's syntax, I tried the following where "myCategory" is a Category in the publication, and "myKeyword" is a Keyword inside of the myCategory Category:
#foreach (var keyword in Publication.MetaData.myCategory) {
if(#keyword.Title == "myKeyword") {
#keyword.Title
}
When I run this template, I get an error stating that DynamicItemsFields: Key 'testcategory' Not Found In ItemFields (Object reference not set to an instance of an object)
Can anyone help with identifying if it is even possible to do what I am attempting here (as it seems like it is based on the documentation but still not sure) and if so, provide an example of the correct syntax?
You're almost there with your code except that you're using the actual CategoryName. As Puf commented, you have to use the "fieldname" of you Publication Metadata not the actual CategoryName. You should just change the "myCategory" to the actual fieldname
#foreach (var keyword in Publication.MetaData.*<<FIELDNAME>>*) {
if(#keyword.Title == "myKeyword") {
#keyword.Title
}
}
[FIELDNAME] --> is the XMLName of publication metadata schema.
Keywords are indeed always within a Category or another Keyword. But they are used within items like Components and (as in the example) metadata on Publications, Folders, etc.
The example from the documentation is outputting each value of a multi-valued metadata Keyword field on the Publication (i.e. "Allow Multiple Values", "Values selected from a list" and "Category" all checked in the Metadata Schema).
If you are trying to do something similar, you can indeed modify the name of the field and it will work. From your question, however, it seems like you are trying to loop over all Keywords within a certain Category - which requires a different approach.
For that, you would need the equivalent of a GetList call within your TBB. I'm not familiar enough with the Razor mediator to provide sample code for that, sorry.
Thanks to Ram G in chat:
The Publication itself, typically your 010, 020... 050 etc. levels, can have a metadata schema attached to them as well. The XMLName of the field being targeted by the Razor logic block above is actually the field name of this metadata schema item, not the name of the Category itself. In the metadata schema for the publication, if you select the Design tab, Make your XML field for the item a "Text" type, select "Options will be selected from a list", by default, another Checkbox will appear called "Category" which, if checked, automatically pulls in the full list of Category items present in that publication. So, when that Field is targeted by the Razor logic now, it is in multiple steps targeting the Category value as well.
Thanks again Ram G

Exposing table name and field names in request URL

I was tasked to create this Joomla component (yep, joomla; but its unrelated) and a professor told me that I should make my code as dynamic as possible (a code that needs less maintenance) and avoid hard coding. The approach we thought initially is take url parameters, turn them into objects, and pass them to query.
Let's say we want to read hotel with id # 1 in the table "hotels". lets say the table has the fields "hotel_id", "hotel_name" and some other fields.
Now, the approach we took in making the sql query string is to parse the url request that looked like this:
index.php?task=view&table=hotels&hotel_id=1&param1=something&param2=somethingelse
and turned it into a PHP object like this (shown in JSON equivalent, easier to understand):
obj = {
'table':'hotel',
'conditions':{
'hotel_id':'1',
'param1':'something',
'param2':'somethingelse'
}
and the SQL query will be something like this where conditions are looped and appended into the string where field and value of the WHERE clause are the key and value of the object (still in JSON form for ease):
SELECT * FROM obj.table WHERE hotel_id=1 AND param1=something and so on...
The problem that bugged me was the exposing of the table name and field names in the request url. I know it poses a security risk exposing items that should only be seen to the server side. The current solution I'm thinking is giving aliases to each and every table and field for the client side - but that would be hard coding, which is against his policy. and besides, if I did that, and had a thousand tables to alias, it would not be practical.
What is the proper method to do this without:
hard coding stuff
keep the code as dynamic and adaptable
EDIT:
Regarding the arbitrary queries (I forgot to include this), what currently stops them in the back end is a function, that takes a reference from a hard-coded object (more like a config file shown here), and parses the url by picking out parameters or matching them.
The config looks like:
// 'hotels' here is the table name. instead of parsing the url for a table name
// php will just find the table from this config. if no match, return error.
// reduces risk of arbitrary tables.
'hotels' => array(
// fields and their types, used to identify what filter to use
'structure' => array(
'hotel_id'=>'int',
'name'=>'string',
'description'=>'string',
'featured'=>'boolean',
'published'=>'boolean'
),
//these are the list of 'tasks' and accepted parameters, based on the ones above
//these are the actual parameter names which i said were the same as field names
//the ones in 'values' are usually values for inserting and updating
//the ones in 'conditions' are the ones used in the WHERE part of the query
'operations' =>array(
'add' => array(
'values' => array('name','description','featured'),
'conditions' => array()
),
'view' => array(
'values' => array(),
'conditions' => array('hotel_id')
),
'edit' => array(
'values' => array('name','description','featured'),
'conditions' => array('hotel_id')
),
'remove' => array(
'values' => array(),
'conditions' => array('hotel_id')
)
)
)
and so, from that config list:
if a parameters sent for a task is not complete, server returns an error.
if a parameter from the url is doubled, only the first parameter read is taken.
any other parameters not in the config are discarded
if that task is not allowed, it wont be listed for that table
if a task is not there, server returns an error
if a table is not there, server returns an error
I actually patterned this after seeing a component in joomla that uses this strategy. It reduces the model and controller to 4 dynamic functions which would be CRUD, leaving only the config file to be the only file editable later on (this was what I meant about dynamic code, I only add tables and tasks if further tables are needed) but I fear it may impose a security risk which I may have not known yet.
Any ideas for an alternative?
I have no problem with using the same (or very similar) names in the URL and the database — sure, you might be "exposing" implementation details, but if you're choosing radically different names in the URL and the DB, you're probably choosing bad names. I'm also a fan of consistent naming — communication with coders/testers/customers becomes much more difficult if everyone calls everything something slightly different.
What bugs me is that you're letting the user run arbitrary queries on your database. http://.../index.php?table=users&user_id=1, say? Or http://.../index.php?table=users&password=password (not that you should be storing passwords in plaintext)? Or http://.../index.php?table=users&age=11?
If the user connected to the DB has the same permissions as the user sitting in front of the web browser, it might make sense. Generally, that's not going to be the case, so you'll need some layer that knows what the user is and isn't allowed to see, and that layer is a lot easier to write correctly by whitelisting.
(If you've stuck enough logic into stored procedures, then it might work, but then your stored procedures will hard-code column names...)
When composing a SQL query with data from the input, it presents a security risk. But keep in mind that columns values are inserted to the fields by taking input from the user, analyzing it and composing a SQL query with it (except for prepared statements). So when done properly, you have nothing to worry about - simply restrict the user to those column & tables. Open source software's code/database is visible to all - and it doesn't harm the system so much as one would think.
Your aliasses could be a rot13() on the meta/name of your objects.
Although, if you escape the input accordingly when working with those names, I don't see any problem in exposing their names.