TYPO3 ExtBase - Required argument X is not set - php

I try to modify the extension importr to insert a custom action to the controller "Importr" at importr\Classes\Controller\ImportrController.php.
I called the action "customAction" and reference to it from a button which I render with fluid in importr\Resources\Private\Templates\Importr\Index.html by using <f:link.action>
<div id="myButton">
<f:link.action
extensionName="Importr"
pluginName="Importr"
controller="Importr"
action="custom"
arguments="{taskid:5}"
>
Click here
</f:link.action>
</div>
controller action:
/**
* #param int $taskid
* #return void
*/
public function customAction($taskid)
{
...
}
However, every attempt to pass a parameter to the action fails.
At my first attempt I even get an error page without even clicking on the button as you can see in the screenshot below.
Attempt #1
/**
* #param int $taskid
* #return void
*/
public function customAction($taskid)
{
print_r($taskid);
die;
}
Uncaught TYPO3 Exception
1298012500: Required argument "taskid" is not set for HDNET\Importr\Controller\ImportrController->custom.
TYPO3\CMS\Extbase\Mvc\Controller\Exception\RequiredArgumentMissingException
thrown in file
/var/www/typo3/typo3_src-6.2.25/typo3/sysext/extbase/Classes/Mvc/Controller/AbstractController.php
in line 425.'
Attempt #2
/**
* #return void
*/
public function customAction()
{
$taskid = "default";
if ($this->request->hasArgument('taskid')) {
$taskid = $this->request->getArgument('taskid');
}
echo "TASKID = '$taskid'";
die;
...
OUTPUT: TASKID = 'default'
Attempt #3:
/**
* #return void
*/
public function customAction()
{
$args = $this->request->getArguments();
$taskid = $args['taskid'];
echo "TASKID = '$taskid'";
die;
OUTPUT: TASKID = ''
I don't know what else I can try. Is it possible that I made a mistake in the Fluid Code? Do I use a wrong pluginName or extensionName or is it even a typo3 bug? Where is the pluginName stored so I can check it?
More Infos
I allowed my custom action by adding it to the other actions inside ext_tables.php
<?php
if (!defined('TYPO3_MODE')) {
die('Access denied.');
}
/** #var string $_EXTKEY */
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
'HDNET.' . $_EXTKEY,
'file',
'tx_importr_mod',
'',
[
'Importr' => 'custom,index,import,preview,create',
],
[
'access' => 'user,group',
'icon' => 'EXT:' . $_EXTKEY . '/ext_icon.gif',
'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_mod.xlf'
]);

There were two problems:
1. ext_tables.php
The order of the actions was not correct.
The first action is always the default action, so it took my custom action as default action and therefor no page was loaded after clicking on the Importr Modul in the menu at the left. It worked after I corrected it.
'Importr' => 'index,import,preview,create,custom',
2. Fluid
The pluginName was incorrect, the correct pluginName is file_importrtximportrmod, which we can see in ext_tables.php
It is not even needed, it also works if you omit pluginName and extensionName.
Make sure to clear the cache in the install tool afterwards.

Related

How to get custom directive arguments in lighthouse graphql laravel

My question is regarding the custom directives
https://lighthouse-php.com/4.11/the-basics/directives.html#definition
My schema is:
type Query {
sayFriendly: String #append(text: ", please.")
}
in lighthouse.php the config, I already have
'namespaces' => [
'models' => ['App', 'App\\Models'],
'queries' => 'App\\GraphQL\\Queries',
'mutations' => 'App\\GraphQL\\Mutations',
'subscriptions' => 'App\\GraphQL\\Subscriptions',
'interfaces' => 'App\\GraphQL\\Interfaces',
'unions' => 'App\\GraphQL\\Unions',
'scalars' => 'App\\GraphQL\\Scalars',
'directives' => ['App\\GraphQL\\Directives'],
],
directive enabled.
I defined the directive at \App\GraphQL\Directives\appendDirective as
<?php
namespace App\GraphQL\Directives;
use Closure;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\Directive;
use Nuwave\Lighthouse\Support\Contracts\FieldMiddleware;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
class appendDirective implements Directive, FieldMiddleware
{
/**
* Name of the directive as used in the schema.
*
* #return string
*/
public function name(): string
{
return 'append';
}
/**
* Wrap around the final field resolver.
*
* #param \Nuwave\Lighthouse\Schema\Values\FieldValue $fieldValue
* #param \Closure $next
* #return \Nuwave\Lighthouse\Schema\Values\FieldValue
*/
public function handleField(FieldValue $fieldValue, Closure $next): FieldValue
{
// Retrieve the existing resolver function
/** #var Closure $previousResolver */
$previousResolver = $fieldValue->getResolver();
// Wrap around the resolver
$wrappedResolver = function ($root, array $args, GraphQLContext $context, ResolveInfo $info) use ($previousResolver): string {
// Call the resolver, passing along the resolver arguments
/** #var string $result */
$result = $previousResolver($root, $args, $context, $info);
return ($result);
};
// Place the wrapped resolver back upon the FieldValue
// It is not resolved right now - we just prepare it
$fieldValue->setResolver($wrappedResolver);
// Keep the middleware chain going
return $next($fieldValue);
}
}
how can I get the value of key "text" from my directive and append to $result [ #append(text: ", please.") ].
The $args is an empty array (and It should be because I did make parameterized query [sayFriendly] )
If you extend your directive from Nuwave\Lighthouse\Schema\Directives\BaseDirective you can have access to $this->directiveArgValue('text'); to retrieve the text argument to your custom directive.
The $args are empty because that are the arguments supplied by the client in the query, in the sayFriendly query example there are no args possible so that will always be empty.
As a tip: you can find this out by looking at an already implemented directives inside Lighthouse, the documentation is a bit thin on the custom directives but you can learn a lot by looking at the directives provided by Lighthouse.

How to add image on push notification using brozot / Laravel-FCM

How to add image on push notification using brozot / Laravel-FCM ?
I'm sending notifications correctly, but I would like to know how can I send an image with the notification?
I tried this code but not working
$pushData = ['body' => $message, 'title'=>$title,'image'=>'image-url'];
$pushJsonData = json_encode($pushData);
if(count($tokens)>0)
{
$optionBuilder = new OptionsBuilder();
$optionBuilder->setTimeToLive(60*20);
$notificationBuilder = new PayloadNotificationBuilder($title);
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
$dataBuilder = new PayloadDataBuilder();
$dataBuilder->addData(['a_data' => $pushJsonData]);
$option = $optionBuilder->build();
$notification = $notificationBuilder->build();
$data = $dataBuilder->build();
$downstreamResponse = FCM::sendTo($tokens, $option, $notification, $data);
$downstreamResponse->numberSuccess();
$downstreamResponse->numberFailure();
$downstreamResponse->numberModification();
//return Array - you must remove all this tokens in your database
$downstreamResponse->tokensToDelete();
//return Array (key : oldToken, value : new token - you must change the token in your database )
$downstreamResponse->tokensToModify();
//return Array - you should try to resend the message to the tokens in the array
$downstreamResponse->tokensToRetry();
// return Array (key:token, value:errror) - in production you should remove from your database the tokens present in this array
$downstreamResponse->tokensWithError();
You need to create a custom script that herance the vendor script and add some properties on it.
Create a new path in app: app/Notifications/Message
Add a new script called CustomPayloadNotification.php
Here you need to:
Extends PayloadNotification (vendor);
Add a new variable $image;
Override __construct method, changing the parameter type to CustomPayloadNotificationBuilder. Set all the variables like is in PayloadNotification and also set the new variable $image.
Override toArray method, setting all the properties like is in PayloadNotification and also set a new property image with $image value.
Something like this:
<?php
namespace App\Notifications\Messages;
use LaravelFCM\Message\PayloadNotification;
use App\Notifications\Messages\CustomPayloadNotificationBuilder;
class CustomPayloadNotification extends PayloadNotification // Extends vendor script
{
protected $image; // New variable
/**
* CustomPayloadNotificationBuilder constructor.
*
* #param CustomPayloadNotificationBuilder $builder
*/
public function __construct(CustomPayloadNotificationBuilder $builder) // Change the type of parameter
{
$this->title = $builder->getTitle();
$this->body = $builder->getBody();
$this->icon = $builder->getIcon();
$this->sound = $builder->getSound();
$this->badge = $builder->getBadge();
$this->tag = $builder->getTag();
$this->color = $builder->getColor();
$this->clickAction = $builder->getClickAction();
$this->bodyLocationKey = $builder->getBodyLocationKey();
$this->bodyLocationArgs = $builder->getBodyLocationArgs();
$this->titleLocationKey = $builder->getTitleLocationKey();
$this->titleLocationArgs = $builder->getTitleLocationArgs();
$this->image = $builder->getImage(); // Set image
}
/**
* convert CustomPayloadNotification to array
*
* #return array
*/
function toArray()
{
$notification = [
'title' => $this->title,
'body' => $this->body,
'icon' => $this->icon,
'sound' => $this->sound,
'badge' => $this->badge,
'tag' => $this->tag,
'color' => $this->color,
'click_action' => $this->clickAction,
'body_loc_key' => $this->bodyLocationKey,
'body_loc_args' => $this->bodyLocationArgs,
'title_loc_key' => $this->titleLocationKey,
'title_loc_args' => $this->titleLocationArgs,
'image' => $this->image, // Set property image with $image value
];
// remove null values
$notification = array_filter($notification, function($value) {
return $value !== null;
});
return $notification;
}
}
Add a new script called CustomPayloadNotificationBuilder.php
Here you need to:
Extends PayloadNotificationBuild (vendor);
Add a new variable protected $image;
Create the set/get methods to $image;
Override build method, returning a new CustomPayloadNotification instead PayloadNotification.
Something like this:
<?php
namespace App\Notifications\Messages;
use LaravelFCM\Message\PayloadNotificationBuilder;
use App\Notifications\Messages\CustomPayloadNotification;
class CustomPayloadNotificationBuilder extends PayloadNotificationBuilder // Extends vendor script
{
protected $image; // New variable
/**
* Set image
*
* #param string $image
*
* #return CustomPayloadNotificationBuilder
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image.
*
* #return null|string
*/
public function getImage()
{
return $this->image;
}
/**
* Build an CustomPayloadNotification
*
* #return CustomPayloadNotification
*/
public function build()
{
return new CustomPayloadNotification($this); // Change the object returned
}
}
Reference CustomPayloadNotificationBuilder instead PayloadNotificationBuilder scripts in your code.
Use the method setImage
Your code should be something like this:
use App\Notifications\Messages\CustomPayloadNotificationBuilder; // Add the reference on the top of your code
// No changes before here [...]
$notificationBuilder = new CustomPayloadNotificationBuilder($title); // Replace here
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
$notificationBuilder->setImage("Image URL here"); // Add an image
// No changes after here [...]
you need to do some change in vendor for this
Step-1 : Go to the following url I am sharing here-
Laravel-FCM-master\Laravel-FCM-master\src\Message\PayloadNotification.php
Step-2 : here you have to add a instance variable as
protected $image;
Step - 3 find the public function __construct(PayloadNotificationBuilder $builder)
step -4 add $this->image = $builder->getImage(); in this function.
step -5 find the public function toArray()
step -6 add here 'image' => $this->image,
step -7 save and exit.
step -8 then follow this url in vendor again Laravel-FCM-master\Laravel-FCM-master\src\Message\PayloadNotificationBuilder.php:
step -9 add in above page
/**
* Indicates the image that can be displayed in the notification
* Supports an url or internal image.
*
* #param string $image
*
* #return PayloadNotificationBuilder current instance of the builder
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
step - 10 then add
/**
* Get image.
*
* #return null|string
*/
public function getImage()
{
return $this->image;
}
step - 11 that's it, now you can easily able to add a new field in your controller where your code was written asked in question.
simply modify as
$notificationBuilder = new PayloadNotificationBuilder($title);
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setImage("https://yourdoamin.com/yourdesiredimage.jpeg")->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
and send you will get exact what you are looking for.

Symfony3 form checkbox save error

I tried to look up on Google but didn't find anyone with such a problem. I think I did everything like the documentation guides but I guess I'm missing something
So I have a form with checkbox like this:
$builder->add(
'productTypes',
EntityType::class,
array(
'label' => 'Available for products',
'class' => 'ShopBundle:ProductType',
'choice_label' => 'name',
'multiple' => true,
'expanded' => true,
'by_reference' => false,
)
);
When I'm editing everything goes smooth, I can edit existing entry and check or uncheck this checkbox, it saves properly, but when I try to add new Object I get error:
PHP Fatal error: Call to a member function add() on null in
C:\xampp\htdocs\uniacar-sf\src\ShopBundle\Entity\ProductAttribute.php
on line 188
This is my controller action:
public function editAction(Request $request, $id = null)
{
$this->setMenuTab('cars', 'admin');
$productTypes = new ArrayCollection();
if (!empty($id)) {
$attribute = $this->getRepo(ProductAttribute::class)->find($id);
$this->setTitle('admin.cars.attributes.edit');
foreach ($attribute->getProductTypes() as $value) {
$productTypes->add($value);
}
} else {
$attribute = new ProductAttribute();
$this->setTitle('admin.cars.attributes.new');
}
$form = $this->createForm(ProductAttributeForm::class, $attribute);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$attribute = $form->getData();
foreach ($productTypes as $productType) {
if (false === $attribute->getProductTypes()->contains($productType)) {
$productType->getAttributes()->removeElement($attribute);
$this->db()->persist($productType);
}
}
$this->db()->persist($attribute);
$this->db()->flush();
return $this->redirectToRoute('carAdmin', array('tab' => 'attributes'));
}
$this->setVariables(
array(
'form' => $form->createView(),
'attribute' => $attribute,
)
);
return $this->response();
}
$this->db() is my shortcut for $this->getDoctrine()->getManager()
And this is definition part of ProductAttribute that relates to ProductType:
/**
* Constructor
*/
public function __construct() {
$this->productTypes = new ArrayCollection();
}
/**
* Many Attributes have Many ProductTypes
* #ORM\ManyToMany(targetEntity="ProductType", mappedBy="attributes", cascade={"persist"})
*/
private $productTypes;
/**
* #param ProductType $productType
*/
public function addProductType(ProductType $productType)
{
$this->productTypes->add($productType);
$productType->addProductAttribute($this);
}
/**
* #param ProductType $productType
*/
public function removeProductType(ProductType $productType)
{
$this->productTypes->removeElement($productType);
}
Also there is part of ProductType Entity that relates to ProductAttribute:
/**
* Constructor
*/
public function __construct() {
$this->attributes = new ArrayCollection();
}
/**
* Many ProductTypes have Many Attributes
* #ORM\ManyToMany(targetEntity="ProductAttribute", inversedBy="productTypes")
* #ORM\JoinTable(name="product_type_to_attribute")
*/
private $attributes;
/**
* #param ProductAttribute $attribute
*/
public function addProductAttribute(ProductAttribute $attribute)
{
if (!$this->attributes->contains($attribute)) {
$this->attributes->add($attribute);
}
}
public function removeProductAttribute(ProductAttribute $attribute)
{
$this->attributes->removeElement($attribute);
}
I tried to follow Symfony Embed Form Tutorial (How to Embed a Collection of Forms)
I know that in this case there is no embeded collection (I have another field in this Entity, that is embeded collection of forms and it works just fine) but from what I understand relations are the same in this case, it's many to many so I have to tell the Symfony how to treat relations, add and remove objects.
I dumped data that comes in POST but it's the same as for edition - productType is there. Any ideas why do I get this error?
It fires in ProductAttribute Entity in the line $this->productTypes->add($productType);
EDIT:
I updated the controller code, I messed up the logic about unlinking ProductType from ProductAttribute. But it doesn't have any impact on the problem, still the same 500 error when I try to save new object.
EDIT2:
I can't get stack trace from Symfony because I get ordinary browser 500 error (probably because it's Fatal Error, I found it in apache logs). The line in controller which creates error is $form->handleRequest($request);.
This is not a Collection of Forms, but you are using collection specific method, this is not a good practice, however, you don't need this below code when you create a new object.
foreach ($productTypes as $value) {
if (false === $attribute->getProductTypes()->contains($value)) {
$attribute->getProductTypes()->removeElement($value);
}
}
So, I haven't found solution to the problem but I solved it somehow by fixing file structure of my project (moved bundle's Resources from general Resources folder to Bundle's Resources folder). I have no idea why this fixed the issue and what is even the connection between working but not proper folder structure and submitting forms but now it works, so I will mark the question as answered.

Laravel 5: Odd "Undefined Variable" error when returning a defined array to View

As the title states, I'm getting an odd error in Laravel 5. I'm new to Laravel, and this week I dived into Jobs/Queues. I've gotten an "Undefined Variable: $errors" error in the past, and that one I was able to understand and fix. But now, I can't seem to get past this one. To my knowledge, everything looks fine. The following breakdown will (hopefully) give you an idea of what I'm doing/where the error happens:
class PostFormFields extends Job implements SelfHandling
{
use InteractsWithQueue, SerializesModels;
/**
* The id (if any) of the Post row
*/
protected $id;
/**
* List of fields and default value for each field
*/
protected $fieldList = [
'title' => '',
'subtitle' => '',
'page_image' => '',
'content' => '',
'meta_description' => '',
'is_draft' => '8',
'publish_date' => '',
'publish_time' => '',
'layout' => 'blog.layouts.post',
'tags' => [],
];
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($id = null)
{
$this->id = $id;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$fields = $this->fieldList;
if($this->id)
{
$fields = $this->fieldsFromModel($this->id, $fields);
} else {
$when = Carbon::now()->addHour();
$fields['publish_date'] = $when->format('M-j-Y');
$fields['publish_time'] = $when->format('g:i A');
}
/**
* Populate with old values, if they exist
* #var [type]
*/
foreach ($fields as $fieldName => $fieldValue)
{
$fields[$fieldName] = old($fieldName, $fieldValue);
}
$fields = array_merge($fields, ['allTags' => Tag::lists('tag')->all()]);
return $fields;
}
Above is the code inside the handler function of my Job class, the file it sits in is called PostFormFields.php. It's job, essentially, is just to return an array filled with all the values pertaining to a post, based on the Post Model and what's in the database that pertains to that specific Post ('title','content',etc) if a user's entered them in the past
public function create()
{
$data = $this->dispatch(new PostFormFields());
$data['title'] = 'testing';
var_dump($data);
return view('admin.post.create', $data);
}
Above is the code inside my PostController class, in the create() method. As you can tell, I'm using a resource controller for my Post Controller. It dispatches the PostFormFields Job and stores all the returned data in an array $data. However, since the create() method will be used to create a new post, only the keys should be returned, with values set to their default value ''.
This works. As you can see, i run a 'var_dump()' on the variable $data to see what, if anything, is returned. I then pass the $data array to the create View. This is where the error comes up.
Laravel "Undefined Varieble" Error
Above is a picture of the error I get when I try to access the /create route. It's clear that the $data does have the $title variable defined, as well as all the other keys in the array. Why am I getting an "Undefined Variable" array when I clearly have it defined by the time it's sent to the create View?
The line of code is says the error is in is the following:
<input type="text" class="radius" name="title" id="title" value="{{ $title }}">
You have to pass that array to view via compact function of laravel. So that you can use it in view as you want.
Please check about compact here - https://laracasts.com/discuss/channels/general-discussion/phps-compact-pros-and-cons?page=1
public function create()
{
$data = $this->dispatch(new PostFormFields());
$data['title'] = 'testing';
var_dump($data);
return view('admin.post.create', compact('data'));
}

CakePHP - TinyMceHelper helper error: Method TinyMceHelper::__name does not exist

So I'm wanting to implement the TinyMce helper. I've followed instructions from the cakephp bakery but am still getting a error.
This is the helpers array in my project controller:
var $helpers = array('Form', 'Time', 'Crumb', 'Text', 'Tinymce');
This is the tinymce helper I downloaded:
<?php
class TinyMceHelper extends AppHelper {
// Take advantage of other helpers
var $helpers = array('Javascript', 'Form');
// Check if the tiny_mce.js file has been added or not
var $_script = false;
/**
* Adds the tiny_mce.js file and constructs the options
*
* #param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
* #param array $tinyoptions Array of TinyMCE attributes for this textarea
* #return string JavaScript code to initialise the TinyMCE area
*/
function _build($fieldName, $tinyoptions = array()) {
if (!$this->_script) {
// We don't want to add this every time, it's only needed once
$this->_script = true;
$this->Javascript->link('/js/tiny_mce/tiny_mce.js', false);
}
// Ties the options to the field
$tinyoptions['mode'] = 'exact';
$tinyoptions['elements'] = $this->__name($fieldName);
return $this->Javascript->codeBlock('tinyMCE.init(' . $this->Javascript->object($tinyoptions) . ');');
}
/**
* Creates a TinyMCE textarea.
*
* #param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
* #param array $options Array of HTML attributes.
* #param array $tinyoptions Array of TinyMCE attributes for this textarea
* #return string An HTML textarea element with TinyMCE
*/
function textarea($fieldName, $options = array(), $tinyoptions = array()) {
return $this->Form->textarea($fieldName, $options) . $this->_build($fieldName, $tinyoptions);
}
/**
* Creates a TinyMCE textarea.
*
* #param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
* #param array $options Array of HTML attributes.
* #param array $tinyoptions Array of TinyMCE attributes for this textarea
* #return string An HTML textarea element with TinyMCE
*/
function input($fieldName, $options = array(), $tinyoptions = array()) {
$options['type'] = 'textarea';
return $this->Form->input($fieldName, $options) . $this->_build($fieldName, $tinyoptions);
}
}
?>
And this my add view that I want to use the helper on:
<?php
echo $form->create('Project');
echo $form->input('title', array('label' => 'Title'));
echo $form->input('website', array('label' => 'Website'));
echo $tinymce->input('description');
echo $form->input('language_id', array('label' => 'Language'));
echo $form->input('tags', array('type' => 'text'));
echo $form->end('Post project');
?>
Everything looks alright but I'm getting this error:
Warning (512): Method TinyMceHelper::__name does not exist [CORE/cake/libs/view/helper.php, line 154]
Think I'm missing a step here?
You must be using CakePHP 1.3. The form helper in 1.2 used __name. In 1.3 it was for some reason changed to _name.
If you update the helper from:
$tinyoptions['elements'] = $this->__name($fieldName);
to
$tinyoptions['elements'] = $this->_name($fieldName);
You should be good to go.
I think you mistyped the helper name in controller. It should be :
var $helpers = array('Form', 'Time', 'Crumb', 'Text', 'TinyMce');
and in your view :
echo $tinyMce->input('description');
Hope that help.
You should do as cdburgess suggested, and if it does not work, make sure your javascripts gets loaded, and edit tinmce.php the TinyMce helper's code to properly load javascripts, line looks like this:
$this->Javascript->link('/webroot/js/tiny_mce.js', false);

Categories