Restler not accepting boolean false - restler

In my Restler API class I have an object defined like so (with lots of other params)
class PatchTaskObj extends TaskObj {
/**
* #var bool|null Whether or not this Task should be pinned to the top of the list {#required false}
*/
public $pinned = null;
}
And then I attempt to use it in my PATCH method:
/**
* Updates an existing Task record.
*
* #param int $id The SQL ident of the task you wish to update. {#min 1} {#from path}
* #param PatchTaskObj $info The properties of the Task to update.
*
* #throws RestException 412 Thrown if at least one update isn't passed in.
*
* #status 204
*/
function patch($id, PatchTaskObj $info)
If I pass in true for the pinned property it works fine, but if I pass false then I get a 400 from Restler with the message:
Bad Request: Invalid value specified for info[pinned]

OK, discovered that Restler's Validator.php is failing to parse the #var property the way it's written. If you remove the |null part then it works as expected. I've submitted an issue to the github site.

Related

error when sending a notification 'Call to undefined method App\Models\Role::routeNotificationFor()'

I am building a web app whereby after an admin(with the role of a manager) approves a booking, the booking passes to another admin(with the role of an accountant) who then starts working on it.I want the manager to send a notification to only the accountant after approving the booking.i tried this code below and it sends to all admins which is not what I want to achieve
$users=User::where('is_admin','1')->get();
Notification::send($users,new Newbookingrecieved($bookingstatus));
then i tried getting the email from the role model
$users=Role::where('Role_name','The Accountant')->get();
Notification::send($users,new Newbookingrecieved($bookingstatus));
but it responded with an error
BadMethodCallException
Call to undefined method App\Models\Role::routeNotificationFor()
here is my notification
<?php
namespace App\Notifications;
use App\Models\Bookings;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class Newbookingrecieved extends Notification
{
use Queueable;
public $bookingstatus;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($bookingstatus)
{
$this->bookingstatus = $bookingstatus;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello there sir/madam')
->subject('New Booking by' .$this->bookingstatus->full_name)
->line('We have received a new Booking and approved it to you to request payment from the client' . $this->bookingstatus->email)
->action('Review This Booking', route('changestatus', $this->bookingstatus->id));
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
here are all the roles
how can i achieve this such that i send the notification to the only adminand the notification wont be sent to other admins.
As I don't know the structure of your User model, I will assume that there is a role_id field.
Here is a piece of my code from one of my old projects that I will modify to your liking (it works for me) :
$users = User::where('role_id', 3)->get(); //3 is the id of The Accountant role
Notification::send($users, new Newbookingrecieved($bookingstatus));

Symfony - softdeleteable delete the entity but let me query it after

I want to implement softdelete in my symfony application.
I'm using Symfony5 and ApiPlatform for the back.
I've run the following command to install the bundle
composer require stof/doctrine-extensions-bundle
Installation worked as composer.json now has :
"stof/doctrine-extensions-bundle": "^1.5",
So I've updated my stof_doctrine_extensions.yaml file as follow:
stof_doctrine_extensions:
default_locale: en_US
orm:
default:
softdeleteable: true
I added the #Gedmo annotation to the entity I want to apply softdeleteable on
Added the deletedAt field, generated the migration and reload the database.
Here is my Entity.php file:
/**
* #Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=false)
* #ORM\Entity(repositoryClass=EntityRepository::class)
*/
class Entity
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"entity:read", "entity:list", "user:read", "user:list"})
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"entity:write", "entity:read", "entity:list"})
*/
protected $firstName;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $deletedAt;
}
I've also written a simple test to see if the feature was working:
public function testRoleAdminCanSoftDeleteEntity(): void
{
$this->buildEntityManager();
$res = $this->buildDeleteRequest(
GenericRoutes::ROUTE.'/11',
GenericCredentials::ADMIN_CREDENTIALS
);
$entity = $this->em->getRepository(Entity::class)->findEntityByEntityField(json_decode(GenericCredentials::CREDENTIALS)->email);
$this->assertNull($entity);
$this->assertResponseIsSuccessful();
$this->assertResponseStatusCodeSame(204);
}
I receive a 204 but the specialist isn't empty.
I've also used the swagger to manually delete the entity/{id} I wanted to remove.
I also receive a 204 and then can query the same entity/{id} right after.
I've verified in the database and the deleted_at field is updated to the moment I ran the DELETE request.
Does anyone has any idea why I still can query this user which I just soft deleted ?
So, regarding to my comment.
You just need to configure filter in the doctrine config, smth like this:
doctrine:
dbal:
...
orm:
...
filters:
softdeleteable:
class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
enabled: true
But in my opinion, it would be much more easy to not using this extension, it is just one more dependency in your project, and just create yourself nullable deletedAt property to the entity and set it to DateTime('now') on delete, and then you can get not deleted entries from the repo just adding one more criteria to findBy - 'deletedAt' => null

vuex actions and jsdoc: how to mark injected function parameter

Typical vuex action is:
const actions = {
/**
* #param {ActionContext} context passed by vuex
* #param {Object} payload
* #return {void}
*/
myAction(vuexContext, payload) {...}
}
Where vuexContext would be injected for me, and in app I would use this function just as myAction(payload). But for that case my WebStorm IDE complains about invalid number of arguments.
Maybe there is some workaround for it?
You can try marking context parameter optional:
/**
* #param {ActionContext} [vuexContext]
* #param {Object} payload
* #return {void}
*/
myAction(vuexContext, payload) {}
Please also vote for the related feature request: WEB-29740

Tx_Extbase_Domain_Repository_FrontendUserRepository->findAll() not working in typo3 4.5.30?

I am trying to run a simple query off of the Tx_Extbase_Domain_Repository_FrontendUserRepository. I cannot get anything to work except findByUid(), not even findAll().
In my controller I have this code which seems to work:
/**
* #var Tx_Extbase_Domain_Repository_FrontendUserRepository
*/
protected $userRepository;
/**
* Inject the user repository
* #param Tx_Extbase_Domain_Repository_FrontendUserRepository $userRepository
* #return void */
public function injectFrontendUserRepository(Tx_Extbase_Domain_Repository_FrontendUserRepository $userRepository) {
$this->userRepository = $userRepository;
}
/**
* action create
*
* #param Tx_BpsCoupons_Domain_Model_Coupon $newCoupon
* #return void
*/
public function createAction(Tx_BpsCoupons_Domain_Model_Coupon $newCoupon) {
...... some code .....
$user = $this->userRepository->findByUid(($GLOBALS['TSFE']->fe_user->user[uid]));
$newCoupon->setCreator($user);
...... some code .....
}
but in another function I want to look up a user not by uid but by a fe_users column called vipnumber (an int column) so I tried
/**
* check to see if there is already a user with this vip number in the database
* #param string $vip
* #return bool
*/
public function isVipValid($vip) {
echo "<br/>" . __FUNCTION__ . __LINE__ . "<br/>";
echo "<br/>".$vip."<br/>";
//$ret = $this->userRepository->findByUid(15); //this works!! but
$query = $this->userRepository->createQuery();
$query->matching($query->equals('vip',$vip) );
$ret = $query->execute(); //no luck
.................
and neither does this
$ret = $this->userRepository->findAll();
How can one work but not the others? In my setup I already put
config.tx_extbase.persistence.classes.Tx_Extbase_Domain_Model_FrontendUser.mapping.recordType >
which seems to be necessary for the fiondByUid to work, is i t preventing the other from working?
I am using typo3 v 4.5.30 with extbase 1.3
Thanks
If $this->userRepository->findByUid(15); works, there is no reason why $this->userRepository->findAll(); should not. However $this->userRepository->findAll(); returns not a single Object but a collection of all objects, so you have to iterate over them.
If you add a column to the fe_users, you have to add it to TCA and to your extbase model (you need a getter and a setter), too! After that you can call findByProperty($property) in your repository. In your case that would be
$user = $this->userRepository->findByVipnumber($vip);
This will return all UserObjects that have $vip set as their Vipnumber. If you just want to check if that $vip is already in use, you can call
$user = $this->userRepository->countByVipnumber($vip);
instead. Which obviously returns the number of Users that have this $vip;
You never use $query = $this->createQuery(); outside your Repository.
To add the property to the fronenduser Model you create your own model Classes/Domain/Model/FronendUser.php:
class Tx_MyExt_Domain_Model_FrontendUser extends Tx_Extbase_Domain_Model_FrontendUser {
/**
* #var string/integer
*/
protected $vipnumber;
}
Add a getter and a setter. Now you create your own FrontendUserRepository and extend the extbase one like you did with the model. You use this repository in your Controller. Now you're almost there: Tell Extbase via typoscript, that your model is using the fe_users table and everything should work:
config.tx_extbase {
persistence{
Tx_MyExt_Domain_Model_FrontendUser{
mapping {
tableName = fe_users
}
}
}
}
To disable storagePids in your repository in general, you can use this code inside your repository:
/**
* sets query settings repository-wide
*
* #return void
*/
public function initializeObject() {
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($querySettings);
}
After this, your Querys will work for all PIDs.
I didn't have the opportunity to work with frontend users yet, so I don't know if the following applies in this case:
In a custom table I stumbled uppon the fact, that extbase repositories automatically have a look at the pids stored in each entry and check it against a set storage pid (possibly also the current pid if not set). Searching for a uid usually means you have a specific dataset in mind so automatic checks for other values could logically be ignored which would support your experiences. I'd try to set the storage pid for your extension to the place the frontend users are stored in ts-setup:
plugin.[replace_with_extkey].persistence.storagePid = [replace_with_pid]

Lack of response and typing info in API Explorer

I am using the latest version of Restler v3 (commit 0d79cd8) but I'm having some problems having my Swagger-based UI look the same as in the examples. The two problems I'm noticing are that variable typing and #return objects are not being displayed.
On the Restler site, here's a good example of both of these working:
example
Instead, in my Actions class I get this:
And yet as you can see from definition of the class both type information and a response object is specified:
class Actions {
/**
* LIST action types
*
* List all the action-types available
*
* #url GET /
*/
function list_actions() {
throw new RestException(501);
}
/**
* GET today's Actions
*
* Get the set of actions done today
*
* #url GET /{user_id}
* #param integer $user_id The user_id for whom the actions apply; you can insert the text "self" and it will resolve to the current/default user
* #param string $time_of_day {#from url} Allow's you to optionally set a time-of-day; if set then actions are only returned after that. Time should be in the format of HH:MM:SS
* #return ActionList
*/
public function action_today ($user_id, $time_of_day = false )
{
throw new RestException(501, "Today's actions for user '{$user_id}' not implemented.");
}
and my definition of ActionList class is:
class ActionList {
/**
* Unique identifier of action
*
* #var integer
*/
public $action_id;
/**
* String based unique identifier
*
* #var string
*/
public $action_slug;
}
If your class is versioned, e.g. in the namespace v1\Actions, you have to annotate the return type in the namespace too, e.g. #return v1\ActionList