In a Doctrine Collection, I have identical objects, each with an integer property 'player' and another integer property called 'team'. Player could be 1,2,3... and Team can be 0,1,2,3,... and so on. 0 means 'default team'. All players belong to the default team first and foremost. A player can then become a member of other teams too. For example, player 2 can be a member of team 0, 2 and 3.
Now, I would like to get the object where Player 3 is a member of Team 2. If not, return the object where Player 3 is a member of Team 0.
How would I achieve this?
What about filter method ?
// get all your player 3 data
$player3Collection = Collection->filter(function(ObjectType $object) {
return ($object->getPlayer() == 3);
});
// then filter again or do other stuff ...
if ($player3Collection->filter(///filter team callback///)->isEmpty() {
throw new NoTeamException();
}
if ($player3Collection->count() == 1) {
return $player3Collection->first(); // default team
}
// etc ...
Found an answer using the collection's filter.
$team=2;
return $player3Collection
->filter(static function(Player $player) use ($team, $player3Collection){
if($player->team===$team){
return true;#/Got it
} elseif($player3Collection->filter(static fn(Player $p) => $p->id===$player->id && $p->team===$team)){
return false;#/A counterpart Player object with correct team exists in player3Collection, so skip it here.
} elseif($player->team===0){
return true;#/Fallback team record
}
return false;#/Exclude other teams
});
Related
I am looking for solution for my problems in checkout. First problem is that I need to make field company ID as required if field "Buy as company" is checked. ID of company checkbox is "wi_as_company". I am try to make it like code bellow, but it makes field "billing_company_wi_id" always as required (also for non-company customers).
add_filter( 'woocommerce_checkout_fields' , 'company_checkbox_and_new_checkout_fields_1', 9999 );
function company_checkbox_and_new_checkout_fields_1( $fields ) {
if (isset($_POST['wi_as_company'])) {
$fields['billing']['billing_company_wi_id']['required'] = false;
} else {
$fields['billing']['billing_company_wi_id']['required'] = true;
}
return $fields;
}
My second problem is that I want to move data (first 8 numbers) automatically from one field to another one and add 2 letters before. One field have this format:
12345678-Y-YY
and I want to move first 8 characters to another field like this:
XX12345678
I will be very grateful for any suggestions.
ANSWER FOR FIRST PROBLEM: If checkbox is checked, then field company ID is required. Write code bellow to your child themes functions.php file and change ID of elements:
wi_as_company is ID of checkbox and
billing_company_wi_id is ID of required field if checkbox is checked
add_action( 'woocommerce_checkout_process', 'afm_validation' );
function afm_validation() {
if ( isset($_POST['wi_as_company']) && isset($_POST['billing_company_wi_id']) && empty($_POST['billing_company_wi_id']) ) {
wc_add_notice( __("Please fill company ID"), "error" );
}
}
ANSWER FOR SECOND PROBLEM: Change in code ID of fields and number of characters to copy. In this case it will copy first 8 characters from "billing_company_wi_tax" to "billing_company_wi_vat" plus it will add letters "XX" before copied text. Insert this function to your child themes functions.php.
add_action( 'wp_footer', 'copy_field', 9999 );
function copy_field() {
global $wp;
if ( is_checkout() ) {
echo '<script> document.getElementById("billing_company_wi_tax").setAttribute("onkeyup","URLChange(this.value);");
function URLChange(titlestr) {
var url=titlestr.replace(/ /g,"-");
url = url.substring(0, 8);
document.getElementsByName("billing_company_wi_vat")[0].value="XX"+url;
}</script>';
}
}
Spock has setupSpec on the Spec class level. I would want to have something similar for a single test case level.
This might not be available in Spock, Does someone has a workaround for this.
void "test something"() {
setup:
User user = createUser()
when:
user.setAdress(new Address(zipCode: inputZipCode, city: inputCity))
then:
user.address.city == inputCity
user.address.zipCode == inputZipCode
cleanup:
deleteUser(user)
where:
inputCity | inputZipCode
"a" |"1"
"b" |"2"
}
Creating and deleting user is unnecessarily done after every iteration.
Could it be possible to have something la- setupSpec for a single test instead of class-level?
It is possible to manipulate the test cases to use class-setupSpec/CleanupSpec or even create a new test (with #Stepwise) to achieve this but I am looking for something good solution not a hack.
I think this is very ugly because it involves manual bookkeeping. I do not recommend you to do it like this, but anyway:
package de.scrum_master.stackoverflow.q57721328
import spock.lang.See
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
class OneTimeSetupCleanupParametrisedTest extends Specification {
#Shared User user
#Shared int iteration
User createUser() {
// Set up test fixture only if iteration == 0 (or optionally, if fixture is uninitialised)
user ?: new User()
}
void deleteUser(User userInstance) {
// Clean up counter (and test fixture, if any) only if iteration == total number of iterations
if (++iteration == specificationContext.currentIteration.estimatedNumIterations) {
userInstance.delete()
user = null
iteration = 0
}
}
// #Unroll
void "test something"() {
setup:
// Call initialiser helper for each iteration, relying on the fact that it will only
// create a text fixture if none exists yet
user = createUser()
when:
user.setAdress(new Address(zipCode: inputZipCode, city: inputCity))
then:
user.address.city == inputCity
user.address.zipCode == inputZipCode
cleanup:
// Call clean-up helper for each iteration, relying on the fact that it will only
// clean up the fixture during the last iteration
deleteUser(user)
where:
inputCity | inputZipCode
"a" | "1"
"b" | "2"
}
static class User {
Address address
User() {
println "creating user"
}
void setAdress(Address address) {
this.address = address
}
void delete() {
println "deleting user"
address = null
}
}
static class Address {
String zipCode, city
}
}
Console log:
creating user
deleting user
Update: The Spock manual says about this topic:
Sharing of Objects between Iterations
In order to share an object between iterations, it has to be kept in a #Shared or static field.
NOTE: Only #Shared and static variables can be accessed from within a where: block.
Note that such objects will also be shared with other methods. There is currently no good way to share an object just between iterations of the same method. If you consider this a problem, consider putting each method into a separate spec, all of which can be kept in the same file. This achieves better isolation at the cost of some boilerplate code.
I'm really new to C++ and I'm having a confusion over something.
What I've achieved so far is:
Created a class named CPlayer
What I want to do next is:
Create a datatype (array/map/or whatever) to store the CPlayer in for each individual player. (PS: Each player can have an entirely different ID from the other player, for example: player1 has ID 1, player2 has ID 5)
In Squirrel I could do:
local playerInfo = {}; // Create a table
playerInfo[ playerId ] <- CPlayer();
// To remove it -
playerInfo.rawdelete( playerId );
Not sure what would be best in C++ to reproduce this.
Having just looked up what a table is in Squirrel, and from reading the question above it seems the C++ version of what you want is
#include <map>
std::map<int, CPlayer> playerInfo;
The equivalent of playerInfo[ playerId ] <- CPlayer(); would be
playerInfo[playerId] = CPlayer();
and the equivalent of playerInfo.rawdelete( playerId ); would be
playerInfo.erase(playerId);
More information here
You can use std::map as shown below. Below sample should give fair idea on the usage.
std::map<into, PlayersInfo> mapPlayerInfo:
int nPlayerId1 = 1; // Player 1 Id sample
int nPlayerId2 = 2; // Player 2 Id sample
PlayerInfo player1(nPlayerId1,...); // Additional arguments to constructor if required
mapPlayerInfo[nPlayerId1] = player1;
PlayerInfo player2(nPlayerId2,...); // Sample 2
mapPlayerInfo[nPlayerId2] = player2;
//Deleting based on player Id
mapPlayerInfo.erase(nPlayerId1);
Regarding the new Ember.js routing system (described here), if I understand correctly, views are destroyed when you exit a route.
Is there any way to bypass destruction of views upon exiting a route, so that the state of the view is preserved when the user re-enters the route?
Update: Looks like, views are not destroyed unless the outlet view is being replaced in the new route. For e.g., if you are in stateA with ViewA in some {{outlet master}} and you go to stateB with ViewB in {{outlet master}}, then ViewB will replace ViewA. A way around this is to define multiple outlets when you need to preserve views, e.g., {{outlet master1}}, {{outlet master2}}, ...
A nice feature would be the ability to pass an array of views to the outlet. And also be able to choose whether views will be destroyed or just become hidden, upon exiting a route.
I have since figure out how to modify the routing system, so that views inserted into outlets are not destroyed. First I override the Handlebars outlet helper, so that it loads an Ember.OutletView into {{outlet}}:
Ember.Handlebars.registerHelper('outlet', function(property, options) {
if (property && property.data && property.data.isRenderData) {
options = property;
property = 'view';
}
options.hash.currentViewBinding = "controller." + property;
return Ember.Handlebars.helpers.view.call(this, Ember.OutletView, options);
});
Where Ember.OutletView extends Ember.ContainerView as follows:
Ember.OutletView = Ember.ContainerView.extend({
childViews: [],
_currentViewWillChange: Ember.beforeObserver( function() {
var childViews = this.get('childViews');
// Instead of removing currentView, just hide all childViews
childViews.setEach('isVisible', false);
}, 'currentView'),
_currentViewDidChange: Ember.observer( function() {
var childViews = this.get('childViews'),
currentView = this.get('currentView');
if (currentView) {
// Check if currentView is already within childViews array
// TODO: test
var alreadyPresent = childViews.find( function(child) {
if (Ember.View.isEqual(currentView, child, [])) {
return true;
}
});
if (!!alreadyPresent) {
alreadyPresent.set('isVisible', true);
} else {
childViews.pushObject(currentView);
}
}
}, 'currentView')
});
Basically we override _currentViewWillChange() and just hide all childViews instead of removing the currentView. Then in _currentViewDidChange() we check if the currentView is already inside childViews and act accordingly. The Ember.View.isEqual is a modified version of Underscore isEqual:
Ember.View.reopenClass({
isEqual: function(a, b, stack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
if (a === b) return a !== 0 || 1 / a == 1 / b;
// A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b;
// Unwrap any wrapped objects.
if (a._chain) a = a._wrapped;
if (b._chain) b = b._wrapped;
// Compare `[[Class]]` names.
var className = toString.call(a);
if (className != toString.call(b)) return false;
if (typeof a != 'object' || typeof b != 'object') return false;
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = stack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (stack[length] == a) return true;
}
// Add the first object to the stack of traversed objects.
stack.push(a);
var size = 0, result = true;
// Recursively compare objects and arrays.
if (className == '[object Array]') {
// Compare array lengths to determine if a deep comparison is necessary.
size = a.length;
result = size == b.length;
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
while (size--) {
// Ensure commutative equality for sparse arrays.
if (!(result = size in a == size in b && this.isEqual(a[size], b[size], stack))) break;
}
}
} else {
// Objects with different constructors are not equivalent.
if (a.get('constructor').toString() != b.get('constructor').toString()) {
return false;
}
// Deep compare objects.
for (var key in a) {
if (a.hasOwnProperty(key)) {
// Count the expected number of properties.
size++;
// Deep compare each member.
if ( !(result = b.hasOwnProperty(key) )) break;
}
}
}
// Remove the first object from the stack of traversed objects.
stack.pop();
return result;
}
});
So that the state of the view is preserved when the user re-enters the
route.
I would, instead, store that information in the controller (or the state manager) so that when the route is re-entered, the new view is initialized with the old state. Does that make sense? So, for example, if it's a list of posts, and one is selected, you would store the data about which post was selected in the controller (or the state manager). After visiting a specific post and then coming back to the list, that same post would be selected.
I can imagine a use case where this wouldn't be very useful (e.g. scrolling to a specific position in a long list) so maybe that doesn't answer your question.
In my application I have two views, Main View and Contacts view, and I have a saved Contacts ID.
When I load my second view, that should access default Contacts Database using my saved ID list and get these contacts information Title, etc. It leaves because the contact has been deleted.
So, How can I check if the contact that I has its ID is exists before I try to access its fields and cause a leave ?
CContactDatabase* contactsDb = CContactDatabase::OpenL();
CleanupStack::PushL(contactsDb);
for (TInt i = 0; i < CsIDs.Count(); i++)// looping through contacts.
{
TRAPD(err, contactsDb->ReadContactL(CsIDs[i])) //---->CsIDs is an array that holds IDs
if(KErrNotFound == err)
{
CsIDs.Remove(i);
}
}
CleanupStack::PopAndDestroy(1,contactsDb);
Thanks Abhijith for your help, and I figured out the reason behind this issue, I shouldn't call
ReadContactL directly under TRAPD under For loop, So I created a function that checks the ID validity
and I called it under TRAPD, and now my Contacts List View loads well, and invalid IDs removed from
My saved IDs list.
Solution is to follow Symbian C++ rules when dealing with "Leave":
void LoadContactsL()
{
CContactDatabase* contactsDb = CContactDatabase::OpenL();
CleanupStack::PushL(contactsDb);
for (TInt i = 0; i < CsIDs.Count(); i++)// looping through contacts.
{
TRAPD(err, ChickValidContactsIDL(i)) //-->Calling IDs checking function under TRAPD
if(KErrNotFound == err)
{
CsIDs.Remove(i);
}
}
CleanupStack::PopAndDestroy(1,contactsDb);
}
// A function that checks invalid IDs.
//Important Symbian rule: Return "void" for functions that "Leave" under TRAP harness.
void ChickValidContactsIDL(TInt index)
{
CPbkContactEngine* iPbkEngine = CPbkContactEngine::NewL(&iEikonEnv->FsSession());
CleanupStack::PushL(iPbkEngine);
iPbkEngine->OpenContactL(CsIDs[index]);
CleanupStack::PopAndDestroy(1,iPbkEngine);
}