Timber - Group ACF fields - wordpress

At the moment all the ACF fields attached to a post get attached to the TimberPost object without any grouping. I'd like to be able to separate them based on what Field Group they belong to. That way I could create cleaner templates in Twig.
I.e.:
Let b be the name of the Field Group which has two fields field1 and field2
Instead of current solution:
{{ post.b_field1}} and {{ post.b_field2}}
Can we do this:
{{ post.b.field1}} and {{ post.b.field2}}
I know I can get the fields for specific field group using acf_get_fields($field_group_id) but the result is an array instead of a Timber object. Is there a way to feed those fields into a TimberPost object?

SpuriouslyAwake: Try extending TimberPost with your own class, it'd look something like...
class MyPost extends TimberPost {
function field_group($field_group_id) {
return acf_get_fields($field_group_id);
}
}
In theory, this would let you do something like.. {{ post.field_group('b').field1 }} (in theory, that's untested code, but you get the gist)

Related

Set easyadmin_autocomplete Select Null by default. Symfony

I would like to know if there is any way to put null value by default in the easyadmin_autocomplete select.
The first item in the list is selected and filled with data from database but i need a null value by default and setted automaticly. The goal is a first result point to an empty one (Choose one...).
Do you know how to do it?
Can you think of any way combining the options defined below?
#easy_admin.yml
Product:
class: App\Entity\Product
controller: App\Controller\ProductController
new:
fields:
- { property: 'category', label: 'Category', type: 'easyadmin_autocomplete', type_options: { class: 'App\Entity\Category' } }
}
In this example, one select has a placeholder with the text 'Any' (Ninguno). I need to know why is handling them different.
These are the options defined for the attr fields -> type_options of the yml:
action
allow_extra_fields
allow_file_upload
attr
auto_initialize
block_name
by_reference
class
compound
constraints
csrf_field_name
csrf_message
csrf_protection
csrf_token_id
csrf_token_manager
data
data_class
disabled
empty_data
error_bubbling
error_mapping
extra_fields_message
help
help_attr
inherit_data
invalid_message
invalid_message_parameters
label
label_attr
label_format
mapped
method
multiple
post_max_size_message
property_path
required
translation_domain
trim
upload_max_size_message
validation_groups
If setting your default value would be a solution for you (like zero), service listener might be an answer:
// You need to add this listener yourself:
class ProductServiceListener
{
...
// you can manipulate entity in this level as you wish:
public function preUpdate(LifeCycleEventArgs $args)
{
// You will focus to Product entity, so block others:
if (!(get_class($entity) == 'App\Entity\Product')) {
return;
}
// Set whatever default value you want if it's null:
if($entity->getCategory() == null) {
$entity->setCategory(0); // Zero, as an example.
}
There is no way to set a placeholder like value for easyadmin_autocomplete.
The normal way for a choice type is to use the placeholder option as described in the symfony documentation. But easyadmin_autocomplete does not extend that type and it is a standalone type. Can't you use a choice type or entity type with the placeholder option. The only need for the easyadmin_autocomplete type is if there are a lot of entities and it will slow the application if all are loaded on the page.
My best bet is that you can extend the easyadmin_autocomplete. Because the easyadmin_autocomplete uses EntityType you can add the option for placeholder in the configureOptions method in the extended type. That will delegate the option to the EntityType but even then it is not displayed in the html because of the select2 javascript which also needs to be modified.
If it is a must I recommend the way to extend the type, add the option and also add custom javascript to easyadmin that will handle the new type and add the placeholder option. You can see the select2 documentation on how to set the placeholder.
But if you can use the entity or choice type for your select it is the preferred solution.

generate route to other admin class

I search over google for a long time, but I don't find any solution to my problem.
In fact I've got an entity, with two fields. One fields 'name' that is a string and a second field targetentity that is also a string containing a namespace to an entity. The namespace can be choice with a select and can be different. So I wan't in my sonata admin bundle when I'm on my list action make a link in the table to redirect to the route list of the entity select.
Someone know how to do this?
You can override the listview as described here: http://blog.webdevilopers.net/override-list-view-twig-template-in-sonataadminbundle/ or here: Modifying list view in Sonata
In the list view you have the admin class available. What you can do is add a function in your admin that return the right url:
public function generateMyUrl($object){
// add your logic here
$url = $this->generateObjectUrl($name, $object, $parameters, $absolute);
return $url;
}
In your inner_list_row template
<a href="{{ admin.generateMyUrl(object) }}" target="_blank">
your link description
</a>
I think you can use a form with type choice read this link it will help you
http://symfony.com/doc/current/reference/forms/types/choice.html

Sonata Block - Pass custom arguments

I'm new with Sonata Block Bundle.
I would like to put into my block a map. It uses some JS library. Function of the context, I need to pass different height, width etc... for example.
But I don't know if it fits with my needs.
At first, I wanted to use Sonata Block because my Maps has dependencies with some Services. So this is cool, I can centralise them.
But can I pass some arguments functions the parent who calls my block ?
Thanks for your answer.
Redfog
Okay, if I understood your question, what you want to do, is pass some custom arguments from your template (where you call your block to be precise) to the php class that is executing the block. Let's get started:
Lets add option to pass height attribute:
{% sample render of your block %}
{{ sonata_block_render({'type':'your.block.id'}, {'height': 50}) }}
Now, in your block service (php/class). You have to add this attribute as a default option in your method: setDefaultSettings, like this:
public function setDefaultSettings(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
// your options goes here, and we add our new option right after them
'height' => null // or whatever suits your needs
));
}
Finally, all you have to is access your option from your execute method like this:
public function execute(BlockContextInterface $blockContext, Response $response = null) {
$settings = $blockContext->getSettings();
// now your value can be access from $settings['height'];
}
Let me know if that's what you're looking for.

Get current URL in Twig template?

I looked around for the code to get the current path in a Twig template (and not the full URL), i.e.
I don't want http://www.sitename.com/page, I only need /page.
{{ path(app.request.attributes.get('_route'),
app.request.attributes.get('_route_params')) }}
If you want to read it into a view variable:
{% set currentPath = path(app.request.attributes.get('_route'),
app.request.attributes.get('_route_params')) %}
The app global view variable contains all sorts of useful shortcuts, such as app.session and app.security.token.user, that reference the services you might use in a controller.
Get current url: {{ app.request.uri }} in Symfony 2.3, 3, 4, 5
Get path only: {{ app.request.pathinfo }} (without parameters)
Get request uri: {{ app.request.requesturi }} (with parameters)
In symfony 2.1 you can use this:
{{ path(app.request.attributes.get('_route'),
app.request.attributes.get('_route_params')) }}
In symfony 2.0, one solution is to write a twig extension for this
public function getFunctions()
{
return array(
'my_router_params' => new \Twig_Function_Method($this, 'routerParams'),
);
}
/**
* Emulating the symfony 2.1.x $request->attributes->get('_route_params') feature.
* Code based on PagerfantaBundle's twig extension.
*/
public function routerParams()
{
$router = $this->container->get('router');
$request = $this->container->get('request');
$routeName = $request->attributes->get('_route');
$routeParams = $request->query->all();
foreach ($router->getRouteCollection()->get($routeName)->compile()->getVariables() as $variable) {
$routeParams[$variable] = $request->attributes->get($variable);
}
return $routeParams;
}
And use like this
{{ path(app.request.attributes.get('_route'), my_router_params()|merge({'additional': 'value'}) }}
You won't need all this unless you want to add additional parameters to your links, like in a pager, or you want to change one of the parameters.
You can get the current URL in Twig like this:
{{ app.request.schemeAndHttpHost ~ app.request.requestUri }}
It should be noted that if you have additional query parameters in your URL, which are not part of the configured route, the accepted answer will not include them in the current URL (path).
Why would you want extra parameters?
For example, if you have a list page with records that can be filtered by keyword and the page has pagination, most likely the query variables for "keyword" and "page" will not be in your route. But in your forward and back buttons for paging, you need the full current URL (that contains the keywords so the next page is still filtered). And you need to modify the page variable.
How to Merge In Extra Query Parameters
So you can get the current route, and merge in the extra variables (after modifying one or more of those extra variables). Note that you are merging in your own variables to the app.request.query.all, and then merging that array into the app.request.attributes.get('_route_params'). The path() method requires that you provide all the required parameters of the route, which is why you need to include the _route_params.
{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')|merge(app.request.query.all|merge({'page': 2 }))) }}
That's really ugly, but if you are developing pagination, you will need to modify the page variable on each separate link, so you have to include the whole thing each time. Perhaps others have a better solution.
Using Symfony 5 you can use this:
{{ app.request.uri }}
If you are using Silex 2 you can not access the Request object anymore.
You can access the current request attributes this way.
app.request_stack.currentrequest.attributes.get('_route')
And to generate the full current URL :
path(app.request_stack.currentrequest.attributes.get('_route'), app.request_stack.currentrequest.attributes.get('_route_params'))

Can I set a general form error with callback validator?

Can I set a general form error with callback validator? I do not want to set it to a specific field, but rather to a form in general errors.
Yes, you have to create what we call a class constraint, which will be applied to the data_class itself, not to a specific field: http://symfony.com/doc/2.0/book/validation.html#classes
Here is a snippet of code to set an error to your global form and not on a field.
public function isValid(ExecutionContext $context) {
if (what ever condition) {
// Do not set the property path as shown in the documentation
$context->addViolation('This name sounds totally fake!', array(), null);
}
}
When you do not define a property path on the context, the violation is added on top level of the form. all you have to do is remove these two lines given in the official documentation :
$propertyPath = $context->getPropertyPath() . '.firstName';
$context->setPropertyPath($propertyPath);
And afterwards simple display the global errors of your form.
{{ form_errors(form) }}

Resources