Yii2 Object of class Closure could not be converted to string - php

I've got error
Object of class Closure could not be converted to string
on this code
'class' => \dosamigos\grid\EditableColumn::className(),
'attribute' => 'remidi3',
'url' => function($data){return ['update?id=remidi3&dataid'.$data->id];},
'type' => 'text',
'editableOptions' => [
'mode' => 'inline',
]
even I've try to change
'url' => function($data){return ['update?id=remidi3&dataid'.$data->id];}
into
'url' => function($data){return 'update?id=remidi3&dataid'.$data->id;},
I need to display id in the URL of editable grid, somebody can help me?

According to source code and PHPDoc, you can't specify closure here.
PHPDoc says:
/**
* #var string the url to post
*/
public $url;
Usage in source code:
if ($this->url === null) {
throw new InvalidConfigException("'Url' property must be specified.");
}
...
$url = (array) $this->url;
$this->options['data-url'] = Url::to($url);
As you can see, it's converted to array and then processed by Url::to(), so the valid types are string and array.
I don't think you need to specify id in url, it should be taken automatically depending on row you working with.

Related

How to use dynamically created enum type in Lighthouse?

I have custom dynamically created Enum type MyCustomEnum witch I need to use in my ServiceProvider.
For example I call Type string now Type::string():
<?php
namespace App\Providers;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\ServiceProvider;
use Nuwave\Lighthouse\Schema\TypeRegistry;
use GraphQL\Type\Definition\EnumType;
class GraphQLServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #param TypeRegistry $typeRegistry
*
* #return void
*/
public function boot(TypeRegistry $typeRegistry): void
{
$typeRegistry->register(
new ObjectType([
'name' => 'MyOtherCustomType',
'fields' => function () use ($typeRegistry): array{
return [
'my_field' => Type::string()
];
},
])
);
}
}
How I can call this dynamically created type MyCustomEnum on line 'my_field' => ... ?
I have a php enum class named CountryEnum which has a static method called graphEnumType(). This method returns an array with this shape. I register it in AppServiceProvider like this so it can be used with graphql:
$typeRegistry->register(CountryEnum::graphEnumType());
Inside the php i treat it like a php enum and call it like this:
CountryEnum::AT->value;
Enums are not a Type, they do not get implemented like class or struct in any way they are true arrays, when your pass an enum, you don't actually pass the enum you pass one of the values the enum has registered to it, now this can be hidden if you don't supply values. to not be hidden when you define the enum you must supply the value for each option and then the values, therefore, have a type.
E.G
$episodeEnum = new EnumType([
'name' => 'Episode',
'description' => 'One of the films in the Star Wars Trilogy',
'values' => [
'NEWHOPE' => [
'value' => 4,
'description' => 'Released in 1977.'
],
'EMPIRE' => [
'value' => 5,
'description' => 'Released in 1980.'
],
'JEDI' => [
'value' => 6,
'description' => 'Released in 1983.'
],
]
]);
Now the enum Episode always has a type of int because the 3 options of the enum all have values that are ints, so the type of that enum value is an int. Therefore anything that uses that Episode Enum, they have to supply what value of the enum they want to save(E.G Episode.NEWHOPE) and that is enum value's actual value is actually what is saved (so the last E.G would actually save 4 and is there for an int), and that defines the type of what is saved/transferred, it is the type of the value.

Why are characters inserted in my PHP link?

I created a module, but the link is not correct.
My site now shows :
/store/2?0=/cgv
The correct link should be :
/store/2/cgv
Why doesn't it work ? where is the error ?
What should I change in the code below, to get the link ?
<?php
namespace Drupal\commerce_agree_cgv\Plugin\Commerce\CheckoutPane;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Form\FormStateInterface;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
/**
* Provides the completion message pane.
*
* #CommerceCheckoutPane(
* id = "agree_cgv",
* label = #Translation("Agree CGV"),
* default_step = "review",
* )
*/
class AgreeCGV extends CheckoutPaneBase implements CheckoutPaneInterface {
/**
* {#inheritdoc}
*/
public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
$store_id = $this->order->getStoreId();
$pane_form['#attached']['library'][] = 'core/drupal.dialog.ajax';
$attributes = [
'attributes' => [
'class' => 'use-ajax',
'data-dialog-type' => 'modal',
'data-dialog-options' => Json::encode([
'width' => 800,
]),
],
];
$link = Link::createFromRoute(
$this->t('the general terms and conditions of business'),
'entity.commerce_store.canonical',
['commerce_store' => $store_id, '/cgv'],
$attributes
)->toString();
$pane_form['cgv'] = [
'#type' => 'checkbox',
'#default_value' => FALSE,
'#title' => $this->t('I have read and accept #cgv.', ['#cgv' => $link]),
'#required' => TRUE,
'#weight' => $this->getWeight(),
];
return $pane_form;
}
}
Because $link is not built correctly :
$link = Link::createFromRoute(
$this->t('the general terms and conditions of business'),
'entity.commerce_store.canonical',
['commerce_store' => $store_id, '/cgv'], # -> this is wrong
$attributes
)->toString();
$route_parameters: (optional) An associative array of parameter names
and values.
You did not specify any name for the 2nd route parameters, so the corresponding array key fallback to the first available numeric indice, that is 0, meaning [ '/cgv' ] becomes [ 0 => '/cgv' ] and you don't get the link you expected.
I think (if I understood your issue correctly) what you need is to define in the first place that specific route handling cgv's for a given commerce_store, that is with the /cgv appended :
$route_collection = new RouteCollection();
$route = (new Route('/commerce_store/{commerce_store}/cgv'))
->addDefaults([
'_controller' => $_controller,
'_title_callback' => $_title_callback,
])
->setRequirement('commerce_store', '\d+')
->setRequirement('_entity_access', 'commerce_store.view');
$route_collection->add('entity.commerce_store.canonical.cgv', $route);
... so that you can build links based on that specific route :
$link = Link::createFromRoute(
$this->t('the general terms and conditions of business'),
'entity.commerce_store.canonical.cgv',
['commerce_store' => $store_id],
$attributes
)->toString();

Zend Framework 3 BaseInputFilter::setData() throws InvalidArgumentException

I have a dynamic setp-by-step form in ZF3. I use fieldsets and a default form to display the current form. The default form has only a csrf token and a submit button added. The form instaniation looks like this:
$form = new ReportForm();
foreach($requestedFieldsetNames as $fieldSetName) {
$form->add([
'type' => $this->registeredFieldSets[$fieldSetName],
'options' => [
'use_as_base_fieldset' => true,
]
]);
}
return $form;
The form displays correctly, but when I submit it, the following exception is thrown when I call isValid():
Zend\InputFilter\BaseInputFilter::setData expects an array or Traversable argument; received string
The data I pass to the form contains the following:
object(Zend\Stdlib\Parameters)[89]
private 'storage' (ArrayObject) =>
array (size=2)
'entityType' => string 'drivers' (length=7)
'csrf' => string '0c435d5f0ca21132ce85e26df65d2e5e-daf2a8843f01e607f23ce48a2c209262' (length=65)
'submit' => string 'Next' (length=7)
The entityType is part of a fieldset. I don't understand why this exception gets thrown, when I pass a Traversable object to the form. Has this occured to anybody else? How can I fix it? Thanks in advance!
If entityType is a fieldset, you can not set a data to it directly. You have to provide data to element's in it. So if we say your fieldset as;
final class entityType extends Fieldset {
function init(){
$this-add([
'type' => 'Text',
'name' => 'my-field'
]);
}
}
Data will be like;
'storage' => [
'entityType' => [
'my-field' => 'drivers
]
]
The problem was really-really trivial, shame on me. I forgot to call $form->prepare in my view script. After calling $form->prepare(), the post data was properly set and the BaseInputFilter accepted the data.

PHP ElasticSearch how to set mapping before indexing records?

I'm using laravel and elasticsearch-php to index and store data to elastic, my problem is that elastisearch uses from dynamic mapping but I need to set my custom mapping. How can I use from my mapping?
Bellow is my code:
$client = \Elasticsearch\ClientBuilder::create()->build();
$mappingData = array(
'index' => 'promote_kmp',
'body' => array(
'mappings' => $resource->getMappingProperties()
)
);
$client->indices()->create($mappingData);
$params = [
'type' => 'resources',
'id' => uniqid(),
'body' => [
'id' => $resource->id,
'name' => $resource->name,
'display_name_en' => $resource->display_name_en,
'display_name_pr' => $resource->display_name_pr,
'display_name_pa' => $resource->display_name_pa,
'table_name' => $resource->table_name,
'model_name' => $resource->model_name,
'in_sidemenu' => $resource->in_sidemenu,
'icon_class' => $resource->icon_class,
'created_at' => $resource->created_at,
'created_by' => $user,
]
];
//$response = $client->indices()->create($resource->getMappingProperties());
$client->index($params);
$resource->getMappingProperties() get the mapping array I have set in model.
but when I want to index a record it says IndexAlreadyExistsException[[promote_kmp] already exists]. This question arise when I want to search for date field searching is not properly working and I guess that mapping is not true.
As I was saying in comments.
The code is executing the creation of index every time you want to query.
But the index must be created only once.
So it should work like the migration for the DB's.
The only idea I can give you is to make a command to generate the index.
So that you could just
$ artisan elasticsearch:generate <index>
About the code, what I've done for our case, made the index with a way to inject the types, plus a way to create them into elasticsearch:
interface Index {
/**
* #param Type[] $types Index types (resources)
*/
function setTypes(array $types);
/**
* Generate the index and the types into the elasticsearch
*/
function create();
}
Then the types should generate the mappings and the type name (as /<index>/<type>, like:
interface Type {
/**
* #return string The type name
*/
function getName();
/**
* #return array The type mapping
*/
function getMapping();
}
So (somewhere), you would create the class (this could be better):
$myIndex = new MyIndex();
$myIndex->setTypes([
new MyFirstType(),
new MySecondType(),
//...
]);
$myIndex->create();
I hope this helps.

Changing display logic for a field in sugarcrm

I have the following situation: Contacts without a first or last name, in fact, they only have a email address.
I can work with these contacts fine, but when I use the listview anywhere (for instance to show all contacts from a company) there now is no way to click through to the contact (normally you would click on the name).
I'm looking for a way to solve this, for instance by showing a clickable text like 'name not known', but can't figure out how to do this. I've been looking at the manual and in the files in the modules directory and the sugarfields dir, but can't quite figure it out.
The closest I got was in /sugarcrm/modules/Contacts/metadata/listviewdefs.php
where this piece of code resides:
$listViewDefs['Contacts'] = array(
'NAME' => array(
'width' => '20%',
'label' => 'LBL_LIST_NAME',
'link' => true,
'contextMenu' => array('objectType' => 'sugarPerson',
'metaData' => array('contact_id' => '{$ID}',
'module' => 'Contacts',
'return_action' => 'ListView',
'contact_name' => '{$FULL_NAME}',
'parent_id' => '{$ACCOUNT_ID}',
'parent_name' => '{$ACCOUNT_NAME}',
'return_module' => 'Contacts',
'return_action' => 'ListView',
'parent_type' => 'Account',
'notes_parent_type' => 'Account')
),
'orderBy' => 'name',
'default' => true,
'related_fields' => array('first_name', 'last_name', 'salutation', 'account_name', 'account_id'),
),
Somewhere there has to be a function that joins the first and lastname together...
Edit: I found a solution:
The actual concatenation function is in /sugarcrm/include/SugarObjects/templates/person/person.php and is called _create_proper_name_field()
I can modify the output for my specific case by adding something like this to the end of the function:
if (empty(trim($full_name))){
$full_name = 'Name unknown';
}
However, I would rather have a upgrade safe solution, so that will be the next challenge.
Don't edit the core because the next upgrade will break your SugarCRM instance. Use logic hooks to be upgrade safe:
create a file 'logic_hooks.php' in /custom/modules/Contacts/
In that file, add the followin code:
<?php
$hook_array['before_save'][] = Array(1,'logic_fill_name','custom/modules/Contacts/logic_hooks/logics.php','ContactLogics','logic_fill_name');
After you have done this. create the file 'logics.php' in /custom/modules/Contacts/logic_hooks.
In the logics.php file, add something like:
<?php
require_once 'include/SugarQuery/SugarQuery.php';
/**
* Class ContactLogics
*/
class ContactLogics {
/**
* #param $bean
* #param $event
* #param $arguments
*/
public function logic_fill_name($bean, $event, $arguments) {
if (empty(trim($bean->first_name)) && empty(trim($bean->last_name))){
$bean->last_name = 'Name unknown';
}
}
}
Now some explanation. When you edited a recordview and pressed the save button, the logic hook 'before_save' will be triggered. This code will change the full name to 'Name unknown' when the full name is empty. When the 'before_save' is executed, the actual save will take place.

Categories