Creating an Advanced Search field capable of searching multiple module fields - sugarcrm

I am currently encountering issues trying to build a custom search field (itself bound to an unused field on a Module) to search two Phone Number fields. The documentation covering modifications of a search field are really poor, but I have the following in place in the module's SearchFields.php
'phone' =>
array (
'query_type' => 'default',
'operator' => '=',
'db_field' =>
array (
0 => 'home_phone_c',
1 => 'work_phone_c',
),
),
The field itself returns no results, so am I missing something that would prevent this from working?

why not you use "sub-query" operator for this? See SearchFields.php inside metadata folder of Account module. You will see entry like following:
'email' =>
array (
'query_type' => 'default',
'operator' => 'subquery',
'subquery' => 'SELECT eabr.bean_id FROM email_addr_bean_rel eabr JOIN email_addresses ea ON (ea.id = eabr.email_address_id) WHERE eabr.deleted=0 AND ea.email_address LIKE',
'db_field' =>
array (
0 => 'id',
),
'vname' => 'LBL_ANY_EMAIL',
),
this will help you to understand the sugar logic of doing it.

You need to designate the correct tables. Try the below code (or use the tables that you're searching):
'phone' =>
array (
'query_type' => 'default',
'operator' => '=',
'db_field' =>
array (
0 => 'accounts_cstm.home_phone_c',
1 => 'accounts_cstm.work_phone_c',
),
),

Related

In suiteCRM how does one get about changing the Address field country and state text fields to be dropdowns?

I am developing a custom suite CRM module however I find the Address field limiting since it uses text fields for country and state fields.
I have tried researching it by following instructions on this site:
https://johndopenotes.wordpress.com/2013/01/08/sugarcrm-change-address-state-and-country-to-dropdown-menu/
However I am stuck at step 5 since my custom module does not have a metadata directory???
Go to /custom/modules/Leads/metadata and update editviewdefs.php. Look for this code:
array (
'name' => 'primary_address_street',
'hideLabel' => true,
'type' => 'Address',
'displayParams' =>
array (
'key' => 'primary',
'rows' => 2,
'cols' => 30,
'maxlength' => 150,
),
),
1 =>
array (
'name' => 'alt_address_street',
'hideLabel' => true,
'type' => 'Address',
'displayParams' =>
array (
'key' => 'alt',
'copy' => 'primary',
'rows' => 2,
'cols' => 30,
'maxlength' => 150,
),
),
and update the type from Address to CustomAddress
array (
'name' => 'primary_address_street',
'hideLabel' => true,
'type' => 'CustomAddress',
'displayParams' =>
array (
'key' => 'primary',
'rows' => 2,
'cols' => 30,
'maxlength' => 150,
),
),
1 =>
array (
'name' => 'alt_address_street',
'hideLabel' => true,
'type' => 'CustomAddress',
'displayParams' =>
array (
'key' => 'alt',
'copy' => 'primary',
'rows' => 2,
'cols' => 30,
'maxlength' => 150,
),
),
Can someone please give me a pointer as to how I can make address field in my custom module dropdowns instead of text fields?
Instead to choosing Address type field you can use combination of multiple fileds. For an example for street address you can use (datatype:textField)
Similarly for city you can add a text filed. Now for state and country you can use dropdown and add dropdown list as per your need
And for zipcode you can use integer / text field as per your requirement.
Now to make state dependend to country you can use custom javascript / jquery in following way
Add a reference to the javascript file you are going to add at the
end of custom/modules/<>/metadata/[edit|detail]viewdefs.php
$viewdefs['Opportunities']['EditView']['templateMeta']['includes'] = array ( array ( 'file' => 'path/to/file/filename.js', ), );
Add the javascript file you want to include into the location you
referenced above.
Quick Repair from the admin section, then browser refresh
It should just be a case of updating the vardefs for the field so the type is set to enum and the options point to your dropdown list. Then run a repair and rebuild.
The guide you've linked to looks like it is creating a new field type, which I think is overkill. It's also using Sugar logic to make the 2 lists dependent, but I'm not sure that's a feature in SuiteCRM.

wordpress WP Query and Custom Field filtering

I've encoutered problem with filtering pages to display in WP query.
I use Codex WP query reference for custom fields with ACF (Advanced Custom Fields plugin - but it doesn't matter, couse it works same as WP custom field) parameters to filter pages.
In "Multiple Custom Field Handling" paragraph, Codex got an example with 2 conditions. We can use OR or AND relation. I works for both until you have 3rd condition (array).
They use example:
'relation' => 'OR',
array(
'key' => 'color',
'value' => 'blue',
'compare' => 'NOT LIKE'
),
array(
'key' => 'price',
'value' => array( 20, 100 ),
'type' => 'numeric',
'compare' => 'BETWEEN'
)
It has only 2 arrays. When I put 3rd, nothing shows. In debug mode I can see an error:
WordPress database error: [Lost connection to MySQL server during query]
When I use AND it works, but I got to use OR. Unfortunately it makes MySQL disconnect.
I've tryed asking phpMySQL for same query WP does. It couses problem - phpMyAdmin says same:
Lost connection
Any Idea?
Maybe I should try different aproach for filtering? (maybe I should use taxonomy?)
Here is code I use:
$query_array = array('relation' => 'OR');
array_push($query_array,
array(
'key' => 'filter1',
'value' => 'value1',
'compare' => 'LIKE'
),
array(
'key' => 'filter1',
'value' => 'value2',
'compare' => 'LIKE'
),
array(
'key' => 'filter1',
'value' => 'value3',
'compare' => 'LIKE'
)
);
$args = array(
'order' => $order_array,
'meta_key' => $meta_key,
'orderby' => $orderby,
'post_type' => 'page',
'paged' => $paged,
'post__in' => $postIDs,
'posts_per_page' => 12,
'paged' => get_query_var('paged'),
'meta_query' => $query_array
);
query_posts($args);
?>
(variables for $args are set of course)
I don't know why I can't use
'compare' => '='
but probably it is why I can't use:
$query_array = array('relation' => 'OR');
array_push($query_array,
array(
'key' => 'filter1',
'value' => array('value1', 'value2', 'value3'),
'compare' => 'IN'
)
);
Just wanted to say that your comment helped me; I'd been butting my head against a very similar problem for a while. I'm using ACF too, and using it to attach items of one post type to another custom post type was easy - for instance, to Attach Person_1 and Person_3 to "Project_A".
This made it easy to list out which users were attached to specific projects. But when it came to do the same in reverse - to show which projects were attached to which users - it became a massive headache.
I finally figured it out, in part thanks to your comment - I'll post my solution here in case someone else comes along with the same problem:
$args = array(
'numberposts' => -1,
'post_type' => 'project',
'meta_query' => array(
'relation' => 'IN',
array(
'key' => 'people',
'value' => ';s:1:"' . $person->ID . '";',
'compare' => 'LIKE'
)
)
);
In short: because the ACF values in repeater fields et cetera are serialized, the compare keyword has to be "LIKE", and I added some context to the value to eliminate false returns - just searching for an ID like "1" would match a lot of the (wrong) posts, but the ";s1;" part ensures that the given value is at index 1, which in my case is the correct index.
So it would need tweaking from case to case. Inspecting what you're trying to match up with var_dumping "get_post_meta($post->ID, 'people')" is helpful for getting the value correct.

From Where SugarCRM assign value for $fields.date_modified

From Where SugarCRM assign value for $fields.date_modified
Just wanted to see the sugar code and want to do some customization in that file
Below code is from : modules\Leads\metadata\detailviewdefs.php
'LBL_PANEL_ASSIGNMENT' =>
array(
array (
array (
'name' => 'assigned_user_name',
'label' => 'LBL_ASSIGNED_TO',
),
array (
'name' => 'date_modified',
'label' => 'LBL_DATE_MODIFIED',
'customCode' => '{$fields.date_modified.value} {$APP.LBL_BY} {$fields.modified_by_name.value}',
),
),
array (
array (
'name' => 'date_entered',
'customCode' => '{$fields.date_entered.value} {$APP.LBL_BY} {$fields.created_by_name.value}',
),
),
),
What SugarCRM version are you using?
I only have a pro version here.
Look for the following line on EditView2.php file under include/EditView directory.
$this->th->ss->assign('fields', $this->fieldDefs);
It is not advisable to modify core codes on sugarcrm. You might as well create a custom view.detail.php file custom/Leads/ directory. I assume you are new to sugar and the following link would be very helpful to you. http://archive.h2ik.co/2012/03/sugarcrm-upgrade-safe-way-to-extend-views/

HTML::FormHandler dynamic fields added client side

I'm using HTML::FormHandler and I would like to have a form that has a dynamic number of form elements. Essentially, I have some inputs that are always present, such as first_name, last_name, and email, but then I have an input, pracitce_area, that I can have many of dynamically (so practice_area1, pracitce_area2, etc). So on the client side I will be using jQuery to dynamically add more practice_area inputs, and I would like for my HTML::FormHandler form to be able to process a dynamic number of these inputs and validate them and put them in the database. The practice_area inputs will be stored in a separate table that will be related with a foreign key to the element of this form, so I would like for HTML::FormHandler to know that these are related and pull out a dynamic number when editing, but also be able to save a dynamic number into the database when saving. Is there a way to handle something like this with HTML::FormHandler? Here's the definition of my form:
package test::Form::Base;
use namespace::autoclean;
use HTML::FormHandler::Moose;
with 'HTML::FormHandler::TraitFor::Model::DBIC';
has title => ( is => 'ro', default => 'Client Information Form');
has '+item_class' => ( default => 'ClientInformationForm' );
has_field 'first_name' => (
type => 'Text',
label => 'First Name',
required => 1,
);
has_field 'last_name' => (
type => 'Text',
label => 'Last Name',
required => 1,
);
has_field 'email' => (
type => 'Email',
label => 'Email',
required => 1,
);
#would like to have this be dynamic in number, and have HTML::FormHandler know
#that it's related with a foreign key when pulling them out of the database
has_field 'practice_area' => (
type => 'TextArea',
);
no HTML::FormHandler::Moose;
__PACKAGE__->meta->make_immutable;
1;
Have you looked at HTML::Formhandler::Repeatable.
You should just be able to use practice_area in your form and have multiple entries. These will just be pulled in an an array(ref) in form processing.

Zend_Validate_Db_RecordExists against 2 fields

I usualy use Zend_Validate_Db_RecordExists to update or insert a record. This works fine with one field to check against. How to do it if you have two fields to check?
$validator = new Zend_Validate_Db_RecordExists(
array(
'table' => $this->_name,
'field' => 'id_sector,day_of_week'
)
);
if ($validator->isValid($fields_values['id_sector'],$fields_values['day_of_week'])){
//true
}
I tried it with an array and comma separated list, nothing works... Any help is welcome.
Regards
Andrea
To do this you would have to extend the Zend_Validate_Db_RecordExists class.
It doesn't currently know how to check for the existence of more than one field.
You could just use two different validator instances to check the two fields separately. This is the only work around that I can see right now besides extending it.
If you choose to extend it then you'll have to find some way of passing in all the fields to the constructor ( array seems like a good choice ), and then you'll have to dig into the method that creates the sql query. In this method you'll have to loop over the array of fields that were passed in to the constructor.
You should look into using the exclude parameter. Something like this should do what you want:
$validator = new Zend_Validate_Db_RecordExists(
array(
'table' => $this->_name,
'field' => 'id_sector',
'exclude' => array(
'field' => 'day_of_week',
'value' => $fields_values['day_of_week']
)
);
The exclude field will effectively add to the automatically generated WHERE part to create something equivalent to this:
WHERE `id_sector` = $fields_values['id_sector'] AND `day_of_week` = $fields_values['day_of_week']
Its kind of a hack in that we're using it for the opposite of what it was intended, but its working for me similar to this (I'm using it with Db_NoRecordExists).
Source: Zend_Validate_Db_NoRecordExists example
Sorry for the late reply.
The best option that worked for me is this:
// create an instance of the Zend_Validate_Db_RecordExists class
// pass in the database table name and the first field (as usual)...
$validator = new Zend_Validate_Db_RecordExists(array(
'table' => 'tablename',
'field' => 'first_field'
));
// reset the where clause used by Zend_Validate_Db_RecordExists
$validator->getSelect()->reset('where');
// set again the first field and the second field.
// :value is a named parameter that will be substituted
// by the value passed to the isValid method
$validator->getSelect()->where('first_field = ?', $first_field);
$validator->getSelect()->where('second_field = :value', $second_field);
// add your new record exist based on 2 fields validator to your element.
$element = new Zend_Form_Element_Text('element');
$element->addValidator($validator);
// add the validated element to the form.
$form->addElement($element);
I hope that will help someone :)
Although, I would strongly recommend a neater solution which would be to extend the Zend_Validate_Db_RecordExists class with the above code.
Enjoy!!
Rosario
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
'validators' => array('EmailAddress', $obj= new Zend_Validate_Db_NoRecordExists(array('adapter'=>$dbAdapter,
'field'=>'email',
'table'=>'user',
'exclude'=>array('field'=>'email','value'=>$this->_options['email'], 'field'=>'is_deleted', 'value'=>'1')
))),
For those using Zend 2, If you want to check if user with given id and email exists in table users, It is possible this way.
First, you create the select object that will be use as parameter for the Zend\Validator\Db\RecordExists object
$select = new Zend\Db\Sql\Select();
$select->from('users')
->where->equalTo('id', $user_id)
->where->equalTo('email', $email);
Now, create RecordExists object and check the existence this way
$validator = new Zend\Validator\Db\RecordExists($select);
$validator->setAdapter($dbAdapter);
if ($validator->isValid($username)) {
echo 'This user is valid';
} else {
//get and display errors
$messages = $validator->getMessages();
foreach ($messages as $message) {
echo "$message\n";
}
}
This sample is from ZF2 official doc
You can use the 'exclude' in this parameter pass the second clause that you want to filter through.
$clause = 'table.field2 = value';
$validator = new Zend_Validate_Db_RecordExists(
array(
'table' => 'table',
'field' => 'field1',
'exclude' => $clause
)
);
if ($validator->isValid('value') {
true;
}
I am using zend framework v.3 and validation via InputFilter(), it uses same validation rules as zend framework 2.
In my case I need to check, if location exists in db (by 'id' field) and has needed company's id ('company_id' field).
I implemented it in next way:
$clause = new Operator('company_id', Operator::OP_EQ, $companyId);
$inputFilter->add([
'name' => 'location_id',
'required' => false,
'filters' => [
['name' => 'StringTrim'],
['name' => 'ToInt'],
],
'validators' => [
[
'name' => 'Int',
],
[
'name' => 'dbRecordExists',
'options' => [
'adapter' => $dbAdapterCore,
'table' => 'locations',
'field' => 'id',
'exclude' => $clause,
'messages' => [
'noRecordFound' => "Location does not exist.",
],
]
],
],
]);
In this case validation will pass, only if 'locations' table has item with columns id == $value and company_id == $companyId, like next:
select * from location where id = ? AND company_id = ?