Symfony2 - Query Builder LIKE null values - symfony

I'm trying to build a dynamic query in response to a custom search from users. I have an issue: when I'm building the query, I don't have the results because the SELECT LIKE column comparison doesn't work with NULL values. How can I work around this issue, considering that query is dynamically built? So, users can give values or not to search criteria...
This is my code:
$qb->add('select', 'f')
->add('from', 'Bundle:Object f')
->add('where', $qb->expr()->andx(
$qb->expr()->like('f.c1',':c1'),
$qb->expr()->like('f.c2',':c2'),
$qb->expr()->like('f.c3',':c3')))
->add('orderBy', 'f.nnumCatalogo ASC');
if ($data->getField1() != null) {
$isField1 = true;
}
if ($data->getField2() != null) {
$isField2 = true;
}
if ($data->getField3() != null) {
$isField3 = true;
}
if ($isField1) {
$qb->setParameter('c1', $data->getField1());
} else {
$qb->setParameter('c1', '%');
}
if ($isField2) {
$qb->setParameter('c2', $data->getField2());
} else {
$qb->setParameter('c2', '%');
}
if ($isField3) {
$qb->setParameter('c3', $data->getField3());
} else {
$qb->setParameter('c3', '%');
}
With this code I have no results becuase of NULL values in some columns not selected with LIKE '%' (mysql).

Try this:
$qb->add('select', 'f')->add('from', 'Bundle:Object f');
if ($data->getField1() != null) {
$qb->andWhere('f.c1 like :c1')
->setParameter('c1', $data->getField1());
}
if ($data->getField2() != null) {
$qb->andWhere('f.c2 like :c2')
->setParameter('c2', $data->getField2());
}
if ($data->getField3() != null) {
$qb->andWhere('f.c3 like :c3')
->setParameter('c3', $data->getField3());
}
$qb->add('orderBy', 'f.nnumCatalogo ASC');

Related

Hiding fields in Quick View form with JS not working

I need to hide few fields in a Quick View Form based on an Option Set (Choice) selection in that Quick View form. However it is not working, so am sharing the code I used for the same here. In my code, I am trying to hide certain fields if the option selected is not equal to a particular value...
function hideFields(executionContext) {
var formContext = executionContext.getFormContext();
var quickViewControl = formContext.ui.quickForms.get("General");
if (quickViewControl != undefined) {
if (quickViewControl.isLoaded()) {
var orgtypevalue = quickViewControl.getControl("new_organizationtype").getValue();
if (orgtypevalue != 248870006) {
quickViewControl.getControl("new_recipienttype").setVisible(false);
quickViewControl.getControl("new_businesstype").setVisible(false);
quickViewControl.getControl("new_businesstypecode").setVisible(false);
quickViewControl.getControl("new_businesstypecharacteristicstypecode").setVisible(false);
return;
}
else {
// Wait for some time and check again
setTimeout(getAttributeValue, 10, executionContext);
}
}
else {
console.log("No data to display in the quick view control.");
return;
}
else {
quickViewControl.getControl("new_recipienttype").setVisible(true);
quickViewControl.getControl("new_businesstype").setVisible(true);
quickViewControl.getControl("new_businesstypecode").setVisible(true);
quickViewControl.getControl("new_businesstypecharacteristicstypecode").setVisible(true);
return;
}
}
}
I need to know where am I wrong. Any help will be appreciated.
Thanks!
you need to update the following
first if version 9 I am updating this
"var quickViewControl = formContext.ui.quickForms.get("General");"
to "var quickViewControl = formContext._ui._quickForms.get("General");"
&
"var orgtypevalue = quickViewControl.getControl("new_organizationtype").getValue();"
to
"var orgtypevalue = quickViewControl.getAttribute("new_organizationtype").getValue();"
& update else with message to wait and call the function again like this
"setTimeout(hideFields, 10, executionContext);"
and add else for the If of "quickViewControl != undefined"
Kindly find the updated code:
function hideFields(executionContext) {
var formContext = executionContext.getFormContext();
var quickViewControl = formContext._ui._quickForms.get("General");
if (quickViewControl != undefined) {
if (quickViewControl.isLoaded()) {
var orgtypevalue = quickViewControl.getAttribute("new_organizationtype").getValue();
if (orgtypevalue != 248870006) {
quickViewControl.getControl("new_recipienttype").setVisible(false);
quickViewControl.getControl("new_businesstype").setVisible(false);
quickViewControl.getControl("new_businesstypecode").setVisible(false);
quickViewControl.getControl("new_businesstypecharacteristicstypecode").setVisible(false);
return;
}
else {
// Wait for some time and check again
setTimeout(hideFields, 10, executionContext);
}
}
else {
//console.log("No data to display in the quick view control.");
//return;
setTimeout(hideFields, 10, executionContext);
}
}
}

How do you pass different collections through the same parameter?

I am creating a method that will take a collection of different types (divs, spans..) and search it. I can't find a parameter to pass different collection types though. I tried IElementContainer and ElementCollections but I can't cast DivCollection to either. Is there another way?
The method that does the search:
private static ElementCollection searchCollections(IElementContainer ec, WACore.compStringInfo info)
{
if (info.componentIDName == WACore.componentIDs.Id.ToString())
{
return ec.Elements.Filter(Find.ById(info.componentIDValue));
}
else if (info.componentIDName == WACore.componentIDs.Name.ToString())
{
return ec.Elements.Filter(Find.ByName(info.componentIDValue));
}
else if (info.componentIDName == WACore.componentIDs.Title.ToString())
{
return ec.Elements.Filter(Find.ByTitle(info.componentIDValue));
}
else if (info.componentIDName == WACore.componentIDs.OuterText.ToString())
{
String str = info.componentIDValue.Substring(1, 6);
return ec.Elements.Filter(Find.ByText(new Regex(str)));
}
else
{
return null;
}
}
The caller(s):
return searchCollections((IElementContainer)doc.TextFields, info);
return searchCollections((IElementContainer)(doc.Divs), info);
return searchCollections((IElementContainer)doc.Spans, info);

Symfony2, Doctrine2, left join (dql) and its result

So we have such dql
$oQuery = $this->createQueryBuilder('assets')
->addSelect('flags')
->addSelect('types')
->addSelect('groups')
->leftJoin('Site\MainBundle\Entity\123\invFlags', 'flags', Join::WITH, 'assets.flag = flags.flagID')
->leftJoin('Site\MainBundle\Entity\123\invTypes', 'types', Join::WITH, 'assets.typeID = types.typeID')
->leftJoin('Site\MainBundle\Entity\123\invGroups', 'groups', Join::WITH, 'types.groupID = groups.groupID');
if (!empty($aFilter)) {
$bFirst = true;
foreach ($aFilter as $sKey => $sValue) {
if ($bFirst) {
$oQuery->where($oQuery->expr()->eq('assets.' . $sKey, $sValue));
$bFirst = false;
continue;
} else {
if ($sValue === null) {
$oQuery->andWhere($oQuery->expr()->isNull('assets.' . $sKey));
}
}
}
}
return $oQuery->getQuery()->getResult();
We call it from repository and have result... BUT. In sql query ($oQuery->getQuery()->getSQL()) I see all columns and proper left join I need, but NOT in result. Why it happens? When I return '->getScalarResult()' I receive all needed data but like array and with prefix of tables
array(38) {
["assets_id"]=>string(4) "4558"
["assets_characterID"]=>string(8) "90206263"
["assets_parentItemID"]=>NULL
Can I anyhow get simple 'combined' object' with all get methods?
ADD:
Forgot to say that there are no relations in entities.

Drupal 7 hook_node_access to conditionally block node access

For all users I need to conditionally block access to nodes of type 'message'. The only way users should be able to view these message nodes is by successfully submitting a form.
I've started like this:
function mymodule_node_access($node, $op, $account) {
if ($op == 'view' && $node->type == 'message') {
return NODE_ACCESS_DENY;
}
}
However, I want to allow view access to individual nodes of this type upon successful submission of form:
function form_submit($form, &$form_state) {
// some logic here
$form_state['redirect'] = 'node/255';
}
so node 255 is of type 'message', and I want to 'lift' the NODE_ACCESS_DENY for this particular node and this user (+ in most cases this will be an anonymous user)
Any suggestions on different ways to accomplish this?
The only way you can do that is to set a value in the form submission handler that is then checked by hook_node_access(); you could use a Drupal variable, or a value saved in a database table.
You need to store the user ID of the user that accessed the form, and the node ID of every node for which such form has been submitted.
Supposing you use a Drupal variable, you could use code similar to the following one:
function mymodule_form_submit($form, &$form_state) {
global $user;
$message_nid = 255;
$values = variable_get('access_nid', array());
if (isset($values[$user->uid])) {
if (!isset($values[$user->uid][$message_nid])) {
$values[$user->uid][$message_nid] = $message_nid;
}
}
else {
$values[$user->uid] = array($message_nid => $message_nid);
}
variable_set('access_nid', $values);
$form_state['redirect'] = 'node/' . $message_nid;
}
function mymodule_node_access($node, $op, $account) {
$result = NODE_ACCESS_IGNORE;
if ($op == 'view' && $node->type == 'message') {
$values = variable_get('access_nid', array());
if (!empty($values[$account->uid]) {
if (isset($values[$account->uid][$node->nid])) {
unset($values[$account->uid][$node->nid]);
$result = NODE_ACCESS_ALLOW;
}
else {
$result = NODE_ACCESS_DENY;
}
}
else {
$result = NODE_ACCESS_DENY;
}
}
variable_set('access_nid', $values);
return $result;
}
To notice that this code allows a user to access a node only once; if the user would try to access the same node the second time, the user would get an "access denied" error. If that is not desired, then the second function should be re-written as follows:
function mymodule_node_access($node, $op, $account) {
if ($op == 'view' && $node->type == 'message') {
$values = variable_get('access_nid', array());
if (!empty($values[$account->uid]) {
if (isset($values[$account->uid][$node->nid])) {
return NODE_ACCESS_ALLOW;
}
return NODE_ACCESS_DENY;
}
}
else {
$result = NODE_ACCESS_DENY;
}
}
return NODE_ACCESS_IGNORE;
}
I used a Drupal variable to write simple code; using a Drupal variable, in this case, should be done if the users that can create nodes of that content type are few; if there are many users who can create those nodes, then using a database table is better.
Also when using Drupal variables, Drupal is using a database table; the difference is that the content of that database table is always loaded in memory. If you need to store many data, you should not use Drupal variables.
Modified solution to use $_SESSION as I'm working mostly with anonymous users:
function mymodule_form_submit($form, &$form_state) {
$message_nid = 255;
if (!isset($_SESSION['node_access'])) {
$_SESSION['node_access'] = array();
}
if (!isset($_SESSION['node_access']['nid'])) {
$_SESSION['node_access']['nid'] = $message_nid;
}
$form_state['redirect'] = 'node/' . $message_nid;
}
function mymodule_node_access($node, $op, $account) {
$node_access = NODE_ACCESS_IGNORE;
if ($op == 'view' && $node->type == 'message') {
if (isset($_SESSION['node_access'] && !empty($_SESSION['node_access'])) {
if ($node->nid == $_SESSION['node_access']['nid']) {
unset($_SESSION['node_access']['nid']);
$node_access = NODE_ACCESS_ALLOW ;
} else {
unset($_SESSION['node_access']['nid']);
$node_access = NODE_ACCESS_DENY;
}
} else {
$node_access = NODE_ACCESS_DENY;
}
}
return $node_access;
}

Change Telerik grid columns based on Appsetting

I have a Html.Telerik().Grid() that is bound to a model in my MVC view. I want it to return a link based on a value in the appsettings in the web.config. Basically, if this is the dev server then show the links but not on the production server, is that possible? I use Ajax binding and my bound column looks as follows:
columns.Bound(f => f.TechnicalKey)
.ClientTemplate("<# if (FileName != 'status.txt' && StatusText=='PROCESSED') { #><a href='/AType/DownloadAFile/<#= TechnicalKey #>'>Download</a> <# } else { #>Not available<# } #>")
.Title("").Filterable(false);
I want the status.txt to be a link on development but not on production (this is how it is now)
Thank you.
Jack
You need to set the client template in a different way depending on the fact your application is deployed or not:
if (/* some check to see if on production which is specific to your implementation */) {
columns.Bound(f => f.TechnicalKey)
.ClientTemplate("<# if (FileName != 'status.txt' && StatusText=='PROCESSED') { #>Download <# } else { #>Not available<# } #>")
.Title("").Filterable(false);
} else {
columns.Bound(f => f.TechnicalKey)
.ClientTemplate("<# if (FileName != 'status.txt' && StatusText=='PROCESSED') { #><a href='/AType/DownloadAFile/<#= TechnicalKey #>'>Download</a> <# } else { #>Not available<# } #>")
.Title("").Filterable(false);
}
I actually achieved this by adding a property in the domain object as follows:
public bool isProduction
{
get
{
return ConfigurationManager.AppSettings["ActivationURL"].Contains("production");
}
}
and then in the view I had:
.Columns(columns =>
{
columns.Bound(f => f.TechnicalKey)
.Template(f => { %>
<% if (f.StatusText == "PROCESSED")
{
if (!f.isProduction || f.FileName != "status.txt")
{
%>Download<%
}
else
{
%>Not available<%
}
}
else
{
%>Not available<%
}
%>
<% })
.ClientTemplate("<# if (StatusText=='PROCESSED') { if(!isProduction || FileName!='status.txt') { #><a href='/AType/DownloadAFile/<#= TechnicalKey #>'>Download</a> <# } else { #>Not available<# }} else { #>Not available<# } #>").Encoded(false).Title("").Filterable(false);
This way I cater for the initial server bound data and the later Ajax bound data.

Resources