Sonata admin brainstorm - symfony

I have 3 entities, two(with Sonata Admins) of which are referenced in the third through one-to-many relationships which also has extra fields. 1st Entity is Journalist which basically manages journalists, 2nd Entity is Event which manages events. Last admin is JournalistEvent which has Journalists who have indicated they want to cover Event and also includes extra fields like isApproved etc.
I want to create a custom list action in the Event Admin to show journalists attending that event. How do i go about it?
Do I create a custom action on Event Admin or do I create a custom query on Journalist Admin to filter journalists attending the event? I have an idea of the former but the latter seems a better way of creating the solution.

You can first list the events and then you can list the Journalists attending each event by using sonata_type_collection form type. If you want to filter out the event list, you may have to write a custom query for that. You can add the following function to the admin class for that.
public function createQuery($context = 'list')
{
$query = parent::createQuery($context);
$query
->orderBy($query->getRootAlias().".eventName", "ASC")
->andWhere(
$query->expr()->orX(
$query->expr()->eq($query->getRootAlias().".isActive", 1),
$query->expr()->isNull($query->getRootAlias().".isActive")));
return $query;
}
This is just a sample query. You will have to modify it. Hope it helps.

Related

Is there anyway to pass dql to doctrine criteria

I am using Symfony3 framework, and I have user entity, and file entity. I wanted to present in sonata administration user list with sum of all size files which are uploaded by user. When I want to make that field sortable I am getting error:
`Catchable Fatal Error: Argument 1 passed to Sonata\DoctrineORMAdminBundle\Datagrid\ProxyQuery::entityJoin() must be of the type array, null given, called in /home/milos/sites/coinaphoto/vendor/sonata-project/doctrine-orm-admin-bundle/Datagrid/ProxyQuery.php on line 143 and defined`
I have custom function in User entity which is calculating sum of files. It returns string.
My question will be can I somehow pass dql to criteria in order to get sum. Or can you suggest some other way to implement this?
` public function getStoragge(){
$criteria = Criteria::create()
->where(Criteria::expr()->someexpression...);
$matches = $this->file->matching($criteria);
}`
Something similar like when you need to aggregate fields
` $dql = "SELECT SUM(e.amount) AS balance FROM Bank\Entities\Entry e " .
"WHERE e.account = ?1";
$balance = $em->createQuery($dql)
->setParameter(1, $myAccountId)
->getSingleScalarResult();`
I don't know about your dql thing, but some fact about sorting in Sonata Admin table views. The problem is, that sorting actions still be made in the background with database operations, no matter what you are doing "virtual" in your model. If you are adding just a method to your model, the datagrid is not able to involve this method/property in sorting.
My experience is, that you can't sort by fields which are not physically available in the corresponding table. Even if you write the whole query for yourself, if you click on the sort buttons, a complete other query is fired which is ignoring your request.
I'll be pleased if somebody tell me the contrary ...
See also this issue https://github.com/sonata-project/SonataAdminBundle/issues/1077

Embedded form persistence : get or create

I work with Symfony2 and doctrine. I currently have an entity called Person. This entity is related to some other entities as a One-To-Many relation (as a Many-To-One unidirectional relation). I want each Person entity to be unique (what I have done in my database by using the UniqueConstraint annotation).
To be clear, I will assume that I have two entities called Home and Car which both have a Many-to-One relation to the target entity Person.
Then I am using forms to create or edit my entities Car and Home. In these forms, I display a embedded form to create a Person entity or select one existing. I explain : the first field of my embedded form is the name of the person. As the user type the name of the person, a list of the existing persons is displayed (using JQuery Autocomplete UI) and if the user select one of them the other fields are autocompleted.
The issue is when the user submit the form with an existing person, I caught an Integrity Error (and I know why, because of my Unique Constraint).
One of the first workaround is to add the id field as an hidden input in the embedded form.
But then the user can edit the other fields and corrupt the current entity.
So no.
Another one could be to prevent the persist in the controller if the Person already exist, but as I am using this in many other entities. I will have to duplicate my code, and I do not want to, as the unique constraint is related to the Person entity and not to the Car or Home entity.
So no again.
The workaround that I am working about is to use a PrePersist Listener waiting for a Person entity, but I do not know how to cancel persist (and maybe it is not possible).
I have the following code :
public function prePersist(LifecycleEventArgs $args) {
$entity = $args->getEntity();
if($entity instanceof Personne) {
$em = $args->getEntityManager();
$persons = $em->getRepository('MyBundle:Person')->findBy(array(
// unique fields
));
if(count($persons) > 0) {
// ... ???
}
}
I have tried a $em->detach but it is useless as I am already persisting the entity.
What I want it is just a kind of a "Get Or Create". I explain, there are only two cases :
the Person entity (not persisted) has all the same fields that one existing in the database (excepted the id field), so the Person entity is the one in the database. I have to "replace" it by the one in the database ;
the Person entity (not persisted) is unique in the database, so we create a new one (persist).
Create your own getOrCreate() method and call it inside your listener.
See this post Symfony2 doctrine FindOneOrCreate
Another possibility would be the data transformers. http://symfony.com/doc/current/cookbook/form/data_transformers.html

Drupal 7 filter field current user

I've created a custom event content type in Drupal 7 with user fields of teacher and student. I would like to create a view in which the content is displayed only for the users who are either teachers or students in that content - a custom calendar.
So far, I've tried to create a filter on Content: Teacher (field_teacher), using user:uid and user. I know it's a syntax problem, but I need the value to be currentlyLoggedinUser
To get the currently logged in user uid, follow this code snippet.
global $user;
$uid = $user->uid;
Hope this works... Muhammad.
Try adding a Relationship To the field Content: Teacher (field_teacher) first and then check the filter options again to see if the one you need is now available.
Why don't you just create two different displays and use the Access views option to filter based on the user's role?
Putting that suggestion aside: You shouldn't be using two fields to distinguish between a teacher and a student for your content type. Use a single field select list. Values would be 0 for student, 1 for teacher, as an example.
Then add that field as a Contextual Filter, select Provide default value and use PHP Code as the type. Use the following code to determine the role of the user and return the appropriate value:
global $user;
if(in_array('student', array_values($user->roles))) {
return 0;
} else {
return 1;
}
I would recommend my first suggestion though and make use of the access based on roles.
It was actually a pretty simple solution - I created contextual filters on the two entity references (student and teacher), then in the section "If no default provided", I added "use currently logged in user".
I then had to write a custom module with a hook_query_alter to change the contextual filter's AND to an OR

Add a search form in a manyToMany Relation interface

How to implement a search form in a many to many relation between entities.
I want to search items from an entity before to add them to my other entity. I am using a long list of items (product) that i need to link to Shops and i can't use a simple listbox to select my items.
I need you to point me to a tutorial or any explaination to deal with this interface problem.
The goal is to use a minimum of javascript
I would suggest to create an view where you could select a category or define your search condition. And a second View where you only display products by the previously selected condition. In your second view you could use an entity Field Type ( http://symfony.com/doc/current/reference/forms/types/entity.html#query-builder ) and provide a custom query for the entities like:
use Doctrine\ORM\EntityRepository;
// ...
$builder->add('users', 'entity', array(
'class' => 'AcmeHelloBundle:Product',
'query_builder' => function(ProductRepository $er) {
return $er->createQueryBuilder('p')
->where('p.category = 1);
},
));
This solution doesn't require JavaScript at all.
I spent lot's of time trying to figure out the best solution to make the compromise between re-usability, performance and ergonomy and i found a nice solution
I did this way :
I created a custom form field that show a collection like entity field type but i pass field names that I want to show in a nice table :
->add('products','reflist',array(
'columns'=>array('name','cost','description'),
'actions'=>array('select'=>true,'remove'=>true),
'entityName'=>'VendorProductBundle:Product',
'searchForm'=> 'Vendor\ProductBundle\Form\ProductSearchType'
));
Then I created a generic searching service that takes in input the entity to search on. The result is sent in a popup paginated.
Finally, I created a controller related to my new field to manage actions like add, remove
Thats's it for the logic.
I can't really share the work since it is really dependent of my framework (depend of search service, layout,etc...)

Drupal: help with content type creating & linking nodes

I have a situation where someone can create a job content type. I've added a CCK field that is related to the 'organisation' content type. So when someone creates a new job posting they can choose which organisation the job is for in that field (auto completed). The problem is I can create a new job and select any organisation, even if I didn't create that organisation myself.
Is there a way I can restrict what someone types in that field to 1. an organisation name that exists, and 2. an organisation that belong to that user?
I'm using drupal 6.
Any help most appreciated!
Jonesy
You can use a php rule for the allowed values array of your node reference field, which I think in your case would need to run a quick query for all the nodes made by the current user.
I have not tested this code, but it should be reasonably close to what you're after if I have understood the question!
global $user; //make sure we have access to the user
//find all the job organisation nodes made by this user
//(replace organisation with the actual name of your content type)
$query = db_query("select nid from {node} where type = 'organisation' and uid = %d", $user->uid);
//put the results in the values array
$values = array()
while($result = db_fetch_result($query)){
$values[] = $result;
}
I'm not in a place where I can check this easily, but you could also try using a select on the edit page, and display the choices with a view. Then, create a view over the content type and check that the node user is the logged in user.
You could use a Nodereference field.
It's Autocomplete, and on the bottom of the settings of the field, you can select a View to filter the Nodes that can be referenced ( it's called "Advanced - Nodes that can be referenced (View) ")
Just make a View limiting the nodes to nodes that the current logged in user created, and use that on the Nodereference settings page.
Using that option, drops the option 'Content types that can be referenced' which is located above the Advanced settings.
So make sure to add a filter on node type.
I assume you already use Nodereference, and you might have looked past that option

Resources