ZF2 dynamic collection validators - doctrine-orm

I've tried to add a dynamic validator to a collection but everything I've tried hasn't worked.
If I have - let's say - 3 fieldsets in a collection, I only want the second fieldset (with name "1") to have a required field.
$input_filter = new Filter\Edit();
$collection_input_filter = new CollectionInputFilter();
$orderDetailFilter = new Filter\OrderDetail($serviceManager);
$collection_input_filter->setInputFilter($orderDetailFilter);
$input_filter->add($collection_input_filter, 'details');
$this->setInputFilter($input_filter)
->setHydrator(new DoctrineHydrator($entityManager))
->setObject(new Order());

Check this:
http://www.aronkerr.com/2013/11/zf2-form-collection-validation-unique.html
He adding unique values for an element in a fieldset collection. He extend the InputCollectionFilter.
You can do the same way for your custom key validation.
You have to extend the isValid Method from the CollectionInputFilter.
Write your own CollectionInputFilter and extend it from the Zend\InputFilter\CollectionInputFilter.
Add your own property:
protected validateFieldsetKeys = array()
for Example
with a setter Method.
When you´re adding your CollectionInputfilter (in your factory or controller), just call your own and add your fieldsetkeys like this:
$collection_input_filter = new CollectionInputFilter();
$collection_input_filter->setValidateFieldsetKeys(array(2,3));

Related

How can I enhance a Drupal 8 Views Bulk Operations Confirm Page?

For a custom Views Views Bulk Operations action, I would like to enhance the information in the list on the confirm page, For example, instead of:
LastName1
LastName2
I would like to have:
LastName1, FirstName, Prefix
LastName2, FirstName, Prefix
Where is the best place to alter this?
There are basically two ways to do this in Drupal 8:
using hook_form_views_bulk_operations_confirm_action_alter. This will allow you to alter the list, for example with custom values and code.
If you have defined a custom action plugin, then in the plugin annotiation you can declare the route name to a custom validation form. This will allow you to do anything you want, including multi-step forms. When you define that custom form, you should subclass Drupal\views_bulk_operations\Form\ConfirmAction, since it's buildForm method takes parameters additional to that of a regular form. So your Plugin would start like this:
/**
* Action description.
*
* #Action(
* id = "my_special_action",
* label = #Translation("My Special Action"),
* type = "custom_entity",
* confirm_form_route_name = "my_module.my_special_action_confirm_form",
* )
*/
class MySpecialAction extends ViewsBulkOperationsActionBase {
}
and the Form will look something like this:
use Drupal\views_bulk_operations\Form\ConfirmAction;
class MySpecialActionConfirmForm extends ConfirmAction {
public function getFormId() {
return 'my_special_action_confirm_form';
}
public function buildForm(array $form, FormStateInterface $form_state, $view_id = NULL, $display_id = NULL) {
....
}
In the custom form class, you will have to define your own submitForm method, if you want to pass anything special to the custom action.

How to query based on one-to-many relationships in Spring Data Neo4j

I have defined simple one-to-many relationship as:
#Relationship(type = "BELONG")
private Set<Category> categories;
I want to query all the objects based on the exact set of Category. i.e. implement something like:
Page<SomeObject> findAllByCategories(Set<Category> categories, PageRequest page);
What is the best way to do it in Spring Data Neo4j?
You have a couple of options on how you can do this.
Your calling code can simply call the following on your SomeObjectRepository:
Iterable<Long> ids = categories.stream().map(SomeObject::getId).collect(Collectors.toSet());
Iterable<SomeObject> someObjects = someObjectRepository.findAll(ids, 1);
Note this method does not support paging though.
Another way is to inject a Session into your calling code and either write a custom Cypher query to retrieve the objects you want or use the load all by instance method:
#Autowired
private Session session;
...
// Option 1: write some cypher
Map<String, Object> params = new HashMap<>():
params.put("ids", ids) // use a stream like above to collect the ids.
Iterable<SomeObject> someObjects = session.query(SomeObject.class, "MATCH (n:SomeObject) ...", params);
//Option 2: use the load by instances method which also allows pagination:
Collection<SomeObject> someObjects = session.loadAll(categories, new Pagination(0, 25));
My recommendation would be option 2 as it pretty much does exactly what you want.

Creating Groups out of two different lists

I guess this is an easy one but I have no clue how to do this.
I have two lists of Persons
List<Person> specificPersons
List<Person> allPersons
I would like to create groups out of the two complete lists like the following with linq.
IEnumerable<IGrouping<string, Person>> personsGroups
The string will be any custom string. I would use this to display both lists separated by a group header in a Windows 8.1 Metro Application ListView using a CollectionViewSource binding to the IEnumerable.
You can do something like this:
string headerSpecific = "Specific";
string headerAll = "All";
var query =
specificPersons.GroupBy(_ => headerSpecific )
.Union(
allPersons.GroupBy(_ => headerAll));
Note you have other ways to accomplish similar functionality (although not matching your question's requirements), for instance using anonymous types instead of groups:
var query =
specificPersons.Select(p => new { Header = headerSpecific, p})
.Union(
allPersons.Select(p => new { Header = headerAll, p}));
I would suggest adding a Group property to Person, which you can set via a simple loop on each of your lists. Then you can do this:
IEnumerable<IGrouping<string, Person>> personsGroups = specificPersons.Concat(allPersons).GroupBy(p => p.Group);
Note that this would not make sense if Person is a domain entity and/or exists in your database. Since these groups are for display purposes, use a view model (e.g. PersonViewModel) and add the Group property to that model to avoid changing your domain model.

Persisting domain model w/ list of enums not working in GORM/Grails

My model needs to have multiple enums of the same type:
class Broker {
static constraints = {
brokerTypes(nullable:false)
}
List<BrokerType> brokerTypes
}
The model is being instantiated with the params from the request, which has in it a list of BrokerTypes:
def save(){
def brokerInstance = new Broker(newParams)
System.out.println(brokerInstance.getBrokerTypes().toString());
if (!brokerInstance.save(flush: true)) {
render(view: "create", model: [brokerInstance: brokerInstance])
return
}
redirect(action: "show", id: brokerInstance.id)
}
The println prints out the list of BrokerTypes as expected, so i know that it exists in the instance. Later, the model is retrieved as follows:
def brokerInstance = Broker.findByLatAndLon(lat,lon)
System.out.println(brokerInstance.getBrokerTypes().toString());
This time the println prints out 'null'
So i imagine the problem is that GORM doesn't know how to store this list of enums, and instead when the brokerInstance.save() is called, its saving the brokerTypes field as null.
Do i need to create a mapping somehow to get GORM to recognize the list? A hack alternative would be to instead of storing the list of enums, to store a list of strings or something and then map back to the enum when needed, but this doesnt seem clean
You will have to use a hasMany clause so that grails/gorm initializes a one to many relationship
You should add the following snippet to your domain class.
static hasMany = [brokerTypes : BrokerType]

Adding a search box to filter a list of results in Symfony?

I need to put a search box within a list of objects as a result of a typical indexSuccess action in Symfony. The goal is simple: filter the list according to a criteria.
I've been reading the Zend Lucene approach in Jobeet tutorial, but it seems like using a sledge-hammer to crack a nut (at least for my requirements).
I'm more interested in the auto-generated admin filter forms but I don't know how to implement it in a frontend.
I could simply pass the search box content to the action and build a custom query, but is there any better way to do this?
EDIT
I forgot to mention that I would like to have a single generic input field instead of an input field for each model attribute.
Thanks!
I'm using this solution, instead of integrating Zend Lucene I manage to use the autogenerated Symonfy's filters. This is the way i'm doing it:
//module/actions.class.php
public function executeIndex(sfWebRequest $request)
{
//set the form filter
$this->searchForm = new EmployeeFormFilter();
//bind it empty to fetch all data
$this->searchForm->bind(array());
//fetch all
$this->employees = $this->searchForm->getQuery()->execute();
...
}
I made a search action which does the search
public function executeSearch(sfWebRequest $request)
{
//create filter
$this->searchForm = new EmployeeFormFilter();
//bind parameter
$fields = $request->getParameter($this->searchForm->getName());
//bind
$this->searchForm->bind($fields);
//set paginator
$this->employees = $this->searchForm->getQuery()->execute();
...
//template
$this->setTemplate("index");
}
It's important that the search form goes to mymodule/search action.
Actually, i'm also using the sfDoctrinePager for paginate setting directly the query that the form generate to get results properly paginated.
If you want to add more fields to the search form check this :)
I finally made a custom form using the default MyModuleForm generated by Symfony
public function executeIndex {
...
// Add a form to filter results
$this->form = new MyModuleForm();
}
but displaying only a custom field:
<div id="search_box">
<input type="text" name="criteria" id="search_box_criteria" value="Search..." />
<?php echo link_to('Search', '#my_module_search?criteria=') ?>
</div>
Then I created a route named #my_module_search linked to the index action:
my_module_search:
url: my_module/search/:criteria
param: { module: my_module, action: index }
requirements: { criteria: .* } # Terms are optional, show all by default
With Javascript (jQuery in this case) I append the text entered to the criteria parameter in the href attribute of the link:
$('#search_box a').click(function(){
$(this).attr('href', $(this).attr('href') + $(this).prev().val());
});
And finally, back to the executeIndex action, I detect if text was entered and add custom filters to the DoctrineQuery object:
public function executeIndex {
...
// Deal with search criteria
if ( $text = $request->getParameter('criteria') ) {
$query = $this->pager->getQuery()
->where("MyTable.name LIKE ?", "%$text%")
->orWhere("MyTable.remarks LIKE ?", "%$text%")
...;
}
$this->pager->setQuery($query);
...
// Add a form to filter results
$this->form = new MyModuleForm();
}
Actually, the code is more complex, because I wrote some partials and some methods in parent classes to reuse code. But this is the best I can came up with.