Welcome to the Question2Answer Q&A. There's also a demo if you just want to try it out.
+4 votes
966 views
in Q2A Core by
edited by

I am trying to override the above function to additionally filter for some information stored in postmetas.

I made a copy of the original function and added the following items to source and arguments, immediately after the initial set-up of the $selectspec array.

$selectspec['source'].=' LEFT JOIN ^postmetas ON ^postmetas.postid = ^posts.postid AND ^postmetas.title=\'custField\' AND ^postmetas.content=$';
array_push($selectspec['arguments'],$custValue);

The query now throws an error because postid is not filled in in the generated query, even though my addtion to the code has nothing to with postids and the part I added comes out correctly formed.

The generated queries contain sequences like:

...WHERE qa_posts.postid=(SELECT IF(LEFT(parent.type, 1)='A', parent.parentid, parent.postid) FROM qa_posts AS child LEFT JOIN qa_posts AS parent ON parent.postid=child.parentid WHERE child.postid=#)

...WHERE qa_posts.postid=(SELECT closedbyid FROM qa_posts WHERE postid=#)

Please Note:

The code works correctly when I comment out my added lines.

When listing all questions in the main view, there is no error (maybe this is handled by a different function), the problem only occurs when trying to view the details of a question.

 

UPDATE:

I tried to insert my argument into the 'source' string instead of array_pushing onto 'arguments' and now the error is gone.

$selectspec['source'].=' LEFT JOIN ^postmetas ON ^postmetas.postid = ^posts.postid AND ^postmetas.title=\'custField\' AND ^postmetas.content=\''.$custValue.'\'';

So I must be doing something wrong when pushing onto the 'arguments' array ... but what?

Q2A version: 1.6.3

1 Answer

+1 vote
by

Unless dynamically built, the only place where I could find this string postid=(SELECT IF(LEFT(parent.type was in the qa_db_post_parent_q_selectspec function. That function calls the one you're trying to change. You mentioned you have copied and changed the copy but if you do so it is impossible for qa_db_post_parent_q_selectspec to fail, so you are changing the real qa_db_posts_basic_selectspec.

So, accepting the fact that you're changing the core, which is something extremely unadvisable unless you know exactly what you're doing,  I can tell you the error seems to be comming from the fact that qa_db_post_parent_q_selectspec function is resetting the arguments array. So no matter what you have added in the qa_db_posts_basic_selectspec as arguments it will be replaced. So having arguments that don't match the source key of the selectspec will result in an SQL error.

You can keep trying to mess with the core but whenever a new Q2A version is released your code might stop working. Not to mention that you will have to keep track of these changes too. The real solution is to create a plugin. Follow the instructions in the Q2A page and take a look at some plugins hosted in Github.

PS: If you can avoid using array_push($array, $element) and use $array[]=$element then do so, as it is a bit faster.

by
Thanks for your answer, I am pretty sure that I am editing the copy as the file is in a plug-in directory that I have created for this purpose. I am using the function qa_register_plugin_overrides(); according to the documentation that I have read so far this was supposed to be legitimate (the function has the if (qa_to_override(__FUNCTION__) check at the beginning) , and it looks like my function is being called.
From your analysis above though, it seems that it's not really possible to override this function because of other side-effects
As far as not using array_push, I was following the convention in the existing code.
by
The thing that doesn't make sense to me is that posts_basic_selectspec is doing exactly what I am doing, adding things to 'source' and 'arguments' depending on certain conditions, why can't I add more things to source and arguments in the same way?
by
I see now. Using qa_register_plugin_overrides() is, in practice, no different than changing the core. Instead of statically changing the core's code you're changing it dynamically. It is not advisable to use that function either for the same reasons that I've stated above. When I say it is better writing a plugin I mean writing what would most likely be a layer that would query the data you need using a custom selectspectand then displaying it properly by means of overriding ("overriding" in terms of OOP rather than qa_to_override) the proper theme function.
by
Thanks again for your time. Any clues as to how to implement a custom selectspec? I can't find any documentation on this, and this sounds like what I am trying to achieve.
by
Well, creating a custom selectspect it is just what you're trying to do. There is no documentation, AFAIK, on how to implement your own selectspecs but just take a look at some examples and you'll see it is not so difficult. The closest thing to a tutorial can be found in the comments of the function qa_db_single_select in the qa-db.php file. You could also use the one you've right now (copied from the existing function) but it is, most likely, more complex than the one you might need.
by
Creating the selectspec isn't that hard from what I can tell. If I want to use this selectspec, it looks like I need to define a page module which uses my custom query in process_request() to generate the content.
...