OR condition inside AND condition in createQueryBuilder depend on condition - mongodb

We need all active records using "tag" which matches search string in createQueryBuilder.
For Ex: Search for "NEW YORK" which internally search for "NEW" or "YORK" in Tags "new, ab, other"
My CODE:
$query = $this->createQueryBuilder();
$query->field('status')->equals("active");
if (isset($params["search"]) && !empty($params["search"])) {
$searchArr = explode(" ", $params["search"]);
foreach ($searchArr as $searchVal) {
$query->addOr(
$query->expr()->addOr($query->expr()->field('tags')->equals(new \MongoRegex('/.*' . $searchVal . '.*/')))
);
}
}
It will give result active OR (tag1 Or tag2). Expected result active AND (tag1 Or tag2)
Any suggestions?

Replace this
foreach ($searchArr as $searchVal) {
$query->addOr(
by this
foreach ($searchArr as $searchVal) {
$query->addAnd(

Related

Bugzilla extension. How to check if custom field empty?

How to check condition if some custom field empty?
For example, it's possible to check that qa_contact is not set.
sub object_end_of_set_all {
my ($self, $args) = #_;
my $object = $args->{'object'};
if ($object->{'bug_status'} eq 'RESOLVED') {
if ($object->{'qa_contact'} eq "") {
ThrowUserError("empty_qa_contact");
}
}
}
Is there is same way for custom field e.g. cf_test ?
I know that to save custom field in variable, need to:
my $test = new Bugzilla::Field({ name => 'cf_test' });
Which method can be used to get its value or check if it's not empty ?
Found out two problems:
1. After executing ThrowUserError("...") any object (cf_test or even bugzilla fields) is always NULL.
2. If to use Hook "object_end_of_set_all" for custom field then only a cached values are showed for a custom field.
The answer is to use different Hook:
sub bug_end_of_update {
my ($self, $args) = #_;
my ($bug, $old_bug, $timestamp, $changes) = #$args{qw(bug old_bug timestamp changes)};
if ($bug->bug_status eq 'RESOLVED') {
if ($bug->cf_test eq "") {
ThrowUserError("test_is_empty");
}
}
}

Sort and delete duplicates in multidimensional array

I have an multidimensional Array and want to sort it by the date and delete the duplicate entries (by date).
$arrayPlaces = [System.Collections.ArrayList]#()
and that is how the Array looks like:
$arrayPlaces.Add(($mailBarcodeInformation[2], $mailScannedStart.Substring(22), "", "", "", "", "", ""))
The empty fields are filled later. The second field $mailScannedStart.Substring(22) is the time and the Array should be sorted by that and the duplicates should also be removed.
I searched a lot but couldn't find any help.
A common approach is to add a custom object into an array and use the buit-in cmdlet sort -unique. It's much more readable:
$arrayPlaces = [System.Collections.ArrayList]#()
#.........
$arrayPlaces.Add([PSCustomObject]#{
barcode = $mailBarcodeInformation[2]
time = $mailScannedStart.Substring(22)
foo1 = ''
foo2 = ''
foo3 = ''
}) >$null
#...........
$sorted = $arrayPlaces | sort time -Unique
However, since you already use a .NET class you can switch to a fast .NET SortedDictionary, which automatically sorts and deduplicates the collection when items are added:
$arrayPlaces = [Collections.Generic.SortedDictionary[string,array]]#{}
Adding and overwriting the old value:
$key = $mailScannedStart.Substring(22)
$arrayPlaces[$key] = $mailBarcodeInformation[2], $key, "", "", "", "", "", ""
Checking for presence of an item using its key:
if ($arrayPlaces.ContainsKey($key)) { ....... }
Removing:
[void]$arrayPlaces.Remove('foo')
Accessing:
$items = $arrayPlaces['foo']
$item = $arrayPlaces['foo'][0]
Enumerating (faster):
foreach ($items in $arrayPlaces.Values) {
# .........
}
Enumerating/pipelining (slower):
$arrayPlaces.Values | foreach { $_[0] = $_[1] + $[2] }

How to prevent SQL injection in PhalconPHP when using sql in model?

Let's say I am building a search that finds all the teacher and got an input where the user can put in the search term. I tried reading the phalcon documentation but I only see things like binding parameters. I read the other thread about needing prepare statements do I need that in Phalcon as well?
And my function in the model would be something like this:
public function findTeachers($q, $userId, $isUser, $page, $limit, $sort)
{
$sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
$result = new Resultset(null, $this,
$this->getReadConnection()->query($sql, array()));
$tagResult = $result->toArray();
$tagList = array();
foreach ($tagResult as $key => $value) {
$tagList[] = $value['id'];
....
}
}
My question is for the Phalcon framework is there any settings or formats I should code for this line $sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
And also any general recommendation for preventing SQL Injection in PhalconPHP controllers and index would be appreciated.
For reference:
My controller:
public function searchAction()
{
$this->view->disable();
$q = $this->request->get("q");
$sort = $this->request->get("sort");
$searchUserModel = new SearchUsers();
$loginUser = $this->component->user->getSessionUser();
if (!$loginUser) {
$loginUser = new stdClass;
$loginUser->id = '';
}
$page = $this->request->get("page");
$limit = 2;
if (!$page){
$page = 1;
}
$list = $searchUserModel->findTeachers($q, $loginUser->id, ($loginUser->id)?true:false, $page, $limit, $sort);
if ($list){
$list['status'] = true;
}
echo json_encode($list);
}
My Ajax:
function(cb){
$.ajax({
url: '/search/search?q=' + mapObject.q + '&sort=<?php echo $sort;?>' + '&page=' + mapObject.page,
data:{},
success: function(res) {
//console.log(res);
var result = JSON.parse(res);
if (!result.status){
return cb(null, result.list);
}else{
return cb(null, []);
}
},
error: function(xhr, ajaxOptions, thrownError) {
cb(null, []);
}
});
with q being the user's search term.
You should bind the query parameter to avoid an SQL injection. From what I can remember Phalcon can be a bit funny with putting the '%' wildcard in the conditions value so I put them in the bind.
This would be better than just filtering the query.
$tags = Tags::find([
'conditions' => 'name LIKE :name:',
'bind' => [
'name' => "%" . $q . "%"
]
])
Phalcon\Filter is helpful when interacting with the database.
In your controller you can say, remove everything except letters and numbers from $q.
$q = $this->request->get("q");
$q = $this->filter->sanitize($q, 'alphanum');
The shortest way for requests:
$q = $this->request->get('q', 'alphanum');

Update embedded subdocument in array with doctrine and mongodb

I want to update (replace) a subdocument within an array of all the documents, that have this specific embedded subdocument.
My sample content object is:
{
"_id" : ObjectId("51f289e5345f9d10090022ef"),
"title" : "This is a content",
"descriptors" : [
{
"_id" : ObjectId("51f289e5345f9d10090022f4"),
"name" : "This is a descriptor",
"type" : "This is a property"
},
{
"_id" : ObjectId("51f289e5345f9d10090022f0"),
"name" : "This is another descriptor",
"type" : "This is another property"
}
]
}
I want to find the object with a specific descriptor._id.
I want to replace the one subdocument with another one (respectivley with an updated version of the old object, but not necessarily with the same properties).
While this works well in RoboMongo / shell...
db.Content.update(
{
'descriptors._id': ObjectId("51f289e5345f9d10090022f4")
},
{
$set: {
'descriptors.$': {
"_id" : ObjectId("51f289e5345f9d10090022f4"),
"name" : "This is the updated descriptor",
"category" : "This is a new property"
}
}
},
{
'multi': true
})
...and with the plain php methods...
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$mongo = new \Mongo('mongodb://localhost:27017');
$database = $mongo->selectDB('MyDatabase');
$output = $database->selectCollection('Content')->update(
array('descriptors._id' => $descriptor['_id']),
array('$set' => array('descriptors.$' => $descriptor)),
array("multiple" => true)
);
...it doesn't work with Doctrine MongoDB ODM...
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$query = $dm->createQueryBuilder('Content')
->update()->multiple(true)
->field('descriptors._id')->equals($descriptor['_id'])
->field('descriptors.$')->set($descriptor)
->getQuery()->execute();
...because it fails with the following error:
Notice: Undefined offset: 2 in C:\MyProject\vendor\doctrine\mongodb-odm\lib\Doctrine\ODM\MongoDB\Persisters\DocumentPersister.php line 998
So I assume, that Doctrine MongoDB ODM needs three parts in the dot-notation. The not so nice solution would be to iterate over the properties of the subdocument and set them manually.
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$query = $dm->createQueryBuilder('Content')
->update()->multiple(true)
->field('descriptors._id')->equals($descriptor['_id']);
foreach ($descriptor as $key => $value) {
$query->field('descriptors.$.'.$key)->set($value);
}
$query->getQuery()->execute();
But this will only update existing and add new properties, but won't remove old/unnecessary properties from the subdocument.
Any ideas how to solve the problem:
with a simple query
while using Doctrine MongoDB ODM
without looping over the subdocument-array in php
I'm using:
Mongo-Server: 2.4.5
PHP: 5.4.16
PHP-Mongo-Driver: 1.4.1
Composer:
"php": ">=5.3.3",
"symfony/symfony": "2.3.*",
"doctrine/orm": ">=2.2.3,<2.4-dev",
"doctrine/doctrine-bundle": "1.2.*",
"doctrine/mongodb-odm": "1.0.*#dev",
"doctrine/mongodb-odm-bundle": "3.0.*#dev"
This was a bug in ODM and should be fixed in PR #661. Please take a look and ensure that the revised test satisfies your use case.
Until the next beta of ODM is tagged, this will only reside in the master branch; however, that should match your 1.0.*#dev version requirement.
You can do this thing but in a "not easy" way becuse when you use EmbedMany or ReferenceMany in Doctrine becames a Doctrine ArrayCollection objects that implemented the ArrayCollection contains() method with (as explained here) with the PHP in_array() method with the $strict parameter set to true... this way works with ReferenceMany but not with EmbedMany!
The concept is: ArrayCollection -> array -> ArrayCollection
In the definition of Document
...
/**
* #ODM\EmbedMany(targetDocument="EmbeddedElement")
*/
private $elements = array();
...
public function getElements() { return $this->elements; }
public function setElements($elements) { $this->elements = $elements; }
public function addElement(Element $element) { $this->elements[] = $element; }
public function setElement(Element $element, $index=0)
{
$elementsArray = $this->elements->toArray();
$elementsArray[$index] = $element;
$this->elements = new ArrayCollection($elementsArray);
}
public function removeElement(Element $element)
{
$index = array_search($element, $this->elements->toArray(), $strict=false);
if($index !== false)
$this->elements->remove($index);
}
public function removeElementByIndex($index) { $this->elements->remove($index); }

How can I get a specific tag from array returned from Net::Amazon::EC2 decribe_tags?

I'm using Net::Amazon::EC2 to get some information about my instances.
I get all of the tags associated with an instance with:
my $tags = $ec2->describe_tags("Filter.Name" => "resource-id", "Filter.Value" => $instance_id);
According to the docs, this returns an array ref of DescribeTag objects.
I can iterate through the results:
foreach my $tag (#$tags) {
print $tag->key . " = " . $tag->value . "\n";
}
Is there a way I can get a tag with a specific key?
You could probably grep through them. Not very elegant, but I don't know the module you are using.
my #filtered_tags = grep { $_->key eq 'specific' } #$tags;