SugarCRM 6.5 CE: how to remove button in detailview according to a condition - sugarcrm

I'm trying to remove buttons in detail view of a Lead if it is alredy converted.
I saw a similar question and it use javascript to hide buttons. I'm trying to obtain same result via php.
This is my view.detail.php in custom\modules\Leads\views\ folder
class LeadsViewDetail extends ViewDetail {
function __construct(){
parent::__construct();
}
function preDisplay() {
parent::preDisplay();
if($this->bean->converted==1) {
echo "hide";
foreach ($this->dv->defs['templateMeta']['form']['buttons'] as $key => $value) {
unset($this->dv->defs['templateMeta']['form']['buttons'][$key]);
}
} else {
echo "show";
}
}
}
Using this code, after a Quick Repair & Rebuilt, I see "hide" or "show" correctly according to the Lead status but buttons are not updated correctly.
If I open a converted Lead after QR&R, I will never see the buttons.
If I open a unconverted Lead after QR&R, I will see the buttons all times.
I'm stuck with this situation. Can anyone explain me where is the problem? How I can solve it?
Every help is very appreciated.

You can probably handle this without extending the ViewDetail by using Smarty logic ("customCode") in custom/modules/Leads/metadata/detailviewdefs.php. It looks like the Convert button is already only rendered when the user has Edit privileges, so it's not a big deal to add one more condition to it...
$viewdefs['Leads']['DetailView']['templateMeta']['form]['buttons'][] = array('customCode' => '
{if $bean->aclAccess("edit") && $bean->converted}
<input title="{$MOD.LBL_CONVERTLEAD_TITLE}"
accessKey="{$MOD.LBL_CONVERTLEAD_BUTTON_KEY}"
type="button"
class="button"
name="convert"
value="{$MOD.LBL_CONVERTLEAD}"
onClick="document.location=\'index.php?module=Leads&action=ConvertLead&record={$fields.id.value}\'" />
{/if}');
Alternatively, if you do have several conditions and they'd get too messy or difficult for Smarty logic to be reasonable, we can combine a small amount of Smarty Logic with the extended ViewDetail.
This except of custom/modules/Leads/metadata/detailviewdefs.php is actually the out-of-the-box file from SugarCRM CE 6.5.24, where it looks like they've actually tried to make this customization easier by supplying a Smarty var $DISABLE_CONVERT_ACTION. For reference, it simply needs the global config variable disable_convert_lead to be set and enabled, but I suspect that this was a relatively new feature not included in earlier versions. Still, it's a good example of using the View to set a simple Smarty variable that we can pivot on:
<?php
$viewdefs['Leads']['DetailView'] = array (
'templateMeta' => array (
'form' => array (
'buttons' => array (
'EDIT',
'DUPLICATE',
'DELETE',
array (
'customCode' => '{if $bean->aclAccess("edit") && !$DISABLE_CONVERT_ACTION}<input title="{$MOD.LBL_CONVERTLEAD_TITLE}" accessKey="{$MOD.LBL_CONVERTLEAD_BUTTON_KEY}" type="button" class="button" onClick="document.location=\'index.php?module=Leads&action=ConvertLead&record={$fields.id.value}\'" name="convert" value="{$MOD.LBL_CONVERTLEAD}">{/if}',
//Bug#51778: The custom code will be replaced with sugar_html. customCode will be deplicated.
'sugar_html' => array(
'type' => 'button',
'value' => '{$MOD.LBL_CONVERTLEAD}',
'htmlOptions' => array(
'title' => '{$MOD.LBL_CONVERTLEAD_TITLE}',
'accessKey' => '{$MOD.LBL_CONVERTLEAD_BUTTON_KEY}',
'class' => 'button',
'onClick' => 'document.location=\'index.php?module=Leads&action=ConvertLead&record={$fields.id.value}\'',
'name' => 'convert',
'id' => 'convert_lead_button',
),
'template' => '{if $bean->aclAccess("edit") && !$DISABLE_CONVERT_ACTION}[CONTENT]{/if}',
),
),
We can combine this $DISABLE_CONVERT_ACTION reference with a custom/modules/Leads/views/view.detail.php like the following to set it based on whatever condition we want:
<?php
require_once('modules/Leads/views/view.detail.php');
class CustomLeadsViewDetail extends LeadsViewDetail {
/*
* while we might normally like to call parent::display() in this method to
* best emulate what the parnts will do, we instead here copy-and-paste the
* parent methods' content because LeadsViewDetail::display() will set the
* DISABLE_CONVERT_ACTION Smarty var differently than we want.
*/
public function display(){
global $sugar_config;
// Example One: Disable Conversion when status is Converted
$disableConvert = ($this->bean->status == 'Converted');
// Example Two: Disable Conversion when there is at lead one related Call
// where the status is Held
$disableConvert = FALSE;
$this->bean->load_relationships('calls');
foreach($this->bean->calls->getBeans() as $call){
if($call->status == 'Held'){
$disableConvert = TRUE;
break; // exit foreach()
}
}
// Example Three: Disable Conversion if the User is in a specific Role, e.g.
// Interns who are great for data entry in Leads but shouldn't be making
// actual sales
global $current_user;
$disableConvert = $current_user->check_role_membership('No Lead Conversions');
// In any of the above examples, once we have $disableConvert set up
// as we want, let the Smarty template know.
$this->ss->assign("DISABLE_CONVERT_ACTION", $disableConvert);
// copied from ViewDetail::display();
if(empty($this->bean->id)) {
sugar_die($GLOBALS['app_strings']['ERROR_NO_RECORD']);
}
$this->dv->process();
echo $this->dv->display();
}
}

Related

Drupal, hook_form_alter add field in node edit / create

I have a node and I need to populate a field programmatically, so here is what I do :
$campaigns = $client->get_campaigns();
$tab_campaign = array(""=>"Dernière newsletter");
foreach ($campaigns->response as $camp){
$tab_campaign[$camp->CampaignID] = $camp->Name;
}
$form['field_last_newsletter'] = array(
'#type' => 'select',
'#required' => true,
'#options' => $tab_campaign,
'#title' => 'Choisir la dernière newsletter',
);
}
This work, I have my select field populated but when I select one and click on save nothing is saved, if I come back to the edit page the select have the default value, what I am doing wrong ?
Thanks.
I think you're looking for a allowed_values_function
setting for option fields. It is a perfect solution for fields with dynamic options.
First, you need to change the current field settings to use the function to set the allowed values.
To do this, modify the field settings in features (if used):
// Exported field_base: 'field_last_newsletter'
// my_module.features.field_base.inc
$field_bases['field_last_newsletter'] = array(
// ....
'settings' => array(
'allowed_values' => array(),
'allowed_values_function' => 'my_module_field_last_newsletter_allowed_values',
),
// ....
);
If you do not use features, you can make this change by executing the PHP code or using hook_update_N
/**
* Implements hook_update_N().
* Update the field_last_newsletter field settings to use callback for allowed_values.
*/
function my_module_update_N(&$sandbox) {
// get default status for field using machine name of field
$default_stats_field = field_info_field('field_last_newsletter');
// unset the allowed values
$default_stats_field['settings']['allowed_values'] = '';
// function name that provides array of values
$default_stats_field['settings']['allowed_values_function'] = 'my_module_field_last_newsletter_allowed_values';
// update value with new value.
field_update_field($default_stats_field);
}
After saving the new settings, you need to implement the callback function for the dynamic allowed values.
/**
* Allowed values callback for field_last_newsletter.
*/
function my_module_field_last_newsletter_allowed_values() {
// ...
$campaigns = $client->get_campaigns();
$tab_campaign = array(""=>"Dernière newsletter");
foreach ($campaigns->response as $camp){
$tab_campaign[$camp->CampaignID] = $camp->Name;
}
return $tab_campaign;
}
The issue here is that you are defining a field in code and since this was not created through the UI a database table to store it's value was not created. I would suggest you create this field through the UI (/admin/structure/types/manage/xxxxx/fields) and in your hook_form_alter you just change the #options array to populate it. This way a database table for your data will be created and Drupal will handle saving the data, populating the saved value, etc...

cakephp form validation for counting multiple textareas as a group

Is it possible to validate a group of form textareas at once? I would like to check that at least 5 out of 15 text areas are notEmpty. Any suggestions on a method for doing this?
If you're going to down vote, explain why.
I've read http://book.cakephp.org/view/150/Custom-Validation-Rules#Adding-your-own-Validation-Methods-152 but it isn't clear to me how I would group multiple field items together and only check for a minimum of 5 notEmpty cases.
Edit: I'm using version 2.3.7
I don't really have any code to show because I'm just trying to do a data validation on a form with many textareas. My form isn't working right now due to other issues. If this was the only problem I could post all the code, but right now it would just confuse matters. I'm looking for a descriptive answer of how to validate a group of fields together.
Attach the validation rule to one textarea
You can do this by attaching the validation rule to any one of the text areas e.g.
class Foo extends AppModel {
public $validate = array(
'textarea_1' => array(
'atLeast5' => array(
'rule' => array('validate5Textareas'),
'message' => 'Please put text in at least 5 of the little boxes'
)
)
);
public function validate5Textareas() {
$filledTextAreas = 0;
// adapt this to match the names/logic of the real form
for ($i = 1; $i <= 15; $i++) {
if (!empty($this->data[$this->alias]['textarea_' . $i])) {
$filledTextAreas++;
}
}
return $filledTextAreas >= 5;
}
}
The $validate array defines a rule such that validate5Textareas is called if textarea_1 is in the data passed to save.
The function validate5Textareas will return true if 5 or more have text in them and false otherwise.

Customizing layout to sfWidgetFormDoctrineChoice

I am using Symfony 1.4 sfWidgetFormDoctrineChoice
I have added the checkboxes to the form, which pulls the Model data successfully. What I want to do is also include a thumbnail next to the checkbox, along with the title.
$this->setWidget('bulkUploadVideos', new sfWidgetFormDoctrineChoice(array(
'model' => 'MediaAsset',
'query' => Doctrine_Query::create()->select('u.url')->from('MediaAsset u')->orderBy('id DESC'),
'add_empty' => false,
'multiple' => true,
'expanded' => true
)
));
This does a fantastic job of pulling the query into a list of checkboxes arranged like so:
⧠ Greenjeans
⧠ Mr Magoo
⧠ Droopy
In the Media Assets table, I also have an image url that I want to include in the layout. SO it would look like this:
|-img thumbnial- | ⧠ Greenjeans
|-img thumbnail- | ⧠ Mr. Magoo
|-img thumbnial- | ⧠ Droopy
I thought maybe using a formatter class, but I do not see any change in the form.
lib/form/formatters/sfWidgetFormSchemaFormatterAllVideos.class.php
<?php
class sfWidgetFormSchemaFormatterAllVideos extends sfWidgetFormSchemaFormatter {
protected
$rowFormat = "<span class=\"my-label-class\">%label%</span>\n <span>%error%%field%%help%%hidden_fields%</span>`n",
$errorRowFormat = "<span class=\"my-error-class\" colspan=\"2\">\n%errors%</span>\n",
$helpFormat = '<br />%help%',
$decoratorFormat = "<div class='custom-video-layout'>\n %content%</div>";
}
and then i put this at the bottom of my MediaAssetsForm.class.php
public function configure() {
parent::configure();
...
..
...
$this->getWidgetSchema()->setFormFormatterName('AllVideos');
Alas, the page layout looks exactly the same. Am I incorrectly calling the Formatter, or is there a much easier way of doing this?
Which btw, still does not answer the question of how I query the image url from the table into the output for each checkbox. That's the main problem I would like to solve. Thumbnails of each record in the form.
The formatter is used to render the whole form, what you need is to change the rendering of one of the widgets.
The sfwidgetFormDoctrineChoice has an option renderer which takes a formatter as an argument. The one that you need is the sfWidgetFormSelectCheckbox. What I would do is:
create your own class which will extend the sfWidgetFormSelectCheckbox class. E.g.
class sfWidgetFormMySelectWithThumbs extends sfWidgetFormSelectCheckbox {
}
Extend the configure function so it takes another option which will hold an array of your thumbnails.
public function configure($options = array(), $arguments = array()) {
parent::configure($options, $arguments);
$this->addOption('thumbnails', array());
}
Change the formatChoices function so it adds the image in front of the checkbox (you can copy and modify the original formatChoices function).
...
$sources = $this->getOption('thumbnails');
...
$inputs[$id] = array(
'input' => sprintf('| %s | %s',
$this->renderTag('img', array('src' => $sources[$key])),
$this->renderTag('input', array_merge($baseAttributes, $attributes))
),
'label' => $this->renderContentTag('label', self::escapeOnce($option), array('for' => $id)),
);
Use the formatter class in your widget:
$this->setWidget('bulkUploadVideos', new sfWidgetFormDoctrineChoice(array(
...
'renderer' => new sfWidgetFormMySelectWithThumbs(array('thumbnails' => $thumbanils))
)
));
Of course you need to retrieve the list of thumbnails as an array where the array keys are the same as the id's used for values for the checkboxes, but that shouldn't be an issue.

Conditional File Count Validator for a Zend_Form_File_Element

In my project we have a Form where the user either needs to upload a file or specify some other information, for example in a text input.
I know that there is the possibility to attach a Count validator to the Form Element, and this works like this:
$upload->addValidator('Count', false, array('min' => 1, 'max' => 3));
This validator gets called, no matter if there are files uploaded or not. But as soon as i replace the validator with a custom version, and do not upload any files, the validator does not get called.
Looking at the isValid() method of Zend_File_Transfer_Adapter_Abstract, I can see the problem:
[...]
foreach($check as $key => $content) {
if (array_key_exists('validators', $content) &&
in_array('Zend_Validate_File_Count', $content['validators'])) {
$validator = $this->_validators['Zend_Validate_File_Count'];
$count = $content;
[...]
Seems like the Count Validator got some special treatment here. But how can I include my customized Validator, without overwriting Zend Files?
Because we do not extend the Zend_Form class, sadly I also cannot overwrite the isValid() method of the involved Form. Any Ideas left? Thanks for your time!
This would probably be easiest with a bit of ajax. That way you could evaluate the selection prior to posting the form.
To do it in PHP, an Element validator is probably not the way to go. It would be better to handle the selection with an if() statment.
pseudocode...
//if file element contains something and text doesn't
if($this->getRequest->getPost('file'=='' && 'text' != ''){
$file = $form->file->receive();
//do some stuff
//if text element contains something and file dosen't
}elseif ($this->getRequst->getPost('file' != '' && 'text' == '') {
if($form->isValid($this->_request->getPost('text')) {
//do some stuff
}
}
This is the idea, hope it helps.

Zend-form setValue , view has empty value like <input value="" >

I have a quite complex form setup using Zend-Form. At one point I'm setting value of a hidden input using :
$oHidden = new Zend_Form_Element_Hidden('ratings'.$k);
$oHidden->setValue('ratings');Zend_Debug::dump($oHidden);
$this->addElements(array($oHidden));
This method works well in other places of the same form, but this one, and another one just like i t outputs :
<input type="hidden" name="ratings1" value="" id="ratings1" />
I've dumped the $oHidden variable and it outputs :
object(Zend_Form_Element_Hidden)#143 (29) {
...
["_value":protected] => string(7) "ratings"
["_view":protected] => NULL
["_isPartialRendering":protected] => bool(false)
}
So it sets the value just fine for a while but it doesn't render it. Please let me know where to start looking reasons for this behavior.
Thanks,
Alek
The problem is precisely the isValid() function. It clears all values from the form and then repopulates it with the parametres that are passed to it. If a parametre is absent, it apparently won't appear anymore in the form, even if it was set explicitly a few lines earlier.
My case was an optional "redirect" hidden field in a login form. Here's the code (simplified for readability):
$form = new Form_Login();
$redirect = $this->_getParam('redirect','/user/login/welcome');
$form->addElement('Hidden','redirect',array('value' => $redirect));
if ($this->_request->isPost() && $form->isValid($this->_getAllParams())) {
// WTF! the "request" field has no value!!!
}
The workaround was setting the action parametre:
$form = new Form_Login();
$redirect = $this->_getParam('redirect','/user/login/welcome');
$this->_setParam('redirect',$redirect);
$form->addElement('Hidden','redirect',array('value' => $redirect));
if ($this->_request->isPost() && $form->isValid($this->_getAllParams())) {
// AHA! now it works!
}
I know the question is half a year old, but oh well, better late than never :D.
$hidden = new Zend_Form_Element_Hidden(array('name' => 'ratings', 'value' => 'ratings'));
Try it!