zf2 validation form: How can I validate dependent fields? - zend-form

I have 5 text form
$number1 = new Text('number-1');
$number2 = new Text('number-2');
$number3 = new Text('number-3');
....
with the relative filters
foreach(...)
$input = new Input($elementName);
$validator = new ValidatorChain();
$validator->addByName('Int')
->addByName('Between', array(
'min'=>0,
'max'=>$this->maxAllowedTicket,
'inclusive'=>true));
$filter = new FilterChain();
$filter->attachByName('Int');
$input->setValidatorChain($validator);
$input->setFilterChain($filter);
I would that only one of this 3 forms can contain a value different from 0.
There are then two possible errors.
TOO MANY NUMBERS
$data['number1'] = 5;
$data['number2'] = 5;
$data['number3'] = 0;
$data['number4'] = 5;
$data['number5'] = 0;
NO NUMBER
$data['number1'] = 0;
$data['number2'] = 0;
$data['number3'] = 0;
$data['number4'] = 0;
$data['number5'] = 0;
How can I validate this multiple fields at the same time ?

You need to write your own Validator class to do so. The isValid() method of your new validation class also receives the $context which includes the values of the whole form. This way you can validate the value of each field depending on the other fields.
namespace My\Validator;
use Zend\Validator\AbstractValidator;
class CustomValidator extends AbstractValidator
{
public function isValid($value, $context = null)
{
// put your logic here and call
// $this->error(); if required
}
}

Craft your own solution using the Callback validator.
Examples are here: http://packages.zendframework.com/docs/latest/manual/en/modules/zend.validator.set.html#callback

Related

Call methods with sililar names through a loop in geb

I'm new to Geb and fairly new in Java. I ask my self if its possible to call multiple methods through a loop. For example this part:
homePage.file1 = Content.Upload()
isDisplayed(homePage.clear1, true)
homePage.file2 = Content.Upload()
isDisplayed(homePage.clear2, true)
homePage.file3 = Content.Upload()
isDisplayed(homePage.clear3, true)
I had the idea to call this through a loop cause the names are very similar to each other. Only the numbers are different.
So I thought about something like this:
String[] elements = { "file1", "file2","file3"}
for( int i = 0; i <= elements.length - 1; i++){
homePage.elements[i] = Generator.fileUpload()
}
But this won't work. Is there any other way to get this to work?
Greetings
Think this is what you're trying to achieve?:
def elements = ["file1", "file2","file3"]
elements.each {
homePage."${it}" = Generator.fileUpload()
}

Why can I not use Continuation when using a proxy class to access MS CRM 2013?

So I have a standard service reference proxy calss for MS CRM 2013 (i.e. right-click add reference etc...) I then found the limitation that CRM data calls limit to 50 results and I wanted to get the full list of results. I found two methods, one looks more correct, but doesn't seem to work. I was wondering why it didn't and/or if there was something I'm doing incorrectly.
Basic setup and process
crmService = new CrmServiceReference.MyContext(new Uri(crmWebServicesUrl));
crmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
var accountAnnotations = crmService.AccountSet.Where(a => a.AccountNumber = accountNumber).Select(a => a.Account_Annotation).FirstOrDefault();
Using Continuation (something I want to work, but looks like it doesn't)
while (accountAnnotations.Continuation != null)
{
accountAnnotations.Load(crmService.Execute<Annotation>(accountAnnotations.Continuation.NextLinkUri));
}
using that method .Continuation is always null and accountAnnotations.Count is always 50 (but there are more than 50 records)
After struggling with .Continutation for a while I've come up with the following alternative method (but it seems "not good")
var accountAnnotationData = accountAnnotations.ToList();
var accountAnnotationFinal = accountAnnotations.ToList();
var index = 1;
while (accountAnnotationData.Count == 50)
{
accountAnnotationData = (from a in crmService.AnnotationSet
where a.ObjectId.Id == accountAnnotationData.First().ObjectId.Id
select a).Skip(50 * index).ToList();
accountAnnotationFinal = accountAnnotationFinal.Union(accountAnnotationData).ToList();
index++;
}
So the second method seems to work, but for any number of reasons it doesn't seem like the best. Is there a reason .Continuation is always null? Is there some setup step I'm missing or some nice way to do this?
The way to get the records from CRM is to use paging here is an example with a query expression but you can also use fetchXML if you want
// Query using the paging cookie.
// Define the paging attributes.
// The number of records per page to retrieve.
int fetchCount = 3;
// Initialize the page number.
int pageNumber = 1;
// Initialize the number of records.
int recordCount = 0;
// Define the condition expression for retrieving records.
ConditionExpression pagecondition = new ConditionExpression();
pagecondition.AttributeName = "address1_stateorprovince";
pagecondition.Operator = ConditionOperator.Equal;
pagecondition.Values.Add("WA");
// Define the order expression to retrieve the records.
OrderExpression order = new OrderExpression();
order.AttributeName = "name";
order.OrderType = OrderType.Ascending;
// Create the query expression and add condition.
QueryExpression pagequery = new QueryExpression();
pagequery.EntityName = "account";
pagequery.Criteria.AddCondition(pagecondition);
pagequery.Orders.Add(order);
pagequery.ColumnSet.AddColumns("name", "address1_stateorprovince", "emailaddress1", "accountid");
// Assign the pageinfo properties to the query expression.
pagequery.PageInfo = new PagingInfo();
pagequery.PageInfo.Count = fetchCount;
pagequery.PageInfo.PageNumber = pageNumber;
// The current paging cookie. When retrieving the first page,
// pagingCookie should be null.
pagequery.PageInfo.PagingCookie = null;
Console.WriteLine("#\tAccount Name\t\t\tEmail Address");while (true)
{
// Retrieve the page.
EntityCollection results = _serviceProxy.RetrieveMultiple(pagequery);
if (results.Entities != null)
{
// Retrieve all records from the result set.
foreach (Account acct in results.Entities)
{
Console.WriteLine("{0}.\t{1}\t\t{2}",
++recordCount,
acct.EMailAddress1,
acct.Name);
}
}
// Check for more records, if it returns true.
if (results.MoreRecords)
{
// Increment the page number to retrieve the next page.
pagequery.PageInfo.PageNumber++;
// Set the paging cookie to the paging cookie returned from current results.
pagequery.PageInfo.PagingCookie = results.PagingCookie;
}
else
{
// If no more records are in the result nodes, exit the loop.
break;
}
}

dynamically change a part of the variable path

I know this question has been asked a bunch of times, but none of the answers (or at least what i took away from them) was a help to my particiular problem.
I want to dynamically change a part of the variable path, so i don't have to repeat the same code x-times with just two characters changing.
Here's what i got:
In the beginning of my script, i'm setting the reference to PlayerData scripts, attached to the GameManager object like this:
var P1 : P1_Data;
var P2 : P2_Data;
function Start(){
P1 = GameObject.Find("GameManager").GetComponent.<P1_Data>();
P2 = GameObject.Find("GameManager").GetComponent.<P2_Data>();
}
Later, i want to access these scripts using the currentPlayer variable to dynamically adjust the path:
var currentPlayer : String = "P1"; //this actually happens along with some other stuff in the SwitchPlayers function, i just put it here for better understanding
if (currentPlayer.PlayerEnergy >= value){
// do stuff
}
As i was afraid, i got an error saying, that PlayerEnergy was not a part of UnityEngine.String.
So how do I get unity to read "currentPlayer" as part of the variable path?
Maybe some parse function I haven't found?
Or am I going down an entirely wrong road here?
Cheers
PS: I also tried putting the P1 and P2 variables into an array and access them like this:
if (PlayerData[CurrentPlayerInt].PlayerEnergy >= value){
// do stuff
}
to no success.
First of all,
var currentPlayer : String = "P1"
here P1 is just string, not the previous P1/P2 which are referenced to two scripts. So, if you want, you can change
currentPlayer.PlayerEnergy >= value
to
P1.PlayerEnergy >= value
or,
P2.PlayerEnergy >= value
But if you just want one function for them, like
currentPlayer.PlayerEnergy >= value
Then you have to first set currentPlayer to P1/P2 which I assume you are trying to do. You must have some codes that can verify which player is selected. Then, maybe this can help -
var playerSelected: int = 0;
var currentPlayerEnergy: int = 0;
.....
//Use your codes to verify which player is selected and then,
if (playerSelected == 1) {
currentPlayerEnergy = P1.PlayerEnergy;
} else if (playerSelected == 2) {
currentPlayerEnergy = P2.PlayerEnergy;
}
//Now use your favorite function
if (currentPlayerEnergy >= value) {
//Do stuff
}
As there was no reply providing the answer I needed, I'll share the solution that did the trick for me, provided by a fellow student.
Instead of having the PlayerData scripts pre-written, I generate them using a public class function in a Playermanager script. This generates the Playerdata as attached scripts, saved into an array.
I can then access them through Playermanager.Playerlist[Playernumber].targetvariable.
Which is what I wanted to do, only with the Playerdata being attached to a script instead of a gameobject. And it works great!
Here's the full code of my Playermanager Script:
//initialise max players
public var maxplayers : int = 2;
// Initialise Playerlist
static var Players = new List.<PlayerData>();
function Start () {
for (var i : int = 0; i < maxplayers; i++){
var Player = new PlayerData();
Players.Add(Player);
Players[i].PlayerName = "Player " + i;
}
DontDestroyOnLoad (transform.gameObject);
}
public class PlayerData {
public var PlayerName : String;
public var PlayerEnergy : int = 15;
public var Fleet : List.<GameObject> = new List.<GameObject>();
}
As you see, you can put any type of variable in this class.
I hope this helps some of you who have the same problem.
cheers,
Tux

Refresh a dijit.form.Select

First, you have to know that I am developing my project with Struts (J2EE
Here is my problem :
I have 2 dijit.form.Select widgets in my page, and those Select are filled with the same list (returned by a Java class).
When I select an option in my 1st "Select widget", I would like to update my 2nd Select widget, and disable the selected options from my 1st widget (to prevent users to select the same item twice).
I succeed doing this (I'll show you my code later), but my problem is that when I open my 2nd list, even once, it will never be refreshed again. So I can play a long time with my 1st Select, and choose many other options, the only option disabled in my 2nd list is the first I've selected.
Here is my JS Code :
function removeSelectedOption(){
var list1 = dijit.byId("codeModif1");
var list2 = dijit.byId("codeModif2");
var list1SelectedOptionValue = list1.get("value");
if(list1SelectedOptionValue!= null){
list2.reset();
for(var i = 0; i < myListSize; i++){
// If the value of the current option = my selected option from list1
if(liste2.getOptions(i).value == list1SelectedOptionValue){
list2.getOptions(i).disabled = true;
} else {
list2.getOptions(i).disabled = false;
}
}
}
Thanks for your help
Regards
I think you have to reset() the Select after you've updated its options' properties. Something like:
function removeSelectedOption(value)
{
var list2 = dijit.byId("codeModif2"),
prev = list2.get('value');
for(var i = 0; i < myListSize; i++)
{
var opt = myList[i];
opt.disabled = opt.value === value;
list2.updateOption(opt);
}
list2.reset();
// Set selection again, unless it was the newly disabled one.
if(prev !== value) list2.set('value', prev);
};
(I'm assuming you have a myList containing the possible options here, and the accompanying myListSize.)

How do I mock this value using Rhino Mocks

Here is the method I'm trying to test:
public override void CalculateReductionOnYield()
{
log.LogEnter();
if (illus.RpFundStreams.Count <= 0)
{
throw new InvalidDataException("No regular premium fund streams which are required in order to calculate reduction on yield");
}
// Add the individual ReductionOnYield classes to the collection.)
foreach (RegularPremiumFundStream fs in illus.RpFundStreams)
{
foreach (int i in ReductionOnYieldMonths)
{
ReductionOnYield roy = new ReductionOnYield(i);
roy.FundStream = fs;
ReductionsOnYield.Add(roy);
}
foreach (ReductionOnYield redOnYield in ReductionsOnYield)
{
if (redOnYield.Month == 0 || illus.RegularPremiumInPlanCurrency == 0M)
{
redOnYield.Reduction = 0M;
}
else
{
double[] regPremiums = new double[redOnYield.Month + 1];
for (int i = 1; i <= redOnYield.Month; i++)
{
regPremiums[i - 1] = Convert.ToDouble(-1*redOnYield.FundStream.FundStreamMonths[i].ValRegularPremium);
}
regPremiums[redOnYield.Month] = Convert.ToDouble(redOnYield.FundStream.GetFundStreamValue(redOnYield.Month));
redOnYield.Reduction = Convert.ToDecimal(Math.Pow((1 + Financial.IRR(ref regPremiums, 0.001D)), 12) - 1);
}
}
}
How do I mock all the required classes to test the value of redOnYield.Reduction to make sure that it working properly?
e.g. how do I mock redOnYield.FundStream.GetFundStreamValue(redOnYield.Month) and redOnYield.FundStream.FundStreamMonths[i].ValRegularPremium ?
Is this a valid test? Or am I going about this the wrong way?
without more info on your objects its hard to say, but you want something like:
var fundStream = MockRepository.GenerateStub<TFundStream>();
fundStream.Stub(f => f.GetFundStreamValue(60)).Return(220000M);
var redOnYeild = MockRepository.GenerateStub<TRedOnYeild>();
redOnYeild.Stub(r => r.FundStream).Return(fundStream);
redOnYield is an object returned from iterating ReductionsOnYield. I don't see where this is coming from. If we assume it's a virtual property, then you'll want to create a collection of mock ReductionOnYield objects and stub out ReductionsOnYield to return your mocked collection (or, to make it easier to test, have CalculateReductionOnYield accept an IEnumerable and operate on that collection).
Once you get the ReductionsOnYield issue resolved, Andrew's response of stubbing out the properties will get you where you want to be. Of course, this assumes that FundStream is virtual (so it can be mocked/stubbed) as well as RegularPremiumFundStream's GetFundStreamValue and FundStreamMonths.