I'm trying to customize a label in an edit view using Smarty.
A field named decription should have label LBL_LABEL_ONE with a currency symbol if some_fieds has value 1, LBL_LABEL_TWO otherwise.
With the following code in detailviewdefs.php, I have no problems to accomplish this in the view detail:
array (
'name' => 'description',
'label' => '
{if $bean->some_field==1}
{$MOD.LBL_LABEL_ONE} {$CURRENCY}
{else}
{$MOD.LBL_LABEL_TWO}
{/if}',
),
Note that some_field is a field of the current module and $CURRENCY is assigned in view.detail.php with the following code:
function preDisplay() {
parent::preDisplay();
$currency = new Currency();
$this->ss->assign('CURRENCY', $currency->getDefaultCurrencySymbol());
}
Using same code in editviewdefs.php I have several problems:
First: the following fatal error getting the field of the bean:
Fatal error: Smarty error: [in
cache/modules/omn_fornitura_gas/EditView.tpl line 506]: syntax error:
invalid attribute name: '$bean->some_field'
(Smarty_Compiler.class.php, line 1536) in
C:\xampp\htdocs\sugar\include\Smarty\Smarty.class.php on line 1095
Second: the variable $CURRENCY seems not to be correct:
{€' module='omn_fornitura_gas'}
instead of
€
Quite a puzzle this one.
The reason you're seeing such a thing is that Sugar seems to render Smarty Detail and Edit view definitions quite differently.
The Problem
In detail, it very neatly compiles the field as such:
cache/modules/omn_fornitura_gas/EditView.tpl
{capture name="label" assign="label"}
{if $bean->some_field==1}
{$MOD.LBL_LABEL_ONE} {$CURRENCY}
{else}
{$MOD.LBL_LABEL_TWO}
{/if}{/capture}
However, in edit, it tries to insert it as an attribute of a translated label:
cache/modules/omn_fornitura_gas/EditView.tpl
{capture name="label" assign="label"}{sugar_translate label='
{if $bean->some_field==1}
{$MOD.LBL_LABEL_ONE} {$CURRENCY}
{else}
{$MOD.LBL_LABEL_TWO}
{/if}' module='omn_fornitura_gas'}{/capture}
This explains both the issues you're seeing, as it complains about the attribute, and displays the module name in the bottom line.
So what can we do about it?
Unfortunately, as the edit/detail templates are compiled and cached by Sugar, we can't feasibly get to them directly without digging quite deeply into the Sugar code.
However, what we can do is work around it by specifying a different label, and then setting that label dynamically, just like you were doing in the metadata, but this time via PHP in view.edit.php.
Try this:
editviewdefs.php
array (
'name' => 'description',
'label' => 'LBL_CUSTOM_LABEL',
),
view.edit.php
function preDisplay() {
parent::preDisplay();
$currency = new Currency();
global $mod_strings;
if ($this->bean->some_field == "1"){
$mod_strings['LBL_CUSTOM_LABEL'] = $mod_strings['LBL_LABEL_ONE'] . " " . $currency->getDefaultCurrencySymbol();
}
else {
$mod_strings['LBL_CUSTOM_LABEL'] = $mod_strings['LBL_LABEL_TWO'];
}
}
What happened there?
$mod_strings is a global variable in sugar that holds the current module's labels. What we've done here is use that to our advantage, and conditionally set what the label should be by setting the property of this custom label when the view is generated. Appreciated that this isn't technically a solution using Smarty, but I hope my above details can help shine a light on the inability to solve this problem exactly the same as the detail view definitions within Sugar.
Let me know if that helps, or if I can provide any further information!
Related
I'm using lexpyrocms parser as a package installed with composer along with a codeigniter framework with HMVC, wich allows me to use {{pseudo-variable}} in my templates/views.
I have a very weird behavior whith the parser syntax in my view :
I have this simple $modules array as data that I can print_r() in the view/template
$modules =
Array (
[users] => stdClass Object ( [id_mdl] => 8 [name_mdl] => users ),
[actions] => stdClass Object ( [id_mdl] => 9 [name_mdl] => actions )
);
If I use basic Lex syntax, I can display the name_mdl without problem with
{{modules}} {{name_mdl}} {{/modules}} => output 'users' and 'actions'
but when I use the conditional 'if' inside the loop, I get a wrong matching when I test if a variable exists :
{{modules}}
{{name_mdl}}
{{/modules}}
this outputs correctly users actions
{{modules}}
{{if exists name_mdl}}
name_mdl OK {{name_mdl}}
{{endif}}
{{/modules}}
but this does not output anything : /
{{modules}}
{{if not exists name_mdl}}
name_mdl NOT OK {{name_mdl}}
{{endif}}
{{/modules}}
This outputs 'name_mdl NOT OK users
name_mdl NOT OK actions'
the parser displays correctly a variable it just recused as existing in the condition..
I've searched a bit everywhere but it looks like an orphan problem, can't find a clue anywhere ..
Well.. I managed to get rid of this strange behavior, but I'm not sure which part of the changement I've made solved the problem ...So for what it's worth :
The error I faced was that in a loop {{list_of_things}}{{/list_of_things}} the checking of an existing variable with conditional if exists wasn't possible, though the display of this variable worked fine :
{{list_of_things}}
{{ list_name }} <-- display the list_name of each entry
{{ if exists list_name }}
The condition was never met, tough the data 'list_name' can be displayed above
{{ endif }}
{{/list_of_things}}
I did two things after that, and got rid-off the problem...
1- I moved the declaration of the Lex Parser $this->parser = new Lex\Parser();
from my front controller application/modules/my_module/module_controller.php
into the constructor of my extending core controller class application/core/MY_Controller.php
2- I cleaned up my views folder cause there where some double file from earlier development :
to be noted : the view called was and is application/modules/my_module/views/theme/my_template.php
before :
modules/my_module/views/
my_template.php
modules/my_module/views/theme/
my_template.php
after :
modules/my_module/views/
modules/my_module/views/theme/
my_template.php
So my best guess is that HMVC messed a bit the Lex Parser with the 'loaded_paths', and that two views with the same name in the same module (even though not in the same directory) can lead to unexpected behavior .. but I don't see why the hell that would change the conditionals of the parser ...
How can I show a validation error for a form field outside of a field constructor in Play framework 2? Here is what I tried:
#eventForm.("name").error.message
And I get this error:
value message is not a member of Option[play.api.data.FormError]
I'm confused because in the api docs it says message is a member of FormError. Also this works fine for global errors:
#eventForm.globalError.message
You can get a better grasp of it checking Form's sourcecode here
Form defines an apply method:
def apply(key: String): Field = Field(
this,
key,
constraints.get(key).getOrElse(Nil),
formats.get(key),
errors.collect { case e if e.key == key => e },
data.get(key))
That, as said in the doc, returns any field, even if it doesn't exist. And a Field has an errors member which returns a Seq[FormError]:
So, you could do something like that (for the Seq[FormError]):
eventForm("name").errors.foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm("name").error.map { error =>
<div>#error.message</div>
}
Or, you could use Form errors:
def errors(key: String): Seq[FormError] = errors.filter(_.key == key)
And get all errors of a given key. Like this (for the Seq[FormError]):
eventForm.errors("name").foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm.error("name").map { error =>
<div>#error.message</div>
}
If you want more details, check the source code. It's well written and well commented.
Cheers!
EDIT:
As biesior commented: to show human readable pretty messages with different languages you have to check how play works I18N out here
To be thorough you're probably going to have to deal with I18N. It's not hard at all to get it all working.
After reading the documentation you may still find yourself a bit consufed. I'll give you a little push. Add a messages file to your conf folder and you can copy its content from here. That way you'll have more control over the default messages. Now, in your view, you should be able to do something like that:
eventForm.errors("name").foreach { error =>
<div>#Messages(error.message, error.args: _*)</div>
}
For instance, if error.message were error.invalid it would show the message previously defined in the conf/messages file Invalid value. args define some arguments that your error message may handle. For instance, if you were handling an error.min, an arg could be the minimum value required. In your message you just have to follow the {n} pattern, where n is the order of your argument.
Of course, you're able to define your own messages like that:
error.futureBirthday=Are you sure you're born in the future? Oowww hay, we got ourselves a time traveler!
And in your controller you could check your form like that (just one line of code to show you the feeling of it)
"year" -> number.verifying("error.furtureBirthday", number <= 2012) // 2012 being the current year
If you want to play around with languages, just follow the documentation.
Cheers, again!
As you said yourself, message is a member of FormError, but you have an Option[FormError]. You could use
eventForm("name").error.map(_.message).getOrElse("")
That gives you the message, if there is an error, and "" if there isn't.
In order-detail.tpl, there are variables such as {$is_guest} and {$return_allowed}. A little debugging (using Javascript alert) shows that {$is_guest} is undefined for some reason and {$return_allowed} returns 0 even though I allowed returns. This is leading to the order-detail page hiding merchandise return section.
All these Smarty variables are defined in root/controllers/OrderDetailController.php, so I don't know what's causing the errors.
I'm using Prestashop 1.4.9. Any help is greatly appreciated. Thank you!
I solved my own question. Go to root/controllers/OrderDetailController.php. Around line 144, change
'is_guest' => false,
to
'is_guest' => "false",
And also, change
{if !$is_guest}
to
{if $is_guest == "false"}
As for $return_allowed, it turns out that the items must be marked as delivered first in the BO. It is defined such that it is false unless paid for + delivered + before return deadline.
I spent more than 10 hours to find out the typo for debugging my PHP program. I expected PHP would produce an error when using an undefined variable. But when it is used as an object in a method, it doesn't. Is there a reason for it?
<?php
$oClass = new MyClass;
// $oCless->tihs('key', 'taht'); //<-- triggers the error: Notice: Undefined variable
$oClass->tihs('key', 'taht');
echo $oClass->arr['key'];
class MyClass {
public $arr = array('key' => 'foo');
function tihs($key, $value) {
$tihs->arr[$key] = $value; //<-- this does not cause an error message.
}
}
?>
Normally if the error reporting level is set to E_ALL | E_STRICT (or E_ALL as of PHP 5.4.0) it should spit out an E_STRICT error. For instance, this code:
error_reporting(E_ALL | E_STRICT);
$tihs->adrr = 453;
Produces:
Strict Standards: Creating default object from empty value in [...]
Interestingly enough, if you specifically create an array instead of an ordinary variable as a property of an object that doesn't exist, e.g.:
error_reporting(E_ALL | E_STRICT);
$tihs->adrr[25] = 453;
No strict standards error is shown! It looks like this could potentially be something PHP folks might want to fix, because I'm not aware this is documented nor I think there's a legitimate reason for this behaviour.
For the record, in both cases regardless of the error a new stdClass is being created on the fly instead, like sberry mentions in his answer.
It is because of PHP trickery...
Under the covers, PHP is actually creating an object called tihs, adding an array to the object called arr and setting key to value.
Here is a print_r($tihs); after the assignment:
stdClass Object
(
[arr] => Array
(
[key] => taht
)
)
You seemed to have misspelt $oClass as $oCless
Agreed, $oCless instead of $oClass would give you an undefined variable error.
Also, "this" is a keyword in most languages and may be in php as well. You should refrain from using it so that it doesn't come out in other languages as a habit. You'll get way more errors if you're using "this" as function and variable names. You wouldn't even get things to compile.
How do you set an error message for max_length and min_length rules. For instance, if I set a rule max_length[6], I'd like the error message to display
Max characters allowed: 5
I got the same problem and even though this post is old, there's no correct answer.. You just have to use the string placeholder %s in second place of your message. In the documentation (http://codeigniter.com/user_guide/libraries/form_validation.html#settingerrors) there is an example for a field not being empty:
$this->form_validation->set_message('username_check', 'The %s field can not be the word "test"');
There, it uses the %s placeholder for the name of the field, but if you modify the 'max_length' message putting the field name first and the length second like this:
$this->form_validation->set_message('max_length', 'The field %s max length is %s');
it will work. Is not the best solution, but that one works for me. Hope it helps
application/language/en/en_lang.php I have this:
$lang['name'] = "Name";
$lang['form_required'] = "is required.";
application/language/es/es_lang.php I have this:
$lang['name'] = "Nombre";
$lang['form_required'] = "es requiero.";
application/controllers/yourController.php I have this:
$this->form_validation->set_rules('name', $this->lang->line('name'), 'required|alpha|xss_clean');
$this->form_validation->set_message('required', '%s ' . $this->lang->line('form_required'));
I hope this help!
#Daniel is correct. Per CodeIgniter's documentation, you can override the default error message for any validation rule (such as "min_length", "max_length", etc.) like this:
$this->form_validation->set_message('validation_rule', 'Your message here');
So, in your example you could do:
$this->form_validation->set_message('max_length', 'Max characters allowed: 5');
Simply include that where your validation rules exist.
gAMBOOKa,
create a 'new' rule that also checks for max_length
$this->form_validation->set_rules('username', 'Username', 'required|_max_length[12]');
and for the method..
function _max_length($val)
{
if (strlen($this->input->post('username')) > $val)
{
$this->form_validation->set_message('_max_length', 'Max characters allowed: 5')
return FALSE;
}
return TRUE;
}
add this to your controller as a new rule and set the message like so ---^
CodeIgniter has one of the better documentations out of all the frameworks. Read the userguide on their site or the one in your CI directory.
http://codeigniter.com/user_guide/libraries/form_validation.html#settingerrors
Take a look in system/language/english/form_validation_lang.php and you'll find
$lang['max_length'] = "The %s field can not exceed %s characters in length.";
Which is easily overridden by copying it to
application/language/english/form_validation_lang.php
And changing it to the string you'd like. Do not edit the file in system/ directly, then it'll be overwritten if you upgrade CodeIgniter.
There is no need to add a new method. You may set a custom message to a form validation error by accessing the "max_length" rule as shown below.
$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]', array('required' => 'Username is required.','max_length' => 'Max characters allowed: 5')
);
Note: This is also applicable for "min_length" rule.